Forum: Mikrocontroller und Digitale Elektronik ATMega UART init und senden


von René K. (tesla24)


Lesenswert?

Hallo liebe Gemeinde,

tut mir schon leid dass ich damit komme, aber ich sehe wohl den Wald vor 
lauter Bäumen nicht? Hatte jetzt ein paar Jahre Programmierpause und 
jetzt bekomme ich UART am ATMega644A nicht zum laufen. (Init und senden) 
ich habe die Suche schon durch und auch das Datenblatt.

Es wird was gesendet (gemessen mit einem DSO mit Decoder) aber viel zu 
wenig und auch falsch.

Den Takt habe ich auf den Pin ausgeben lassen und gemessen, es sind die 
eingestellt und eingetragenen 8 Mhz.

Die Einstellung soll 9600 Baud (8,n,1) sein, zur Berechnung beutze ich 
setbaud.h

Hier meine init:

#define F_CPU 8000000UL
#define BAUD 9600UL

#include <util/setbaud.h>

void serial_init()
}
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
    UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00); //8,n,1
}


und hiermit sende ich in einem timer Interrupt ca. 3Hz

ISR(TIMER0_OVF_vect) //
{

  //cli(); //weitere Interrupts deaktivieren

  PORTB ^= (1<<PB0);  // Toggelt den Ausgänge an PORTB0

        while(!(UCSR0A & (1<<UDRE0)));

        UDR0=48;


  //sei(); //alle Interrupts wieder aktivieren
}

Vielen Dank im voraus !

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

Das vollständige Programm vorzustellen wäre sinnvoll gewesen.
Was passiert, wenn Sie statt dieses "setbaud" den Wert aus dem 
Datenblatt, nämlich 51, nehmen?

von René K. (tesla24)


Lesenswert?

Danke für die Antwort!

Ich habe auch schon den Zahlenwert direkt eingetragen aber es ändert 
nichts.

Um das Problem zu isolieren habe ich jetzt ein Programm wo ich nur immer 
wieder was über die Schnittstelle raus schicke.

Ich bin so langsam am verzweifeln. Am DSO wird der Pin geschaltet, aber 
immer nur ein-zwei lange Flanken und nie die kompletten Daten mit 8,n,1

1
#define F_CPU 8000000UL
2
#define BAUD 9600UL
3
4
#include <avr/io.h>
5
#include <util/setbaud.h>
6
#include <util/delay.h>
7
8
9
void uart_init(void)
10
{
11
  UBRR0L = UBRRL_VALUE;
12
  UBRR0H = UBRRH_VALUE;
13
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
14
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00); //8,n,1
15
}
16
17
18
int main(void)
19
{
20
  uart_init();
21
    /* Replace with your application code */
22
    while (1) 
23
    {
24
    while(!(UCSR0A & (1<<UDRE0)))
25
    {
26
      
27
    }
28
    UDR0 = "42";
29
    
30
    _delay_ms(100);
31
    }
32
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

René K. schrieb:
> UDR0 = "42";

Das ist Quark.

In UDR0 muss ein einzelnes Zeichen und kein String übergeben werden.

Schreibe also:
1
void putc (uint8_t ch)
2
{
3
    while(!(UCSR0A & (1<<UDRE0)))
4
    {
5
        ;
6
    }
7
    UDR0 = ch;
8
}
9
10
int main(void)
11
{
12
    uart_init();
13
14
    while (1) 
15
    {
16
        putc ('4');
17
        putc ('2');
18
        _delay_ms(100);
19
    }
20
}

Das Schreiben einer Funktion puts(), die einen String wie "42" ausgeben 
kann, überlasse ich jetzt einmal Dir.

: Bearbeitet durch Moderator
von Bernd N (Gast)


Lesenswert?

Versuch mal...
1
void UartInit (void)
2
{
3
    UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);        // UART TX einschalten
4
    UCSR0C |= (3 << UCSZ00);                                      // Asynchron 8N1
5
    UBRR0H = UBRR_VAL >> 8;                                       // Baudrate setzen
6
    UBRR0L = UBRR_VAL & 0xFF;
7
}

von S. Landolt (Gast)


Lesenswert?

an René K.

Also bei mir läuft das (mit UDR0='L';).
Vielleicht eine Fehlinterpretation der DSO-Ausgabe.

von René K. (tesla24)


Angehängte Dateien:

Lesenswert?

Ich habe auch das Gefühl das am DSO liegt, aber ich habe alles schon zig 
mal durchgeschaut....

Aber selbst wenn das DSO nicht richtig decodiert, dann müsste ich doch 
dennoch die 8n1 sehen wenn ich ein Zeichen sende. oder ?

Hier nochmal der aktuelle Code:
1
#define F_CPU 8000000UL
2
#define BAUD 9600UL
3
4
#include <avr/io.h>
5
#include <util/setbaud.h>
6
#include <util/delay.h>
7
#include <stdio.h>
8
9
10
11
12
void uart_init(void)
13
{
14
  //UBRR0L = UBRRL_VALUE;
15
  //UBRR0H = UBRRH_VALUE;
16
  //UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
17
  //UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00); //8,n,1
18
  
19
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);  // UART TX einschalten
20
UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00);                    // Asynchron 8N1
21
UBRR0H = (UBRR_VALUE>>8);                               // Baudrate setzen
22
UBRR0L = (UBRRL_VALUE & 0xff);
23
}
24
25
26
27
int main(void)
28
{
29
  uart_init();
30
31
    while (1) 
32
    {
33
           while(!(UCSR0A & (1<<UDRE0)))
34
    {
35
        
36
    }
37
    UDR0 = 'L';
38
    
39
    _delay_ms(10);
40
    }
41
}

von S. Landolt (Gast)


Lesenswert?

Tja, auch Ihr aktuelles Programm läuft bei mir einwandfrei.
  Der Watchdog ist ja sicher ausgeschaltet, sonst hätten Sie nicht die 8 
MHz verifizieren können, wie eingangs geschildert.

von S. Landolt (Gast)


Lesenswert?

Jetzt bin ich irritiert, in dem Bild sehe ich doch ein 4C == 'L'!?

von René K. (tesla24)


Lesenswert?

Es funktioniert mit dem einzelnen Zeichen... so was blödes: LSB first 
und am DSO war MSB first.

Aber irgendwie hatte ich das mit den Bits anders in Erinnerung...

Jetzt hoffe ich das ich den anderen Kram noch hinbekomme. Ich muss einen 
String basteln (nur Zahlen) und der soll zyklisch übertragen werden. 
Dieser setzt sich dann aus mehreren Variablen zusammen.

Danke für eure Hilfe bis hierhin!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.