Hallo! Ich habe bisher meinen Mega8 immer mit Assembler programmiert. Jetzt habe ich ein Programm angefangen, dass mit Assembler einfach zu umständlich wird und bin deshalb auf C umgestiegen. Mit Assembler hat das Senden über den UART problemlos geklappt, mit C funktioniert es komischerweise nicht. Es kommt nur sporadisch mal ein Zeichen, dass so aussieht wie ein hochgesetztes L. Es wird aber scheinbar permanent etwas gesendet, da die LEDs an TX und RX flackern. Da es mit Assembler klappt, ist die Hardware also schonmal in Ordnung. Vielleicht ist es nur ein kleiner Fehler. Bitte helft mir. Hier mein Code: #define F_CPU 8000000 #define BAUD 9600 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) #define LOW(x) ((x) & 0xFF) #define HIGH(x) (((x) >> 8) & 0xFF) #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010)) #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! #endif #include <avr/io.h> #include <stdlib.h> void initUART() { UCSRB |= (1<<TXEN); UBRRL = LOW(UBRR_VAL); UBRRH = HIGH(UBRR_VAL); } int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */ UDR = c; /* sende Zeichen */ return 0; } void uart_puts (char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_putc(*s); s++; } } void main() { char buffer[20]; initUART(); while(1) { //sprintf(buffer, "Hallo"); //uart_puts(buffer); uart_putc('H'); uart_putc('A'); uart_putc('L'); uart_putc('L'); uart_putc('O'); } }
Dominik wrote: > void initUART() > { > UCSRB |= (1<<TXEN); > UBRRL = LOW(UBRR_VAL); > UBRRH = HIGH(UBRR_VAL); > } Wie war das mit dem temporären oberen Register?
1 | /* entweder */
|
2 | UBRRH = HIGH(UBRR_VAL); |
3 | UBRRL = LOW(UBRR_VAL); |
4 | /* oder */
|
5 | UBRR = UBRR_VAL |
OK, danke. Das war schonmal der erste dumme Fehler. Da muss aber noch was sein, denn es funktioniert immer noch nicht.
Das "Übliche" hast du abgecheckt? Richtige BAUD-Rate am Empfänger eingestellt? Läuft der Mega8 wirklich mit 8MHz?
Ja, das übliche habe ich gecheckt. Wie gesagt, wenn ich eins von meinen Assemblerprogrammen lade, funktioniert es direkt.
Statt Hyperterminal benutze ich jetzt TeraTerm. In TeraTerm werden jetzt sehr schnell hintereinander diese besagten "L" ausgegeben. Woran liegt das denn bloß???
Sven Pauli wrote: > Wie war das mit dem temporären oberen Register? Gibt's beim USART Baud Rate Register aber nicht (macht auch nur dort Sinn, wo es wirklich wichtig ist, dass die Werte für Low- und High-Byte synchronisiert werden) > /* entweder */ > UBRRH = HIGH(UBRR_VAL); > UBRRL = LOW(UBRR_VAL); Siehe oben: Reihenfolge spielt in diesem Fall keine Rolle > /* oder */ > UBRR = UBRR_VAL Ein 16-Bit-Register gibt es in diesem Falle nicht und kann es auch nicht geben, u.a. weil UBRRL und UBRRH beim Mega8 im Speicher nicht hintereinander liegen.
Kurzes Update: Es muss irgendwo in der Baudraten-Berechnung der Wurm drin sein. Ich habe jetzt ins Baudratenregister direkt den Wert 52 geschrieben (aus der Tabelle im Datenblatt entnommen). Jetzt kommt aber nur nach mehrmaligem Reset-Drücken das gewünschte Zeichen!!! Woran liegt das nun wieder? Ich verzweifele gleich....
> #define BAUD 9600
Das müsste vermutlich ein 9600L oder 9600UL sein, F_CPU sollte auch ein
8000000UL verpasst bekommen, sonst kann es Problemchen bei der
Berechnung geben...
Danke Johannes. Trotzdem ist das Problem noch da: Nur nach mehrmaligem Reset kommen die richtigen Zeichen an. Wenn man dann nochmal Reset drückt kommen meistens wieder die falschen.
mal nen auszug vin meinem mega8, da funktionierts: [c] #include <inttypes.h> #include <avr/io.h> #include <stdlib.h> #include <util/delay.h> #include "lcd_mega8.h" #ifndef F_CPU #define F_CPU 8000000 #endif #define BAUD 9600UL //Baudrate #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1) void wait (uint16_t zeit) //zeit: wartezeit in ms (0 bis 65536) { uint16_t i; for(i=0;i<zeit;i++) _delay_ms(1); //da für _delay_ms max Takt-abhängige Werte erlaubt } // uart#################################################################### ## void uart_init(void) { UCSRB = (1<<RXEN)|(1<<TXEN); // UART TX und RX einschalten UCSRC |= ( 1 << URSEL )|( 3<<UCSZ0 ); // Asynchron 8N1 //nur für 19200 Baud bei 16MHz für Mega32 //UBRRH = 0; // Highbyte ist 0 //UBRRL = 51; // Lowbyte ist 51 //falls anderer Mega bzw andere Frequenz UBRRH = (uint8_t) (UBRR_BAUD>>8); UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff); } void uart_data(unsigned char c) { while (!(UCSRA & (1<<UDRE))) {} // warten bis Senden möglich UDR = c; // Zeichen senden } void uart_string (char *s) { while (*s) { uart_data(*s); s++; } } //###################################################################### ##### int main(void) { uint16_t adcval=0; char s[17]; uart_init(); uart_string( "Messung gestartet:" ); uart_string( "\n\r" ); while(1) { } return 0; } [\c]
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.