Guten Tag liebe Community, das ist das erste mal dass ich hier etwas poste, ich hoffe ich mach das richtig. Ich sitze gerade an meiner Studienarbeit und hab ein Problem ... Ich sende mit einem ATmega2560 über UART an einen ATmega32A. Gesendet wird mit 8n2. Durch eine LED die ich aktiviere sobald der 32A in den Interrupt springt seh ich dass er etwas empfängt. Aber er empfängt einfach nicht was ich schicke. Daten vom ATmega2560 per UART mit Terminal ausgelesen (ASCII): r108yg109yb42yr107yg108yb41yr106yg107yb40yr105yg106yb39yr104yg105yb38yr1 03yg Code vom 32A der diesen Daten auswerten soll: ........................................................................ . ######################################################################## #include <avr/io.h> #include <inttypes.h> #include <avr/delay.h> #include <avr/interrupt.h> #define F_CPU 8000000UL #define BAUD 115200UL #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1) #define intervall10 "set intervall 10" #define streamon "set stream 1" #define streamoff "set stream 0" void timer2_init() //PWM Rot { TCCR2 |= (1 << COM21)|(1 << WGM20)|(1 << CS22); OCR2 = 230; } void timer1_init() //PWM Grün, Blau { TCCR1A |= (1 << COM1A1)|(1 << COM1B1) |(1<<WGM10); TCCR1B |= (1 << CS11)|(1 << CS10); TCNT1 = 0; OCR1A = 230; OCR1B = 230; } // USART initialisieren void uart_init(void){ UBRRH = (unsigned char)(UBRR_BAUD >> 8); UBRRL = UBRR_BAUD; UCSRA = (1 << UDRE); //Puffer-leer bit setzen UCSRB |= (1<<RXEN)|(1<<RXCIE); //Senden aktivieren UCSRC |= (1<<UCSZ1)|(1<<UCSZ0)|(1<<USBS); //Anzahl Datenbits und Stopbits wählen do { UDR; } while (UCSRA & (1 << RXC)); } #define UART_MAXSTRLEN 100 char uart_string[UART_MAXSTRLEN + 1] = ""; volatile uint8_t uart_str_complete = 0; volatile uint8_t uart_str_count = 0; int Gruen; //Farbwert gelb 0-255 int Blau; //Farbwert blau 0-255 int Rot; //Farbwert rot 0-255 int testcounter = 0; int main(void) { // USART + timer initialisieren uart_init(); timer1_init(); timer2_init(); DDRA |= 0xFFF; DDRD |= (1<<PD6); DDRD |= (1<<PD4); //OC1B DDRD |= (1<<PD5); //OC1A DDRD |= (1<<PD7); //OC2 sei(); do{ if(uart_str_complete == 1){ if(uart_string[0] == 'r'){ memmove(uart_string, uart_string+1, strlen(uart_string)); Rot = atoi(uart_string); OCR2 = Rot; if(Rot > 50){ PORTA |= (1<<PA4); } else{ PORTA &= ~(1<<PA4); } } if(uart_string[0] == 'g'){ memmove(uart_string, uart_string+1, strlen(uart_string)); Gruen = atoi(uart_string); OCR1A = Gruen; if(Gruen > 50){ PORTA |= (1<<PA5); } else{ PORTA &= ~(1<<PA5); } } if(uart_string[0] == 'b'){ memmove(uart_string, uart_string+1, strlen(uart_string)); Blau = atoi(uart_string); OCR1B = Blau; if(Blau > 50){ PORTA |= (1<<PA6); } else{ PORTA &= ~(1<<PA6); } } if(uart_string[0] == 'c'){ if(uart_string[1] == '1'){ PORTA |= (1<<PA7); } else{ PORTA &= ~ (1<<PA7); } } if(uart_string[0] == 'O'){ if(uart_string[1] == '1'){ PORTA |= (1<<PA2); PORTA |= (1<<PA3); } else{ PORTA &= ~ (1<<PA2); PORTA &= ~ (1<<PA3); } } uart_str_complete = 0; } } while (1); } ISR(USART_RXC_vect) // Interrupt { unsigned char nextChar; nextChar = UDR; if( uart_str_complete == 0 ) { if((nextChar != 'y')) { uart_string[uart_str_count] = nextChar; uart_str_count++; uart_string[uart_str_count] = '\0'; } else { uart_string[uart_str_count] = '\0'; uart_str_count = 0; uart_str_complete = 1; } } } ....................................................................... ##################################################################### Leider klappt das mit der formatierung nicht so ganz hier im kleinen Fenster, viel verschoben ist ja nicht. Mein Problem ist.... ich sehe im Terminal dass ich die Daten richtig schicke. Aber mein Interrupt erkennt das 'y' einfach nicht. Ich saß nun schon 12 Stunden an diesem Probelm und finde einfach den Fehler nicht. Ich hoffe hier im Forum kann mir jemand helfen. Vielen Dank im voraus!!!! MfG Martin
Wow danke für die schnelle Antwort. Ja die Fuse is auf 8Mhz eingestellt. beeinflusst der teiler vom timer auch den Takt den der Uart benutzt?
Oszi habe ich mir sogar extra eins ausgeliehen und hier. Aber ich muss zugeben ich habe keine Ahnung wie man so etwas erkennt. Noch zur Info ... der ATmega32A läuft auf einem STK500 momentan
Sprich den Mega32 doch auch mal über ein Terminal an und schick ihm deine Zeichenketten. Zur Fehlersuche kann er dann ein Echo zurück schicken und noch ein Hinweis, in welcher Schleife er gerade ist.
Gute Idee daran hatte ich noch nicht gedacht, werde ich versuchen.Danke
UART Studienarbeit schrieb: > Oszi habe ich mir sogar extra eins ausgeliehen und hier. Aber ich muss > zugeben ich habe keine Ahnung wie man so etwas erkennt. Viele "UUUUUU" senden. Und Timing messen. Moderne haben eingebaute Werkzeuge, bei älteren kann auch ein Lineal und Taschenrechner helfen.
UART Studienarbeit schrieb: > Oszi habe ich mir sogar extra eins ausgeliehen und hier. Aber ich muss > zugeben ich habe keine Ahnung wie man so etwas erkennt. Um die Baudrate mit dem Oszi zu "messen", sendest du fortlaufend 0x55 oder 0xAA mit einem Stopbit. Damit erhältst du eine Rechteckspannung an Tx von 57,6KHz bzw. 28,8KHz.
Wenn ich es durch ein echo nicht herausfinde werde ich das mit dem oszi probieren. Vielen Dank für die ganzen Antworten. Ich bin völlig baff wie schnell man hier Hilfe bekommt!
8MHz und 115200Baud ist nicht möglich für nen AVR. Und deshalb glaub ich dir auch nicht, dass du das mit nem Terminal korrekt empfangen konntest. Selbst im double-speed-mode sind das fast 4% Fehler. Wenn du allerdings auf beiden Seiten mit demselben Fehler arbeitest, funktioniert es schon, aber dann eben nicht mit Standardbaudraten (Terminal).
der ATmega2560 sitzt mit einem externen 7,3Mhz Quarz auf einer kleinen Platine. die Platine hab ich von einem Prof bekommen um damit zu arbeiten. Ich habe ebenfalls ein Programm von ihm bekommen und habe seine UART-init übernommen.
Mhm ich muss zugeben das war nie mein Lieblingsfach... daher bin ich bei dem ganzen Thema noch nicht so bewandert, ich versuche mein Bestes. Thema Echo: ISR(USART_RXC_vect) // Interrupt { unsigned char nextChar; nextChar = UDR; if( uart_str_complete == 0 ) { if((nextChar != 'y')) { uart_string[uart_str_count] = nextChar; uart_str_count++; uart_string[uart_str_count] = '\0'; while (!(UCSRA & (1<<UDRE))); UDR = nextChar; } else { uart_string[uart_str_count] = '\0'; uart_str_count = 0; uart_str_complete = 1; } } } Ich weiss nicht ob ich das so einfach machen darf... also ein echo direkt im interrupt für jedes einzelne char. Sobald ich dem mega32 einen Befehl sende bekommen ich dieses Zeichen zurück das Null-Zeichen zurück <\0>.
UART Studienarbeit schrieb: > #define F_CPU 8000000UL UART Studienarbeit schrieb: > 7,3Mhz Quarz Fällt dir was auf?
der code den ich geschickt habe is vom mega32 ... der läuft mit dem internen 8Mhz. der 2560 läuft mit dem 7,3Mhz Quarz
Entschuldigt meine Rechtschreibung, ich versuche immer so schnell es geht zu Antworten bevor jemand von Ihnen schlafen geht. Da hacke ich einfach auf meine Tastatur ein.
Du könntest es auch ohne Hardware UART lösen was etwas mehr Programmieraufwand bedeuten würde, aber letztendlich viel unproblematischer im Taktverhalten ist. Nicht das du später irgend einen Vorführeffekt hast. Das Byte einfach bitweise mit einem Taktsignal über einen 2ten Pin rausschieben. Das Taktsignal löst beim Empänger einen Interrupt aus und er schiebt das Bit in ein Byte rein. Durch die Taktleitung hat man keinerlei Probleme wenn die Takte der µC nicht synchron sind und einander weglaufen, da jedes Bit neu synchronisiert wird.
also ich kann den mega32 nicht mit dem internen 8Mhz und 115200baud laufen lassen?
UART Studienarbeit schrieb: > Ich weiss nicht ob ich das so einfach machen darf... also ein echo > direkt im interrupt für jedes einzelne char. sollte funktionieren, die while() davor brauchst du eigentlich nicht vielleicht setzt du zum Testen die Baudrate herunter, wenns funzt, kannst du sie ja wieder hochsetzen
Ah ok, an eine Software-UART hatte ich noch nicht gedacht. Ich hatte nicht so grosse Probleme erwartet
UART Studienarbeit schrieb: > also ich kann den mega32 nicht mit dem internen 8Mhz und > 115200baud > laufen lassen? Und nochmal: Schaue dir das Timing an. Von beiden! Vergleiche! Und dann findest du deine eigene Antwort. Oder Rechne es aus. Das bringt das gleiche Ergebnis, wenn du es richtig machst. Teiler, Fuses, ist ja alles offen.
Ok ich werde es versuchen. Nur noch eins was mit gerade klar wird. der jetztige mega32 ist nur ein testµC. Ich bekomme in einer woche meine Finale Platine. Und dann wird der mega32 ebenfalls mit einem externen 7,3Mhz Quarz betrieben. Wenn das nun wirklich am Timing liegt sollte sich das doch eigentlich erledigen wenn ich den mega32 mit dem selben Quarz laufen lasse wie der 2560. oder?
UART Studienarbeit schrieb: > sollte sich das doch eigentlich > erledigen wenn ich den mega32 mit dem selben Quarz laufen lasse wie der > 2560. Ja.
UART Studienarbeit schrieb: > Wenn das nun wirklich am Timing liegt sollte sich das doch eigentlich > erledigen wenn ich den mega32 mit dem selben Quarz laufen lasse wie der > 2560. > oder? Ja
Super dann hat sich der Thread erledigt, danke Emile.Und vielen Dank an alle hier :) bin echt begeistert von dem forum!!!
... bevor du eine Woche wartest, kannst du natürlich auch mit einer geringeren Baudrate arbeiten, z.B. 38400, da beträgt der Baudratenfehler nur 0,2% bei 8MHz, beim 7.3728MHz-Quarz ist der Fehler 0%.
UART Studienarbeit schrieb: > bin echt begeistert von dem forum!!! Wenn da nicht immer die Freitags Trolle wären :-) Ah Ah Ah 00:16h es ist schon wieder Freitag .... Gute Nacht :-)
Émile Baudot schrieb: > ... bevor du eine Woche wartest, kannst du natürlich auch mit > einer > geringeren Baudrate arbeiten, z.B. 38400, da beträgt der Baudratenfehler > nur 0,2% bei 8MHz, beim 7.3728MHz-Quarz ist der Fehler 0%. Nee, sorry, vergiss es, du nimmst ja den internen RC-Oszillator, hab ich gerade erst gesehen. Der ist wahrscheinlich zu ungenau. Das mit der niedrigeren BR wird auch nur dann funktionieren, wenn du an den mega32 einen ext. Quarz dranklemmst. Vllt nochmal in ein paar Schubladen wühlen...
Guten Abend zusammen, und vielen Dank an alle die mir hier geholfen haben. Ich wollte den Thread natürlich noch auflösen und aufklären wo mein Fehler lag. Die Platine die ich von der Hochschule gestellt bekommen habe, auf der sich der mega2560 befindet, hat einen RS485 Baustein mit dem die UART nach aussen geführt wird. Das STK500 auf dem der mega32A installiert war kommuniziert jedoch mittels RS232. Daher konnte eine Kommunikation garnicht zustande kommen. Trotzdem nochmals vielen Dank an alle die sich hier die Mühe gemacht haben und versuchten mit zu helfen!!!!! Mit freundlichen Grüssen Martin
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.