Hallo Männers, ich habe hier entweder einen bockigen MEGA162 vor mir, oder einen Bug ausgegraben. Fakt ist, das die Datenübertragung mit USART0 nicht oder nur teilweise geht. Die Receive-Interrupts werden ordnungsgemäß ausgelöst und auch ist ein Empfang da. Aber leider kommt nur Datenmüll an! Ich habe jetzt eine Parametrierung vorgenommen und dabei ist mir aufgefallen, dass der Befehl: UCSR0C |= ((1<<URSEL0)|(1<<UCSZ01)|(1<<UCSZ00)); zwar durch den Compiler läft, aber keinen Effekt (gesetzte Bits) im Debugger zeigt! auch der Befehl aus dem Tutorial => UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1 wird verweigert (Compilerfehler), da UCSZ0 so nicht ansprechbar sein soll. Hat jemand von Euch eine Idee, wie ich dem Kollegen plausibel machen kann, dass ich 8Datenbits haben will? Das gleiche Programm läuft mit einem MEGA128 ohne Probleme! vielen Dank! Ulf
Lass das Register in Ruhe. 8N1 ist die Voreinstellung. Das C-Register ist bei einigen AVRs doppelt belegt und lässt sich dann nicht einfach zurücklesen (weil du stattdessen das UBRRxH liest).
Schau mal in iom162.h nach, wie die Register und bits dort heissen. Dann klappts auch mit dem Compiler. Allerdings: Warum heissen die Register dort anders, als im Datenblatt? Oliver
Hallo, @Jörg: ok ist klar, aber: ich muss ja irgendwie die Übertragungsrate einstellen. Das heißt in meinem Fall bei 16 MHz Takt und 19,2 kbps => einen Teiler von 51 in UBRR. laut Datenblatt geht das bei UBRRxH so => /* Set UBRRH to 2 */ UBRRH = 0x02; ... bei mir dann analog => UBRR0H = 0x00; wobei hier die 0 für USART0 steht. Soweit so gut. Der Compiler läuft durch, aber im Debugger bekomme ich keine Rückmeldung, ob die Bits geschrieben sind. Ist das normal? Wenn ich testweise UBRR0H mit 0x02 fülle, sollte ich doch im Debugger (I/O-Viev) etwas sehen, oder? Noch eine Frage zum UDR-FiFo. Wird jedesmal wenn ich das UDR auslese der Inhalt weitergeschoben? Es sollte ja, oder?. Wird der RXCIE nach jedem empfangenem Byte ausgelöst oder erst wenn 2 Byte da sind? Muss ich dann das UDR 2x in der ISR auslesen? Das gleiche Programm läuft im mega128 problemlos! Bei dem hier habe ich den Eindruck, das jedes 2. Zeichen verschwindet, zumindest bekomme ich nur noch sehr hohe ASCII-Werte, obwohl ich zum großen Teil Zahlen (Ziffern 0-9) übertrage! Naja, langsam glaube ich an den Weihnachtsmann, und das Datenblatt kann ich bald rezitieren. Vielleicht sieht nach einem Bier und ein paar Stunden Schlaf die Welt wieder freundlicher aus.... Gute Nacht ! Ulf
Hallo, also, dieser Code läuft bei mir auf dem 162
1 | #define F_CPU (deine Quarzfrequenz) // Beispiel: #define F_CPU 14745460
|
2 | |
3 | void uart0_init(int BaudRate) |
4 | {
|
5 | int ubrr0 = (F_CPU / 16 / BaudRate - 1); // Baudrate UART0 einstellen |
6 | UBRR0H = (unsigned char)(ubrr0>>8); |
7 | UBRR0L = (unsigned char)ubrr0; |
8 | |
9 | UCSR0C = (1<<URSEL0)|(3<<UCSZ00); // UART0 Frame Format einstellen: 8data, 1 Stop-bit, keine Parity |
10 | UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1 << RXCIE0); // UART0 Receiver und Transmitter einschalten |
11 | }
|
12 | |
13 | void uart1_init(int BaudRate) |
14 | {
|
15 | int ubrr1 = (F_CPU / 16 / BaudRate - 1); // Baudrate UART1 einstellen |
16 | UBRR1H = (unsigned char)(ubrr1>>8); |
17 | UBRR1L = (unsigned char)ubrr1; |
18 | |
19 | UCSR1C = (1<<URSEL1)|(3<<UCSZ10)|(1<<UPM11); // UART1 Frame Format einstellen: 8data, 1 Stop-Bit, even Parity |
20 | UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); // UART1 Receiver und Transmitter einschalten |
21 | }
|
22 | |
23 | int main() // Hauptprogramm |
24 | |
25 | {
|
26 | sei(); // Interrupts einschalten |
27 | |
28 | uart1_init(9600); // USART's initialisieren (Baudrate auf 9600 ) |
29 | uart0_init(9600); |
30 | |
31 | // tu was
|
32 | |
33 | cli(); |
34 | return 0; |
35 | }
|
Achtung! die CKDIV8-Fuse ausschalten.... Gruß Udo
Hallo, danke Udo!! Wobei, der springende Punkt war nicht die Initialisierung sondern: Achtung! die CKDIV8-Fuse ausschalten.... ;-) Hab ich irgendwie bei der Portierung nicht gesehen!!! Aber, irgendwie läuft das jetzt nur teilweise! Die Datenübertragung funktioniert im Grunde, aber der µC liest nur Mist ein. D.h. es werden nicht alle Daten erkannt! Ich habe gerade mit meinem Digiview das Datenpaket gecheckt => ist i.O.! Also bis zum USART-in im mega162 ist alles paletti. Ich habe alle Takteinstellungen nochmals gecheckt, noch irgend welche verborgenen Teiler gesucht..... Hat jemand noch eine Idee woran das liegen könnte?? Danke!! Ulf
Hallo, UCSR0C |= ((1<<URSEL0)|(1<<UCSZ01)|(1<<UCSZ00)); bei einer OR-Verknüpfung muß erst das Register gelesen werden, dann verknüpft und wieder geschrieben. Es wird aber nicht das Control-Register gelesen, sondern immer das Statusregister! Solche Zugriffe nie verknüft machen, sonder direkt den Wert schreiben. Also USR0C = ((1<<URSEL0)|(1<<UCSZ01)|(1<<UCSZ00)); Wenn noch mehr zu setzen ist, eben da mit dazu. Ich weiß doch, warum mir ASM lieber ist, man ist viel näher an Hardware und am Datenblatt dran. ;-) Gruß aus Berlin Michael
Asterix-007 wrote: > Das heißt in meinem Fall bei 16 MHz Takt und 19,2 kbps => einen Teiler > von 51 in UBRR. Womit du wiederum UBRRH gar nicht erst anfassen musst, da es auf 0 voreingestellt ist. UBRRH muss man nur setzen, wenn man auf relativ schnell getakteten Prozessoren niedrige Baudraten erzielen will. Die allerersten AVR-UARTs hatten dieses Register überhaupt noch nicht. > Soweit so gut. Der Compiler läuft durch, aber im Debugger bekomme ich > keine Rückmeldung, ob die Bits geschrieben sind. > > Ist das normal? Das kann für so ein Doppelregister schon normal sein. Ich nehme an, du redest von JTAG, ja? Wenn überhaupt, dann kannst du nur eins der beiden auf dieser Adresse liegenden Register im Debugger lesen.
Hallo, PROBLEM GELÖST!!!! Also es funktioniert jetzt alles!! Ich glaube das Hauptproblem war der CKDIV8-Fuse! Alles weitere waren Änderungen, welche durch Probieren den Code verändert haben. Also saß letztendlich der Fehler wieder vorm Computer.... Naja, vielen Dank an alle welche sich den Kopf zerbrochen haben. @ Jörg: ja, ich habe mit einem MKII gearbeitet! Allerdings scheint mir, dass der keines der Doppelregister anzeigt wird. Ich habe spasseshalber mal das UBRRH und das UCSR0C mit Werten beschrieben, weder der eine noch der andere war im Debugger zu sehen. die Funktion scheint ja meine Vermutung zu bestätigen, aber noch mal meine Frage: Der UDR auf der Empfangsseite ist ein "2fach-FIFO". Wird jedesmal wenn ich das UDR auslese der Inhalt weitergeschoben? Es sollte ja, oder?. Wird der RXCIE nach jedem empfangenem Byte ausgelöst oder erst wenn 2 Byte da sind? Muss ich dann das UDR 2x in der ISR auslesen? Nach meiner Beobachtung könnte die 2.Speicherstelle zum Puffern gedacht sein, denn die Doppelabfrage funktioniert nicht. Wie siehst du das? Nochmal an alle die sich Gedanken gemacht haben: DANKE!! Ulf
Asterix-007 wrote: > @ Jörg: ja, ich habe mit einem MKII gearbeitet! Allerdings scheint > mir, dass der keines der Doppelregister anzeigt wird. Ja, ich habe mir die IO bitmap im Devicedescriptor des JTAG ICE mkII mal angesehen. Ist richtig, UCSR0C und UCSR1C sind vom Lesen (und Schreiben) des JTAG ICE ausgeblendet. Das ist wohl eine Konsequenz ihres Daseins als Doppelregister. > Der UDR auf der Empfangsseite ist ein "2fach-FIFO". Wird jedesmal > wenn ich das UDR auslese der Inhalt weitergeschoben? Es sollte ja, > oder? Ja, da es ja ein FIFO ist. > Wird der RXCIE nach jedem empfangenem Byte ausgelöst Ja. > Muss ich dann das UDR 2x in der ISR auslesen? Du kannst. Du kannst es aber auch bleiben lassen, dann wird halt der Interrupt sofort wieder ausgelöst, das bringt halt nur ein wenig mehr Overhead.
Hallo, das Datenblatt ist dein Freund: "A second Buffer Register has been added. The two buffer registers operate as a circular FIFO buffer. Therefore the UDR must only be read once for each incoming data!" und "The Receiver Shift Register can now act as a third buffer level. This is done by allowing the received data to remain in the serial Shift Register (see Figure 75) if the Buffer Registers are full, until a new start bit is detected. The USART is therefore more resistant to Data OverRun (DOR) error conditions." und "The Receiver starts data reception when it detects a valid start bit. Each bit that follows the start bit will be sampled at the baud rate or XCK clock, and shifted into the Receive Shift Register until the first stop bit of a frame is received. A second stop bit will be ignored by the Receiver. When the first stop bit is received, i.e., a complete serial frame is present in the Receive Shift Register, the contents of the Shift Register will be moved into the receive buffer. The receive buffer can then be read by reading the UDR I/O location. und "When the Receive Complete Interrupt Enable (RXCIE) in UCSRB is set, the USART Receive Complete Interrupt will be executed as long as the RXC Flag is set (provided that global interrupts are enabled). When interrupt-driven data reception is used, the receive complete routine must read the received data from UDR in order to clear the RXC Flag, otherwise a new interrupt will occur once the interrupt routine terminates. Gruß Udo
Moin, danke für die Antworten, @Jörg: mit der Doppelabfrage habe ich mir eigentlich erst die Probleme geschaffen. D.h. ich habe in der ISR 2x nacheinander das UDR abgefragt. Das Problem bestand dann darin, dass ein 2. Byte gelesen wurde, dieses aber nicht zum Datenstring passte!!!!! Das 2. Byte war definitiv nicht von meiner Quelle gesendet! Woher auch immer dieser 2. Wert kommt ist mir nicht klar! Ich kann das Datenblatt nur so interpretieren, dass der 2. Speicherplatz im FIFO nur als Puffer gedacht ist. In meinem Fall ist es besser auf den nächsten Interrupt zu warten, sonst zerfällt mir mein Datenstring!! @Udo: ja, klar das Datenblatt.... Ich glaube das habe ich die letzten Wochen zur Genüge durch. Und manchmal ist halt nicht mehr alles so klar, wie es bei oberflächlicher Betrachtung zuerst scheint! mfg Ulf
Asterix-007 wrote:
> D.h. ich habe in der ISR 2x nacheinander das UDR abgefragt.
Das darfst du natürlich nur tun, nachdem du zuvor das entsprechende
Interruptflag abgefragt hast um rauszufinden, ob denn auch wirklich
derzeit noch etwas anliegt an Daten.
Hallo Ulf, sorry, war nicht so negativ gemeint wie es vielleicht rüber gekommen ist. Ich habe die Erfahrung gemacht, dass je öfter ich das Datenblatt gelesen habe, desto mehr kam ich dahinter, was die Verfasser eigentlich gemeint haben. > Das darfst du natürlich nur tun, nachdem du zuvor das entsprechende > Interruptflag abgefragt hast um rauszufinden, ob denn auch wirklich > derzeit noch etwas anliegt an Daten. mmmh, da bin ich anderer Ansicht. Die ISR sollte, wenn das RXC-Flag vom UART gesetzt wird, nur die Daten abholen. Je kürzer die ISR, desto besser, damit das RXC-Flag schnell wieder gelöscht wird. Das RXC-Flag signalisiert der ISR ja, dass wieder neue Daten bereitgestellt sind. Da muß nichts abgefragt werden. Gruß Udo
Udo wrote: > ... Da > muß nichts abgefragt werden. Ja, es muss nicht, aber es kann. Im Falle des FIFO, der mit 2 Zeichen gefüllt ist, spart es dir einen erneuten sofortigen Interrupt mit all seinem Overhead (der wesentlich aufwändiger ist als die Abfrage des Flags).
Hallo, @ Jörg: ich hab natürlich nur auf den Interrupt reagiert und dann 2x gelesen. Wenn ich dich jetzt richtig verstehe hätte ich vor dem 2x lesen das RXC-Flag abfragen sollen. Klingt einleuchtend! @Udo: hab ich auch nicht so aufgefasst. Nur wird man hier sehr oft in einem Tonfall "abgebügelt", der mir sehr missfällt. Jedenfalls war es bei mir so, dass mich das häufige Lesen des Datenblattes mehr verwirrt hat als aufgeklärt. Gerade in einem solchen speziellen Fall. Aber inzwischen ist ja der Sachverhalt geklärt!!! Vielen Dank! Ulf
Hallo Jörg, aber das RXC-Flag wird ja erst dann gesetzt, wenn ein komplettes Byte in den Teil des FIFO's, das als UDR-Register bezeichnet ist, gelangt ist. Das passiert aber erst dann, wenn aus dem Shiftregister wieder Daten ins FIFO gelangen. Ungünstigenfalls, wenn keine Daten mehr empfangen werden, pollst du in deiner ISR lange auf das RXC-Flag.... Gruß Udo
Udo wrote: > ... Ungünstigenfalls, wenn keine Daten mehr empfangen werden, > pollst du in deiner ISR lange auf das RXC-Flag.... Nee, das natürlich nicht. ;-) Du hast das irgendwie flashc verstanden. Ich würde sowas machen:
1 | ISR(USART0_RXC_vect) |
2 | {
|
3 | do { |
4 | uint8_t c = UDR; |
5 | // process c
|
6 | } while ((UCSR0A & RXC0) != 0); |
7 | }
|
statt einfach nur:
1 | ISR(USART0_RXC_vect) |
2 | {
|
3 | uint8_t c = UDR; |
4 | // process c
|
5 | }
|
(Die endgetestete Schleife absichtlich, da beim ersten Einstieg in die ISR durch einen Interrupt ja das RXC immer gesetzt sein sollte.)
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.