Forum: Mikrocontroller und Digitale Elektronik UART Probleme


von Florian S. (didi34)


Lesenswert?

Ich verwende einen Atmega8 und sende zeichen auf Putty.
1
/* 
2
  UART-Init: 
3
Berechnung des Wertes für das Baudratenregister 
4
aus Taktrate und gewünschter Baudrate
5
*/
6
 
7
#ifndef F_CPU
8
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
9
   F_CPU im Makefile definiert werden, eine nochmalige Definition
10
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
11
   #ifndef/#endif 
12
 
13
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
14
   verwendet wird und dort eine andere, nicht zur Hardware passende 
15
   Taktrate eingestellt ist: Dann wird die folgende Definition 
16
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
17
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
18
   noch nicht definiert: */
19
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
20
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
21
                         // Ohne ergeben sich unten Fehler in der Berechnung
22
#endif
23
 
24
#define BAUD 9600UL      // Baudrate
25
 
26
// Berechnungen
27
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
28
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
29
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
30
 
31
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
32
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
33
#endif 
34
#include <avr/io.h> 
35
#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
36
#define BAUD 9600
37
#include <util/setbaud.h>
38
 
39
void uart_init(void)
40
{
41
  UBRRH = UBRR_VAL >> 8;
42
  UBRRL = UBRR_VAL & 0xFF;
43
 
44
  UCSRB |= (1<<TXEN);  // UART TX einschalten
45
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
46
}
47
int uart_putc(unsigned char c)
48
{
49
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
50
    {
51
    }                             
52
 
53
    UDR = c;                      /* sende Zeichen */
54
    return 0;
55
}
56
 
57
 
58
/* puts ist unabhaengig vom Controllertyp */
59
void uart_puts (char *s)
60
{
61
    while (*s)
62
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
63
        uart_putc(*s);
64
        s++;
65
    }
66
}
67
int main()
68
{
69
char wort [100] = "hallo welt";
70
 uart_init();
71
uart_puts (wort);
72
}
Und was ich als Ausgabe bekomme ist : ÀÀÀÀÀÀÀÀÀÀ also hallo welt nur mit 
À Buchstaben. Kann mir jemand helfen?

von dunno.. (Gast)


Lesenswert?

also zweimal FCPU definieren ist bestimmt keine besonders gute idee... 
vorallem nicht, wenn du die jedes mal anders definierst..

wie schnell schwingt er denn, der takt?

von Florian S. (didi34)


Lesenswert?

1
/* 
2
  UART-Init: 
3
Berechnung des Wertes für das Baudratenregister 
4
aus Taktrate und gewünschter Baudrate
5
*/
6
 
7
#ifndef F_CPU
8
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
9
   F_CPU im Makefile definiert werden, eine nochmalige Definition
10
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
11
   #ifndef/#endif 
12
 
13
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
14
   verwendet wird und dort eine andere, nicht zur Hardware passende 
15
   Taktrate eingestellt ist: Dann wird die folgende Definition 
16
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
17
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
18
   noch nicht definiert: */
19
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
20
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
21
                         // Ohne ergeben sich unten Fehler in der Berechnung
22
#endif
23
 
24
#define BAUD 9600UL      // Baudrate
25
 
26
// Berechnungen
27
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
28
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
29
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
30
 
31
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
32
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
33
#endif 
34
#include <avr/io.h> 
35
#include <util/setbaud.h>
36
 
37
void uart_init(void)
38
{
39
  UBRRH = UBRR_VAL >> 8;
40
  UBRRL = UBRR_VAL & 0xFF;
41
 
42
  UCSRB |= (1<<TXEN);  // UART TX einschalten
43
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
44
}
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(Terminator)" */
61
        uart_putc(*s);
62
        s++;
63
    }
64
}
65
int main()
66
{
67
char wort [100] = "hallo welt";
68
 uart_init();
69
uart_puts (wort);
70
}
Habe es jetzt so umgeändert.
Der Controller läuft intern mit   3.686 MHz

von Sucher (Gast)


Lesenswert?

Hallo

läuft dein Atmega mit 1 MHZ?

Schmeiß diese Zeile raus

>>#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */

derRest müßte ok sein. Habe ich auch so.

Eventuell mal da zu Testzwecken (explizit Werte einsetzen?)

UBRRL=(F_CPU / (baudrate * 16L) - 1)

einsetzen.

von dunno.. (Gast)


Lesenswert?

Florian Schuller schrieb:
> Der Controller läuft intern mit   3.686 MHz

dann sollte man das FCPU auch mitteilen, sonst stimmt die baudrate 
nicht, und du liest halt irgendwas auf der seriellen, nur nicht das was 
der controller schreibt..

von Florian S. (didi34)


Lesenswert?

Habe es jetzt so geändert
1
/* 
2
  UART-Init: 
3
Berechnung des Wertes für das Baudratenregister 
4
aus Taktrate und gewünschter Baudrate
5
*/
6
 
7
#ifndef F_CPU
8
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
9
   F_CPU im Makefile definiert werden, eine nochmalige Definition
10
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
11
   #ifndef/#endif 
12
 
13
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
14
   verwendet wird und dort eine andere, nicht zur Hardware passende 
15
   Taktrate eingestellt ist: Dann wird die folgende Definition 
16
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
17
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
18
   noch nicht definiert: */
19
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
20
#define F_CPU 3686400UL  // Systemtakt in Hz - Definition als unsigned long beachten 
21
                         // Ohne ergeben sich unten Fehler in der Berechnung
22
#endif
23
 
24
#define BAUD 9600UL      // Baudrate
25
 
26
// Berechnungen
27
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
28
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
29
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
30
 
31
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
32
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
33
#endif 
34
#include <avr/io.h> 
35
//#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
36
//#define BAUD 9600
37
#include <util/setbaud.h>
38
 
39
void uart_init(void)
40
{
41
  UBRRH = UBRR_VAL >> 8;
42
  UBRRL = UBRR_VAL & 0xFF;
43
 
44
  UCSRB |= (1<<TXEN);  // UART TX einschalten
45
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
46
}
47
int uart_putc(unsigned char c)
48
{
49
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
50
    {
51
    }                             
52
 
53
    UDR = c;                      /* sende Zeichen */
54
    return 0;
55
}
56
 
57
 
58
/* puts ist unabhaengig vom Controllertyp */
59
void uart_puts (char *s)
60
{
61
    while (*s)
62
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
63
        uart_putc(*s);
64
        s++;
65
    }
66
}
67
int main()
68
{
69
char wort [100] = "hallo welt";
70
 uart_init();
71
uart_puts (wort);
72
}
Und ich bekomme als ausgabe :  À8?àø8ø8þø8Àøø8À8ø8øø

von Karl H. (kbuchegg)


Lesenswert?

Florian Schuller schrieb:


> #define F_CPU 3686400UL  // Systemtakt in Hz - Definition als unsigned
> long beachten

damit alleine ist es noch nicht getan.
Läuft der µC auch mit 3.6864Mhz?

Und schmeiss das #ifndef da rundeherum raus. Es zeigt sich, dass das zu 
mehr Fehler führt als es gut ist.

von Karl H. (kbuchegg)


Lesenswert?


von Klaus 2. (klaus2m5)


Lesenswert?

Florian Schuller schrieb:
> #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"

Siehst Du diese Meldung? Sonst ist F_CPU bereits falsch definiert.

Florian Schuller schrieb:
> Und ich bekomme als ausgabe :  À8?àø8ø8þø8Àøø8À8ø8øø
                                     ----         --

Man kann Hallo Welt grob erkennen.
           --    -
                      nur halb so schnell wie es sein müsste.

von Florian S. (didi34)


Lesenswert?

Habe einen externen Quarz verwendet und es funktioniert.
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
Noch kein Account? Hier anmelden.