Hallo Ich versuche gerade den uart aus dem Tuto. Funzt alles soweit, nur wenn ich am pc einen buchstaben sende empfange ich im AVR erst beim zweiten senden des Buchstabens den Richtigen. So sieht mein Code aus: int zeichen (void){ for (;;){ fdevopen (uart_transmitt,NULL,0); printf("Bitte Befehl eingeben "); uart_getc(); if (UDR != 's'&& UDR !='w'){ printf("Falsche Eingabe!"); } if (UDR == 's'){ printf("Motor Stop "); for(int h = 0; h< 20; h++){ _delay_ms(20);} printf("Bitte Befehl eingeben! "); } if (UDR == 'w'){ printf("Motor an!"); } for(int h = 0; h< 20; h++){ _delay_ms(20);} } return(0);} Uns so empfange ich: /* Zeichen empfangen */ int uart_getc(void) { while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben }
Puh, das ist hard stuff! UDR kannst du nicht beliebig oft abfragen. Nach dem Abfragen wird es nämlich gelöscht! Die Abfrage muss an einer Stelle zentral erfolgen; die Routine dafür hast du schon: uart_getc
1 | /* Zeichen empfangen */
|
2 | unsigned char uart_getc(void) |
3 | {
|
4 | while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar |
5 | return UDR; // Zeichen aus UDR an Aufrufer |
6 | // zurueckgeben
|
7 | }
|
8 | |
9 | int zeichen (void) |
10 | {
|
11 | unsigned char zeichen; |
12 | |
13 | fdevopen (uart_transmitt,NULL,0); |
14 | |
15 | for (;;) |
16 | {
|
17 | printf("Bitte Befehl eingeben "); |
18 | zeichen = uart_getc(); |
19 | |
20 | switch (zeichen) |
21 | {
|
22 | case 's': |
23 | case 'S': |
24 | printf("Motor Stop "); |
25 | for(int h = 0; h< 20; h++) |
26 | _delay_ms(20); |
27 | break; |
28 | |
29 | case 'w': |
30 | case 'W': |
31 | printf("Motor an!"); |
32 | for(int h = 0; h< 20; h++) |
33 | _delay_ms(20); |
34 | break; |
35 | |
36 | default:
|
37 | printf("Falsche Eingabe!"); |
38 | break; |
39 | }
|
40 | }
|
41 | // wird wegen for(;;) nie erreicht!
|
42 | return 0; |
43 | }
|
Und wo laeuft das Program ? Aufm AVR ? Aha. Was ist wenn solcher Mist wie printf() laenger dauert wie ein Zeichen zu empfangen ? Printf() gehoert da sowieso nicht hin. Mach was anderes ... zB einen Pin wackeln und mit'm Scope anschauen.
Hallo Danke für Hilfe! Wieso wird case'w' z.B. zweimal hingeschrieben? Ich habe uart_getc doch auch nur am Anfang einmal aufgerufen?? Aber komischerweise gehts mit deinem Code. Kannst Du mir das nochmal erklären. Frank
case 'w': case 'W': Ist ein Zusatzfeature. Wenn du mal im Sendeprogramm aus Versehen CAPSLOCK eingeschaltet hast, funktionieren dann die Befehle mit Grossbuchstaben auch. Jedes Lesen von UDR in deinem Code ist eigentlich eine Abfrage des UART. Aber du machst das öfters, ohne dass wie in uart_getc gewartet wird, bis ein Zeichen vorhanden ist. D.h. es kann (und wird) passieren, dass du im if das UDR ausliest, wenn gerade ein "halbes" Zeichen in UART steht. Du bekommst dadurch Unsinn für deinen Programmablauf geliefert und - schlimmer - du löschst das halbe Zeichen und verstümmelst das nächste Zeichen mit dem Rest der "noch in der Leitung steckt". Einmal lesen, der Variable zeichen zuweisen und dann zeichen auswerten. Für später, wenn du fitter im Programmieren bist, im Hinterkopf behalten: Die Auswertung darf auch nicht zu lange dauern, weil der UART wenige (je nach µC) Zeichen zwischenpuffern kann. Wenn zu selten abgefragt wird (400ms Warten ist für µC/UART eine Ewigkeit), gehen Zeichen verloren, wenn der Puffer voll ist. Man kann da durch interruptgesteuerte UART-Abfragen und grössere Puffer (Ringpuffer) besser programmieren.
Achso, jedem if (UDR == ... Aufruf frage ich den Uart ab.Dann hätte ich ja im meinem Code nur UDR in eine andere Variable schieben müssen und diese abfragen, dann wärs gegangen. Vielen Dank
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.