Forum: Mikrocontroller und Digitale Elektronik Atmega8 UART Probleme


von Ruediger (Gast)


Lesenswert?

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

von Jochen R. (josch90)


Lesenswert?

Ist der Controller neu? Möglicherweise läuft er noch auf seinem internen 
Takt. Also sicherstellen dass der 8Mhz Quarz dran is un auch in den 
Fuses aktiviert ist.


Gruß

von Sebastian M. (noobuntu)


Lesenswert?

mit uart_puts versendest du ja eine Zeichenkette. Weis nicht ob es 
Probleme gibt wenn du nur 1 Zeichen damit verschickst. Was passiert den 
wenn du
1
usart_putc('X');
 benutzt ?
Oder probiert mal
1
usart_puts("Test");

Sonst solltest du mal deine Fuses überprüfen.

von Ruediger (Gast)


Lesenswert?

Hey, das einzelne Zeichen hab ich ja auch nicht mit UART_puts versendet 
sondern direkt an UDR übergeben. Das klappt ja dann auch. Nur wenn ich 
mit UART_puts('test');  nen string senden will klappt es nicht....
Die Fuses hab ich aber trotzdem nochmal überprüft und die stehen auf 
Ext. Crystal und an meinem STK500 ist ebenfalls alles auf externen Quarz 
gejumpert. Hoffe ihr habt noch mehr ideen. LG Ruediger

von Mmmh (Gast)


Lesenswert?

1
uart_puts('TEST');    //Test Senden

soll wohl
1
uart_puts("TEST");    //Test Senden

heissen.

Ich wundere mich stark das dieser Code überhaupt ohne Fehler compiliert 
wurde.

von Ruediger (Gast)


Lesenswert?

Oh man, das wars!!!!
Vielen Vielen Dank! Hatte echt ein Brett vorm Kopf. Mit "TEST" 
funktioniert es tadelos! Warum der Compiler allerdings keinen Fehler 
gemeldet hat,weiß ich auch nicht. Auf jeden Fall vielen Dank für dein 
wachsames Auge. Mfg Ruediger

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
Noch kein Account? Hier anmelden.