Forum: Mikrocontroller und Digitale Elektronik UART mit ATMEGA32 sendet falsche Daten


von Stefan (Gast)


Lesenswert?

Hallo,

stehe vor einem Problem, welches ich leider alleine nicht lösen kann. 
Ich habe versucht, eine serielle Datenübertragung mit einem ATMEGA32 zu 
programmieren. Im Terminalprogramm ("Awavo Com Port Monitor") kommt 
leider immer etwas anderes heraus, als ich im µC hineinstecke...Die 
Baudrate soll 2400bps (UBRR = 01A0 -> 0,1%Fehler)betragen. Ich komme 
leider nicht dahinter, wo der Fehler liegt....vlt kann mir ja hier 
jemand helfen :) Währe sehr sehr dankbar!
1
#define F_CPU 16000000UL                              // Taktfrequenz des µC definieren
2
#include <util/delay.h>
3
#include <avr/io.h>
4
5
int main(void)
6
{
7
  //------------------------------------µC - Initialisierung ----------------------------------------------------------------------
8
  
9
  DDRB = 0xFF;                                  // Datenrichtung für Port B als Ausgang definieren
10
  
11
  
12
// AD - Wandler:
13
  
14
  ADMUX |= 0x00;                                  // Sind die Mux4...0 -Bits = 0, so wird der Port ADC0 ausgewählt
15
  ADMUX |= (1<<REFS0) | (1<<ADLAR);                        // Referenzspannung ist AVCC
16
  
17
  ADCSRA = 0x00;
18
  ADCSRA |= (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);                  // Prescaler für Samplerate auf 128
19
  ADCSRA |= (1<<ADEN);                              // ADC einschalten
20
  
21
  
22
// USART - Serielle Schnittstelle
23
  
24
  UCSRB |= (1<<TXEN);                                // USART - Transmitter einschalten          
25
  
26
  // - Baudrate  auf 2400bps einstellen
27
  UCSRC &= ~(1<<URSEL);                              // URSEL = 0 für Zugriff auf das UBRRH-Register
28
  UBRRH = 0x01;                                  // UBRRH mit Baudrate für 2400bps (Bits 8 - 11) -416
29
  UBRRL = 0xA0;                                  // UBRRL mit Baudrate für 2400bps (Bits 0 - 7)  
30
  
31
  // - Frame Format definieren (8 Bit ohne Parity und 1 Stopbit)
32
  
33
  UCSRC |= (1<<URSEL);                              // URSEL = 1 für Zugriff auf das UCRSC Register
34
  UCSRC = (1<<UCSZ1) | (1<<UCSZ0);                        // 8 Bit Frame Format - alle anderen Einstellungen sind defaultmäßig bereits wie gewünscht
35
  
36
  // - Transmitter aktivieren
37
  
38
  //UCSRB |= (1<<TXEN);                                // USART - Transmitter einschalten          
39
  
40
  
41
  while(1)
42
  {
43
    ADCSRA |= (1<<ADSC);                            // Starten der Umwandlung
44
    while(ADCSRA & (1<<ADSC));                          // Warten bis ADSC wieder 0 wird (µC ist fertig mit der AD - Wandlung)
45
    PORTB = ADCH;                                // Ausgabe des Higher-Bytes am Port B
46
    /*
47
    while (!(UCSRA & (1<<UDRE)))                        // Warten bis die Daten des letzten Vorganges fertig verarbeitet sind
48
      {
49
          
50
      }
51
    UDR = ADCL;                                  // Messdaten vom ADC übertragen (Lower Byte)
52
    
53
    while (!(UCSRA & (1<<UDRE)))                        // Warten bis die Daten des letzten Vorganges fertig verarbeitet sind
54
      {
55
          
56
      }
57
    UDR = ADCH;                                  // Messdaten vom ADC übertragen (Higher Byte)
58
    */
59
    while (!(UCSRA & (1<<UDRE)))                        // Warten bis die Daten des letzten Vorganges fertig verarbeitet sind
60
      ;
61
                  
62
    UDR = 0x07;
63
    
64
    _delay_ms(1000);                              // 1s warten bevor die Schleife noch einmal durchlaufen wird
65
  }
66
}

PS.: bitte nicht den Kopf abreissen...habe wenig Erfahrung im Umgang mit 
AVR's

Liebe Grüsse,
Stefan

von holger (Gast)


Lesenswert?


von Stefan E. (sternst)


Lesenswert?

1
  UCSRC &= ~(1<<URSEL);                              // URSEL = 0 für Zugriff auf das UBRRH-Register
2
  UBRRH = 0x01;                                  // UBRRH mit Baudrate für 
3
...
4
  UCSRC |= (1<<URSEL);                              // URSEL = 1 für Zugriff auf das UCRSC Register
5
  UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
Nee, so funktioniert das URSEL nicht.
Schau nochmal ins Datenblatt (da stehen doch sogar Beispiele).

von Uwe (de0508)


Lesenswert?

Hallo,

wie URSEL funktioniert musst du mal nachlesen.

Das geht, aber es ist falsch, im Datenblatt steht eine andere Formel:
Baudrate = 2400
UBRR = F_CPU  16 Baudrate -1
UBRR = 16 * 10^6  16 Baudrate - 1
UBRR= 10^6   2400 - 1 = 416 - 1 = 415

=>
UBRRL = UBRR mod 256 = 159
UBRRH = UBRR / 256 = 1
1
  // - Baudrate  auf 2400bps einstellen
2
  UCSRC &= ~(1<<URSEL);                              // URSEL = 0 für Zugriff auf das UBRRH-Register
3
  UBRRH = 0x01;                                  // UBRRH mit Baudrate für 2400bps (Bits 8 - 11) -416
4
  UBRRL = 0xA0;                                  // UBRRL mit Baudrate für 2400bps (Bits 0 - 7)
Siehe Datenblatt, S.159.

Das funktioniert nicht:
1
 UCSRC |= (1<<URSEL);                              // URSEL = 1 für Zugriff auf das UCRSC Register
2
  UCSRC = (1<<UCSZ1) | (1<<UCSZ0);

Das Datenformat 8Bit, UCSZ1=1, UCSZ0=1 ist voreingestellt !
Siehe Datenblatt, S.158.

von Stefan E. (sternst)


Lesenswert?

Uwe S. schrieb:
> Das geht, aber es ist falsch, im Datenblatt steht eine andere Formel:

Man sollte vielleicht auch richtig runden.
Es sind 416,666 - 1, also gerundet 417 - 1 = 416.
Und der Wert steht auch in der Tabelle im Datenblatt.

von Uwe (de0508)


Lesenswert?

Danke Stefan,

ja du hast Recht habe ich übersehen, wenn man mit/ ab 0,5 rundet, 
stimmen die Werte.

von Wolfgang (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Man sollte vielleicht auch richtig runden.
> Es sind 416,666 - 1, also gerundet 417 - 1 = 416.

Das macht nun wirklich nicht den riesigen Unterschied. Das wäre gerade 
ein Baudratenfehler von 0.24% oder im Empfänger ein Zeitfehler von 2.4% 
für den Abtastzeitpunkt des letzten Bits.
Davon bricht die Datenübertragung nicht zusammen, wenn die Signale sonst 
sauber sind.

von Stefan (Gast)


Lesenswert?

Wow! So viele hilfreiche Antworten...vielen Dank erstmal!

Die Checkliste habe ich mir schon durchgesehen...am Anfang hatte ich den 
Verdacht, dass eine der Fuses falsch gesetzt ist..dem war aber nicht so.

Hab mir das Datenblatt nochmal durchgelesen und denke, dass ich den 
Fehler schon gefunden habe... URSEL muss WÄHREND dem Schreibvorgang den 
richtigen Wert haben...also UCSRC |= (1<<URSEL) | (1<<UCSZ1) | 
(1<<UCSZ0); liege ich hiermit richtig?

Zu der Baudrate:
ich habe eben diesen Wert von 416 berechnet und im Datenblatt, in der 
Tabelle, nachgeschlagen...als Hex-Wert ergibt das eben 1A0...


Liebe Grüsse,
Stefan

von Stefan (Gast)


Lesenswert?

Siehe da, ich habe nur den Befehl "UCSRC &= ~(1<<URSEL);" vor "UBRRH = 
0x01" auskommentiert und alles funktioniert so wie ich mir das gewünscht 
habe! :) VIELEN DANK AN EUCH!! Alleine wäre ich da nie drauf gekommen! 
;)

Liebe Grüsse,
Stefan

von Total-Hirnöderl (Gast)


Lesenswert?

Was ist an dem bescheuertem Thema eigentlich so interessant?

von Stefan E. (sternst)


Lesenswert?

Wolfgang schrieb:
> Das macht nun wirklich nicht den riesigen Unterschied.

Habe ich denn irgendetwas in der Richtung behauptet?
Es ging doch lediglich um die Frage:
"Wieso bekommt Uwe bei der Berechnung einen anderen Wert heraus, als im 
Datenblatt steht?"

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.