Forum: Mikrocontroller und Digitale Elektronik ATMega32A UART läuft mit falschem Clock


von Star K. (starkeeper)


Angehängte Dateien:

Lesenswert?

Hi,
ich habe Probleme mit der UART von einem ATMega32. Ich habe den 
Hardwareaufbau sowie die Software aus folgendem Thread genommen:
http://embdev.net/topic/158895

Ansich sollen Software und Hardware wunderbar harmonieren, nur leider 
tun sie das bei mir nicht.

Es handelt sich um einen ATMega32A der extern mit einem 10MHz Clock 
versorgt wird. Es ist also kein Quarz angeschlossen sondern ein 
Taktgeber. Die UART soll mit 38400 baud senden. Ich kann mit dem 
Logikanalyser erkennen, dass der Controller auch regelmäßig Daten 
sendet. Leider sind diese aber so langsam, dass der PC sie nicht 
erkennt. Ich habe mal einen Screenshot des Logikanaylzers angehängt. Auf 
der TXD leitung sendet der ATMega, auf der RXD Leitung sendet ein FTDI 
der am PC hängt.

Die Fuses für den ATMega32A stehen auf:
Low: 0xA0
High: 0x91

Die Einstellung für den Clock sollte mit diesen Fuses korrekt sein und 
ein externer clock genutzt werden. Dennoch stimmt die UART 
Geschwindigkeit nicht.

Mit folgender Formel wird im Code die Baudrate von 38400 eingstellt:
ubrr_val = ((10000000)/(38400*8L)-1);

Wo liegt nun der Fehler? Oder was kann noch schief laufen und den Fehler 
verursachen?

von Stefan E. (sternst)


Lesenswert?

Wenn ich die im Screen-Shot zu sehende Baudrate zurück rechne, dann 
komme ich auf einen Wert von 6 für UBRRH. Da hat dann wohl jemand URSEL 
nicht (korrekt) benutzt.

von Star K. (starkeeper)


Lesenswert?

Also ich kenne mich mit den Eigenarten von ATMega's nicht aus. Da muss 
ich mal ins Datenblatt schauen wozu das Bit da ist.

Der Code ist wie gesagt nicht von mir und soll angeblich funktionieren. 
Hier mal die komplette Sequenz mit der die UART initialisiert wird:
1
uint16_t ubrr_val = ((10000000)/(38400*8L)-1);
2
UCSR0A = _BV(U2X0);
3
UBRR0H = (unsigned char)(ubrr_val>>8);
4
UBRR0L = (unsigned char)(ubrr_val & 0xFF);
5
UCSR0C = (1<<URSEL0) | (_BV(UCSZ00) | _BV(UCSZ01));
6
UCSR0B = _BV(RXCIE0) | _BV(RXEN0);

von Stefan E. (sternst)


Lesenswert?

Star Keeper schrieb:
> Hier mal die komplette Sequenz mit der die UART initialisiert wird

Sicher nicht, denn da wird der Transmitter ja überhaupt nicht 
eingeschaltet. Wenn das wirklich die echte "komplette Sequenz" wäre, 
würde überhaupt nichts aus dem TXD-Pin kommen.

von Star K. (starkeeper)


Lesenswert?

Jo stimmt das ist etwas komisch gemacht, das TXEN0-Bit wird erst in der 
Sende-Funktion in das Register geschrieben...

Ich konnte mein Problem mitlerweile auch lösen, in dem ich die Bausrate 
erst an letzter Stelle setze. Also folgendermaßen:
1
uint16_t ubrr_val = ((10000000)/(38400*8L)-1);
2
UCSR0A = _BV(U2X0);
3
UCSR0C = (1<<URSEL0) | (_BV(UCSZ00) | _BV(UCSZ01));
4
UCSR0B = _BV(RXCIE0) | _BV(RXEN0);
5
6
UBRR0H = (unsigned char)(ubrr_val>>8);
7
UBRR0L = (unsigned char)(ubrr_val & 0xFF);

Das muss mal einer verstehen, zumal im Datenblatt die andere Reihenfolge 
drin steht.

von Spess53 (Gast)


Lesenswert?

Hi

>Das muss mal einer verstehen, zumal im Datenblatt die andere Reihenfolge
>drin steht.

Das wird eigentlich über das URSEL-Bit geregelt. UCSRC und UBRRH teilen 
sich die gleiche IO-Adresse. Bei gesetztem URSEL-Bit wird auf UCSRC 
zugegriffen und bei gelöschtem auf UBRRH.

Was mich etwas wundert: Das Datenblatt des ATMega32A kennt z.B. kein 
UCSR0A, sondern nur UCSRA. Bei den anderen Registern und Bitbezeichnern 
das gleiche.

MfG Spess

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.