Nabend zusammen, ich habe heute den ganzen Tag damit verbracht mit einem ATMega644 ein paar Zeichen an die serielle Schnittstelle zu senden. Ich benutze die lib von Peter Fleury. Atmega läuft, nein, lief mit 12MHz. Dann mal mit 8MHz und jetzt wieder 12. Terminalprogramm war TeraTerm. Mit dem habe ich bislang immer gute Erfahrungen gemacht. Naja jedenfalls wollte ich einen String ("Hallo") und ein Zeichen ('C') senden. Der PC hat immer etwas empfangen. Im Atmega war als Baudrate 9600 eingestellt. Im Terminal auch aber da kamen nur wirre Zeichen. Stelle ich nun im Terminal auf 14400 baud dann kam etwas in dieser Art an: H#--*C Fast richtig! :) Nunja, ich habe wie gesagt den ganzen Tag rumprobiert. Einen 8MHz Quarz genommen, Fuses tausendmal gecheckt. Nichts!! Eben lud ich mir dann mal ein anderes Terminalprogramm runter und siehe da: Mein String und mein Zeichen kommen in Klartext an!!! JUHU Aber: Atmega=9600 Baud, Terminal=14400 Baud Frage: Warum bekomme ich bei gleicher Baudrate nur Müll angezeigt? Ich habe wie gesagt mehrere Frequenzen schon durch, mehrere Baud Berechnungen und nie hat es geklappt. Frage 2: Trotz ungleicher Baudraten sehe ich meine gesendeten Sachen nicht mit TeraTerm sondern nur mit Putty oder HTerm. Warum?? Einstellungen sind die gleichen! Und ja, https://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART kenne ich. Und nein, CKDIV8 ist nicht gesetzt.
Vielleicht hast du den Quarz mit falschen Kondensatoren belastet. Steckbrett?
9600:8MHzx12MHz=14400 Du hast nicht zufällig die Baudrate für 8MHz betechnet und mit 12MHz laufen lassen?
Ne... Platine. Naja hab 22pF. Konnte zwar nicht mit einem Oszi messen aber Quarz sollte laufen. Da hängt noch ein LCD dran und 2 serielle ICs. Also das läuft alles soweit. Mich wundert es halt nur, dass der String korrekt gesendet wird aber mit unterschiedlichen Baudraten und mit ausgewählten Terminal Programmen.
Zeig doch bitte mal deinen Code - zumindest mal das USART Init. Da HTerm auch unter Win10 völlig problemlos funktioniert, kann ich dir das nur ans Herz legen. Ist für Entwickler, die irgendwas mit UART oder USB Serial zu tun haben, m.M.n. das universellste, was es gibt.
Jürgen schrieb: > 9600:8MHzx12MHz=14400 > Du hast nicht zufällig die Baudrate für 8MHz betechnet und mit 12MHz > laufen lassen? Mh... eigentlich nicht. Hatte vorher ja alles auf 12MHz laufen und beim 8MHz die Berechnung neu gemacht. Jetzt läuft er wieder mit 12MHz. 9600 im Atmeg und 14400 im Terminal
Max B. schrieb: > Hatte vorher ja alles auf 12MHz laufen und beim 8MHz die Berechnung neu > gemacht. > Jetzt läuft er wieder mit 12MHz. Da frage ich mich doch wie du die Änderungen auf die jeweils andere Frequenz bewirkt hast. Denn so wie du dich gibst hast du da womöglich Fehler gemacht.
1 | void uart_init(unsigned int baudrate) |
2 | {
|
3 | UART_TxHead = 0; |
4 | UART_TxTail = 0; |
5 | UART_RxHead = 0; |
6 | UART_RxTail = 0; |
7 | |
8 | #if defined( AT90_UART )
|
9 | /* set baud rate */
|
10 | UBRR = (unsigned char)baudrate; |
11 | |
12 | /* enable UART receiver and transmmitter and receive complete interrupt */
|
13 | UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN); |
14 | |
15 | #elif defined (ATMEGA_USART)
|
16 | /* Set baud rate */
|
17 | if ( baudrate & 0x8000 ) UART0_STATUS = (1<<U2X); //Enable 2x speed |
18 | UBRRH = ((unsigned char)(baudrate>>8))&0x80; |
19 | UBRRL = (unsigned char) baudrate; |
20 | |
21 | /* Enable USART receiver and transmitter and receive complete interrupt */
|
22 | UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN); |
23 | |
24 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
25 | #ifdef URSEL
|
26 | UCSRC = (1<<URSEL)|(3<<UCSZ0); |
27 | #else
|
28 | UCSRC = (3<<UCSZ0); |
29 | #endif
|
30 | |
31 | #elif defined (ATMEGA_USART0 )
|
32 | /* Set baud rate */
|
33 | if ( baudrate & 0x8000 ) UART0_STATUS = (1<<U2X0); //Enable 2x speed |
34 | UBRR0H = ((unsigned char)(baudrate>>8))&0x80; |
35 | UBRR0L = (unsigned char) baudrate; |
36 | |
37 | /* Enable USART receiver and transmitter and receive complete interrupt */
|
38 | UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0); |
39 | |
40 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
41 | #ifdef URSEL0
|
42 | UCSR0C = (1<<URSEL0)|(3<<UCSZ00); |
43 | #else
|
44 | UCSR0C = (3<<UCSZ00); |
45 | #endif
|
46 | |
47 | #elif defined ( ATMEGA_UART )
|
48 | /* set baud rate */
|
49 | if ( baudrate & 0x8000 ) UART0_STATUS = (1<<U2X); //Enable 2x speed |
50 | UBRRHI = ((unsigned char)(baudrate>>8))&0x80; |
51 | UBRR = (unsigned char) baudrate; |
52 | |
53 | /* Enable UART receiver and transmitter and receive complete interrupt */
|
54 | UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN); |
55 | |
56 | #endif
|
57 | |
58 | }/* uart_init */ |
Und hier die defines für die Baudrate:
1 | /** @brief UART Baudrate Expression
|
2 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
|
3 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
|
4 | */
|
5 | #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
|
6 | |
7 | /** @brief UART Baudrate Expression for ATmega double speed mode
|
8 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
|
9 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
|
10 | */
|
11 | #define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)
|
Max B. schrieb: > 9600 im Atmeg und 14400 im Terminal > Jetzt läuft er wieder mit 12MHz. 14400B / 9600B = 1,5 12Mhz / 8Mhz = 1.5 Komisch, nicht wahr? Kaum zu fassen...
:
Bearbeitet durch User
Max B. schrieb: > Und hier die defines für die Baudrate: Nein, ich würde gern wissen wie du das Einstellen der 8MHz bzw 12MHz erreicht hast.
So, danke... ich hab's! Aus:
1 | #define baudrate 9600
|
mach:
1 | #define baudrate 9600UL
|
und jetzt läuft es mit gleicher Baudrate und auch mit TeraTerm. Kann mir einer sagen warum? Ich habe jetzt ganz oft beide Möglichkeiten gesehen aber mir nichts dabei gedacht das mal auszuprobieren.
Max B. schrieb: > Kann mir einer sagen warum? Du redest nicht mit jedem der dir helfen will ... ... heute keine Bauernsprechstunde, wa? Nur weiter so!
Beo Bachta schrieb: > Max B. schrieb: >> Kann mir einer sagen warum? > > Du redest nicht mit jedem der dir helfen will ... > ... heute keine Bauernsprechstunde, wa? > > Nur weiter so! Doch, schon. Aber ich habe mir meine Frage gerade schon selber beantwortet. Bei den 12MHz sollte das UL hinter die Baudrate um den Überlauf zu umgehen. Warum das aber bei 8MHz nicht geklappt hat weiß icj nicht. Und die MHz hab ich auch schön in Hz angegeben.
Ich hatte das mit dem unsigned Long einfach nicht mehr auf dem Schirm, da viele Beiträge und Tutorials mit weniger MHz beschrieben sind.
Max B. schrieb: > Doch, schon. > Aber ich habe mir meine Frage gerade schon selber beantwortet. > Bei den 12MHz sollte das UL hinter die Baudrate um den Überlauf zu > umgehen. Damit steht fest dass du nichts von dem verstanden hast was ich gefragt habe.
Beo Bachta schrieb: > Max B. schrieb: >> Doch, schon. >> Aber ich habe mir meine Frage gerade schon selber beantwortet. >> Bei den 12MHz sollte das UL hinter die Baudrate um den Überlauf zu >> umgehen. > > Damit steht fest dass du nichts von dem verstanden hast was > ich gefragt habe. Okay...
Ich würde empfehlen, die Datei setbaud.h zu benutzen: https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html Dann können solche Dinge nicht schief gehen.
Stefan ⛄ F. schrieb: > Ich würde empfehlen, die Datei setbaud.h zu benutzen: > > https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html > > Dann können solche Dinge nicht schief gehen. Danke für den Tipp! Die kannte ich gar nicht.
Einige "Wenns" Wenn Du den Quarz richtig zappeln lässt - also den richtigen Quarz und die richtigen Kondensatoren verwendest. Wenn Du die Fuses (Quarztyp) richtig eingestellt hast. Auch der DIV8 sollte stimmen! Wenn Du die Teilerfaktoren passend zum Quarz richtig eingestellt hast. Wenn die zur seriellen Schnittstelle gehörigen Register richtig initialisiert wurden. Das ist ein ganzer Haufen. Es kann natürlich nicht schaden, wenn der Quarz nach dem 3-ten Mal herunterfallen auf die Fliesen noch lebt und der Prozessor den Überschlag beim letzten Anfassen überlebt hat. Eins ist nämlich sicher: Hätte der Chip einen internen Fehler, so hätte sich das längst herumgesprochen. Ist nämlich schon etliche Jahre auf dem Markt.
Wenn ich so ein Problem habe (lange nicht mehr passiert), dann lasse ich im Sekundentakt einen Piezo piepsen und hole mir eine Uhr mit Sekundenzeiger auf den Bildschirm. Wenn synchron, dann gut. https://www.uhrzeit.org/atomuhr.php
Max B. schrieb: > So, danke... ich hab's! > > Aus: > > #define baudrate 9600 > > mach: > > #define baudrate 9600UL > > und jetzt läuft es mit gleicher Baudrate und auch mit TeraTerm. > Kann mir einer sagen warum? Das UL ist hier nicht erforderlich, da die Makros UART_BAUD_SELECT und UART_BAUD_SELECT_DOUBLE_SPEED bereits dafür sorgen, dass die Berechnung der Baudrate in long erfolgt. Vermutlich hat aber erst diese Änderung bewirkt, dass das Programm neu kompiliert wurde. Die Änderung von F_CPU im Makefile führt nur dann zur Neukompilierung, wenn nicht nur die C-Quelldateien, sondern auch das Makefile selbst in den Make-Regeln berücksichtigt wird. Mach im Zweifelsfall einfach
1 | make clean |
2 | make |
(wenn dein Makefile ein clean-Target hat) oder lösche alle kompilierten Dateien, um eine vollständige Neukompilierung zu erzwingen. Noch etwas:
1 | UBRRH = ((unsigned char)(baudrate>>8))&0x80; |
2 | ...
|
3 | UBRR0H = ((unsigned char)(baudrate>>8))&0x80; |
4 | ...
|
5 | UBRRHI = ((unsigned char)(baudrate>>8))&0x80; |
Das ist ein Bug. Da müsste statt 0x80 jeweils ~0x80 oder besser 0x0f stehen. Da der Fehler nur bei niedrigen Baudraten in Erscheinung tritt, ist wohl noch kaum jemand darüber gestolpert. Das von Stefan vorgeschlagene setbaud.h aus der AVR-Libc funktioniert auch mit niedrigen Baudraten. Zudem wird dort eine Warnung ausgegeben, wenn eine bestimmte Baudrate nicht oder nur mit unzureichender Genauigkeit umgesetzt werden kann. Edit: Ich sehe gerade, dass der o.g. Bug auch schon anderen aufgefallen ist: Beitrag "Fehler in uart-lib von Peter Fleury?"
:
Bearbeitet durch Moderator
Yalu X. schrieb: > Das ist ein Bug. Da müsste statt 0x80 jeweils ~0x80 oder besser 0x0f > stehen. Sehr guter Hinweis! Müsste es aber dann nicht "besser 0x7f" heißen? Okay, es könnte sein, dass die 3 Bits im oberen Nibble keine Bewandnis haben, da müsste ich das Datenblatt mal heranziehen...
:
Bearbeitet durch Moderator
Yalu X. schrieb: > Das UL ist hier nicht erforderlich, da die Makros UART_BAUD_SELECT und > UART_BAUD_SELECT_DOUBLE_SPEED bereits dafür sorgen, dass die Berechnung > der Baudrate in long erfolgt. Da bin ich aber erleichtert. Ich habe nämlich gestern eine halbe Stunde darüber gegrübelt und konnte mir nicht erklären, warum das "UL" nötig sein sollte.
Ja ich hatte gestern noch testweise eine andere UART Init im Programm. Deswegen habe ich mir die von Peter nicht mehr angeguckt. Es läuft aber jetzt. Habe auch den Bug behoben in der Init. Läuft jetzt einwandfrei! Danke nochmal an Alle!
Frank M. schrieb: > Okay, es könnte sein, dass die 3 Bits im oberen Nibble keine Bewandnis > haben, da müsste ich das Datenblatt mal heranziehen... Diese Bits sind "reserved" und sollten nur mit 0 beschrieben werden.
Yalu X. schrieb: > Frank M. schrieb: > Okay, es könnte sein, dass die 3 Bits im oberen Nibble keine Bewandnis > haben, da müsste ich das Datenblatt mal heranziehen... > > Diese Bits sind "reserved" und sollten nur mit 0 beschrieben werden. Okay, dann wäre ~0x80 sogar falsch. Danke fürs Nachschauen :-)
:
Bearbeitet durch Moderator
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.