Hey Leute, ich weiss das es schon genug Beiträge über Probleme mim UART
gibt,aber ich komm einfach nich weiter. Ich möchte mir ein Programm in
GCC schreiben, das bestimmte Wörter über die Hardware UART Schnittstelle
des Atmega8 verschickt, wenn jeweils ein bestimmter eingang low ist. Um
aber klein anzufangen soll mein uC erstmal nur ein Wort über die UART
Schnittstelle versenden. Hab mir dafür den Code aus der Tutorial Seite
zusammenkopiert. Und das ganze sieht bei mir so aus:
1 | #include <avr/io.h>
|
2 | #ifndef F_CPU
|
3 | /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
|
4 | F_CPU im Makefile definiert werden, eine nochmalige Definition
|
5 | hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
|
6 | #ifndef/#endif
|
7 |
|
8 | Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
|
9 | verwendet wird und dort eine andere, nicht zur Hardware passende
|
10 | Taktrate eingestellt ist: Dann wird die folgende Definition
|
11 | nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
|
12 | von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
|
13 | noch nicht definiert: */
|
14 | #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
|
15 | #define F_CPU 8000000UL // Systemtakt in Hz - Definition als unsigned long beachten
|
16 | // Ohne ergeben sich unten Fehler in der Berechnung
|
17 | #endif
|
18 |
|
19 | #define BAUD 9600UL // Baudrate
|
20 |
|
21 | // Berechnungen
|
22 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
23 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
24 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
|
25 |
|
26 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
27 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
28 | #endif
|
29 |
|
30 |
|
31 | int main(void)
|
32 | {
|
33 | UCSRB |= (1<<TXEN); // UART TX einschalten
|
34 | UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1
|
35 |
|
36 | UBRRH = UBRR_VAL >> 8;
|
37 | UBRRL = UBRR_VAL & 0xFF;
|
38 |
|
39 | uart_puts('TEST'); //Test Senden
|
40 |
|
41 | }
|
42 |
|
43 |
|
44 | // bei neueren AVRs andere Bezeichnung fuer die Statusregister, hier ATmega8:
|
45 | int uart_putc(unsigned char c)
|
46 | {
|
47 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
|
48 | {
|
49 | }
|
50 |
|
51 | UDR = c; /* sende Zeichen */
|
52 | return 0;
|
53 | }
|
54 |
|
55 |
|
56 | /* puts ist unabhaengig vom Controllertyp */
|
57 | void uart_puts (char *s)
|
58 | {
|
59 | while (*s)
|
60 | { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
|
61 | uart_putc(*s);
|
62 | s++;
|
63 | }
|
64 | }
|
das sollte doch soweit in Ordnung sein,oder? Zumindest sendet mein uC so
irgendwas. Nur leider sieht das nach Kauderwelsch aus. Dachte also
zuerst an ein Timing Problem. Ist aber in den Fuses alles richtig
eingestellt. Wenn ich den Code so abänder das ich nicht mehr uart_puts
aufrufe sondern mit UDR = 'X' ein einzelnes zeichen verschicke, klappt
auch alles perfekt. Hier der Code mit dem einzelnen Zeichen:
1 | #include <avr/io.h>
|
2 | #ifndef F_CPU
|
3 | /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
|
4 | F_CPU im Makefile definiert werden, eine nochmalige Definition
|
5 | hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
|
6 | #ifndef/#endif
|
7 |
|
8 | Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
|
9 | verwendet wird und dort eine andere, nicht zur Hardware passende
|
10 | Taktrate eingestellt ist: Dann wird die folgende Definition
|
11 | nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
|
12 | von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
|
13 | noch nicht definiert: */
|
14 | #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
|
15 | #define F_CPU 8000000UL // Systemtakt in Hz - Definition als unsigned long beachten
|
16 | // Ohne ergeben sich unten Fehler in der Berechnung
|
17 | #endif
|
18 |
|
19 | #define BAUD 9600UL // Baudrate
|
20 |
|
21 | // Berechnungen
|
22 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
23 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
24 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
|
25 |
|
26 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
27 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
28 | #endif
|
29 |
|
30 |
|
31 | int main(void)
|
32 | {
|
33 | UCSRB |= (1<<TXEN); // UART TX einschalten
|
34 | UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1
|
35 |
|
36 | UBRRH = UBRR_VAL >> 8;
|
37 | UBRRL = UBRR_VAL & 0xFF;
|
38 |
|
39 | UDR = 'X'; // X Senden
|
40 |
|
41 | }
|
42 |
|
43 |
|
44 | // bei neueren AVRs andere Bezeichnung fuer die Statusregister, hier ATmega8:
|
45 | int uart_putc(unsigned char c)
|
46 | {
|
47 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
|
48 | {
|
49 | }
|
50 |
|
51 | UDR = c; /* sende Zeichen */
|
52 | return 0;
|
53 | }
|
54 |
|
55 |
|
56 | /* puts ist unabhaengig vom Controllertyp */
|
57 | void uart_puts (char *s)
|
58 | {
|
59 | while (*s)
|
60 | { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
|
61 | uart_putc(*s);
|
62 | s++;
|
63 | }
|
64 | }
|
wie gesagt ich hab da nur eine Zeile geändert,aber dann komm auch X an
und kein kauderwelsch. Naja, hoffe ihr habt mein Problem verstanden und
könnt mir vielleicht helfen. Vielen Dank schonmal, Ruediger