Forum: Mikrocontroller und Digitale Elektronik Atmega Uart - Falsche Byte Übertragung


von AtmegaNoob (Gast)


Lesenswert?

Hi!

Folgender Aufbau habe ich:

Auf einem Atmel Evalution Board habe ich einen Atmega32.
Über Uart sende ich Daten vom Atmega zum PC. (Nicht Angeschlossen 
sondern über den AZ-Delivery FT232-AZ USB zu TTL Serial Adapter für 3,3V 
und 5V).
Leider bekomme ich auf dem PC (HTerm) falsche Bytes.

Die ersten beiden Bytes sind ok und dann wird die zweite Byte 5 Mal 
widerholt.
Auch zeigt hTerm sporadisch an, dass es Fehler in der Übertragung für 
manche Bytes gibt. Baudrate, Byte und Stoo Bit sind gleich angezeigt.
1
#include <avr/io.h>
2
#include <stdio.h>
3
//#define F_CPU 3686400UL
4
#define F_CPU 16000000UL
5
#include <util/delay.h>
6
#define Baud 38400
7
//#define CR "\0\r\n"
8
9
10
void uart_init(void)
11
{
12
  UCSRB = (1 << TXEN);
13
  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
14
  UBRRL=0x05; // Baudrate festlegen
15
  UBRRH=0x00; // Baudrate festlegen
16
}
17
18
int uart_send(unsigned char c)
19
{
20
  while (!(UCSRA & (1<<UDRE)))
21
  {
22
    // mach nichts
23
  }
24
  //senden
25
  UDR=c;
26
  return 0;
27
}
28
29
30
void uart_write(char *s)
31
{
32
  while(*s)
33
  {
34
    uart_send(*s);
35
    s++;
36
  }
37
}
38
39
int main(void)
40
{
41
  uart_init();
42
  while(1==1)
43
  {
44
    //uart_write("Das ist ein Test" CR);
45
    uart_write("Das ist ein Test\r\n");
46
    _delay_ms(1000);
47
  }
48
}

Mal zum Testen in Assembler probiert:

1
;
2
; Laboraufgabe 4 - (UART).asm
3
;
4
5
.include "m32def.inc"
6
7
.def temp = r16    ; Register für kleine Arbeiten
8
.def zeichen = r17  ; in diesem Register wird das Zeichen an die Ausgabefunktion übergeben
9
10
.equ F_CPU = 16000000  ; Systemtakt in Hz
11
.equ BAUD = 9600    ; Baudrate
12
13
; Berechnungen
14
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
15
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL)+1))    ; Reale Baudrate
16
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promile
17
18
.if((BAUD_ERROR>10) || (BAUD_ERROR<-10))  ; max +/- 10 Promile Fehler
19
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
20
.endif
21
22
; Stackpointer initialisieren
23
24
  ldi  temp,  HIGH(RAMEND)
25
  out SPH,  temp
26
  ldi  temp,  LOW(RAMEND)
27
  out  SPL,  temp
28
29
; Baudrate einstellen
30
  ldi  temp,  HIGH(UBRR_VAL)
31
  out UBRRH,  temp  
32
  ldi  temp,  LOW(UBRR_VAL)    
33
  out  SPL,  temp
34
; Frame-Format 8 Bit
35
  ldi  temp,  (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
36
  out UCSRC,  temp
37
  sbi UCSRB,  TXEN  ; TX aktivieren
38
  ldi  r16,  (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
39
  out  UCSRC,  r16
40
loop:
41
  ldi  zeichen,  0b00000001
42
  rcall  serout    ; Unterprogramm aufrufen
43
  ldi  zeichen,  0b00000010
44
  rcall  serout    ; Unterprogramm aufrufen
45
  ldi  zeichen,  0b00000011
46
  rcall  serout    ; Unterprogramm aufrufen
47
  ldi  zeichen,  0b00000100
48
  rcall  serout    ; Unterprogramm aufrufen
49
  ldi  zeichen,  0b00000101
50
  rcall  serout    ; Unterprogramm aufrufen
51
  ldi  zeichen,  0b00000110
52
  rcall  serout    ; Unterprogramm aufrufen
53
  ldi  zeichen,  0b00000111
54
  rcall  serout    ; Unterprogramm aufrufen
55
  ldi  zeichen,  0b00001000
56
  rcall  serout    ; Unterprogramm aufrufen
57
  
58
59
  rcall  serout
60
  rcall  sync
61
  rjmp  loop
62
63
serout:
64
  sbis  UCSRA,  UDRE  ; Warten bis UDR für das nächste Byte bereit ist
65
  rjmp  serout
66
  out  UDR,  zeichen  
67
  ret            ; zurücl zum Hauptprogramm
68
69
; kleine Pause zum Synchronisieren des Empfängers, falls zwischenzeitlich
70
; das Kabel getrennt wurde
71
72
sync:
73
  ldi  r16,  0
74
sync_1:
75
  ldi  r17,  0
76
sync_loop:
77
  dec  r17
78
  brne  sync_loop
79
  dec  r16
80
  brne  sync_1
81
  ret
82
83
; Replace with your application code



Danke im Voraus!

von Jan V. (janv)


Lesenswert?

AtmegaNoob schrieb:
> Baudrate, Byte und Stoo Bit sind gleich angezeigt.

Und die Parität?

von M. K. (sylaina)


Lesenswert?

AtmegaNoob schrieb:
> void uart_init(void)
> 11{
> 12  UCSRB = (1 << TXEN);
> 13  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
> 14  UBRRL=0x05; // Baudrate festlegen
> 15  UBRRH=0x00; // Baudrate festlegen
> 16}

Ein Blick in die Baudraten-Tabelle im Datenblatt bei 16 MHz verrät mir, 
dass UBRR = 5 zu keiner typischen Baudrate passt, unabhängig davon wie 
U2Xn gesetzt wurde. Für die auskommentierten 3.6864 MHz und passt UBBR = 
5 bei U2Xn = 0 für die angegebenen 38k4. Fazit: Für das Eval-Board (das 
wahrscheinlich mit 16 MHz laufen wird) wird der Baudratenfehler 
schlichtweg zu groß sein.

von Wolfgang (Gast)


Lesenswert?

AtmegaNoob schrieb:
> Die ersten beiden Bytes sind ok und dann wird die zweite Byte 5 Mal
> widerholt.

Das ist ja widerlich.
Hast du dir das Signal und das genaue Timing vom TX des ATmega mit Oszi 
oder LA genau angesehen?

von AtmegaNoob (Gast)


Lesenswert?

Wolfgang schrieb:
> AtmegaNoob schrieb:
>> Die ersten beiden Bytes sind ok und dann wird die zweite Byte 5 Mal
>> widerholt.
>
> Das ist ja widerlich.
> Hast du dir das Signal und das genaue Timing vom TX des ATmega mit Oszi
> oder LA genau angesehen?


Also ich habe kein Oszi zu Hause.
Also beim C Code hsne ich bei hTerm eine Baudrate von 38400 angegeben.
Beim Assembler Code dem entsprechend 9600.

von AtmegaNoob (Gast)


Lesenswert?

M. K. schrieb:
> AtmegaNoob schrieb:
>> void uart_init(void)
>> 11{
>> 12  UCSRB = (1 << TXEN);
>> 13  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
>> 14  UBRRL=0x05; // Baudrate festlegen
>> 15  UBRRH=0x00; // Baudrate festlegen
>> 16}
>
> Ein Blick in die Baudraten-Tabelle im Datenblatt bei 16 MHz verrät mir,
> dass UBRR = 5 zu keiner typischen Baudrate passt, unabhängig davon wie
> U2Xn gesetzt wurde. Für die auskommentierten 3.6864 MHz und passt UBBR =
> 5 bei U2Xn = 0 für die angegebenen 38k4. Fazit: Für das Eval-Board (das
> wahrscheinlich mit 16 MHz laufen wird) wird der Baudratenfehler
> schlichtweg zu groß sein.


Danke für den Hinweis.
Also auf dem Board ist ein 16 Mhz Verbaut.

Werde ich korrigieren und testen  wenn ich wieder zu Hause bin.

von Georg G. (df2au)


Lesenswert?

AtmegaNoob schrieb:
> //#define CR "\0\r\n"

Auch, wenn es auskommentiert ist: Bitte denk über diese Zeile noch 
einmal intensiv nach. Die NULL am Ende des Strings setzt der Compiler 
automatisch. Am Anfang des Strings bewirkt sie ein vorzeitiges Ende.

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Mal zum Testen in Assembler probiert

Und läuft das oder nicht?
Für die direkte UBRR-Zuweisung siehe Anhang.

von S. Landolt (Gast)


Lesenswert?

>> Mal zum Testen in Assembler probiert
> Und läuft das oder nicht?

Nein, natürlich nicht: das zweite 'out SPL, temp' (in Zeile 33) muss 
'out UBRRL,temp' heißen.

von AtmegaNoob (Gast)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
>>> Mal zum Testen in Assembler probiert
>> Und läuft das oder nicht?
>
> Nein, natürlich nicht: das zweite 'out SPL, temp' (in Zeile 33) muss
> 'out UBRRL,temp' heißen.

Vielen Dank.


Mit folgendem (korrigiertem) Code erhalte ich nur lauter "0" angezeigt.
(Config in hterm: 8 Data, 2 Stop, 9600 Baud)
1
;
2
; Laboraufgabe 4 - (UART).asm
3
;
4
5
.include "m32def.inc"
6
7
.def temp = r16    ; Register für kleine Arbeiten
8
.def zeichen = r17  ; in diesem Register wird das Zeichen an die Ausgabefunktion übergeben
9
10
.equ F_CPU = 16000000  ; Systemtakt in Hz
11
.equ BAUD = 9600    ; Baudrate
12
13
; Berechnungen
14
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
15
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL)+1))    ; Reale Baudrate
16
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promile
17
18
.if((BAUD_ERROR>10) || (BAUD_ERROR<-10))  ; max +/- 10 Promile Fehler
19
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
20
.endif
21
22
; Stackpointer initialisieren
23
24
  ldi  temp,  HIGH(RAMEND)
25
  out SPH,  temp
26
  ldi  temp,  LOW(RAMEND)
27
  out  SPL,  temp
28
29
; Baudrate einstellen
30
31
  ldi  temp,  HIGH(UBRR_VAL)
32
  out UBRRH,  temp  
33
  ldi  temp,  LOW(UBRR_VAL)    
34
  out  UBRRL,  temp
35
36
; Frame-Format 8 Bit
37
38
  ldi  temp,  (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
39
  out UCSRC,  temp
40
41
  sbi UCSRB,  TXEN  ; TX aktivieren
42
43
; aus doc2503.pdf Seite 146
44
; 
45
; USART_Init:
46
; Set baud rate
47
; outUBRRH,  r17
48
; outUBRRL,  r16
49
; Enable receiver and transmitter
50
; ldi r16,  (1<<RXEN)|(1<<TXEN)
51
; out UCSRB,  r16
52
; Set frame format: 8data, 2stop bit
53
; ldi r16,  (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
54
; outUCSRC,  r16
55
; ret
56
57
  ldi  r16,  (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
58
  out  UCSRC,  r16
59
; ret
60
61
loop:
62
63
  ldi  zeichen,  'T'
64
  rcall  serout    ; Unterprogramm aufrufen
65
  ldi  zeichen,  'e'
66
  rcall  serout    ; Unterprogramm aufrufen
67
  ldi  zeichen,  's'
68
  rcall  serout    ; Unterprogramm aufrufen
69
  ldi  zeichen,  't'
70
  rcall  serout    ; Unterprogramm aufrufen
71
  ldi  zeichen,  '!'
72
  rcall  serout    ; Unterprogramm aufrufen
73
  ldi  zeichen,  10
74
  rcall  serout    ; Unterprogramm aufrufen
75
  ldi  zeichen,  13
76
  rcall  serout    ; Unterprogramm aufrufen
77
78
  rcall  serout
79
  rcall  sync
80
  rjmp  loop
81
82
serout:
83
  sbis  UCSRA,  UDRE  ; Warten bis UDR für das nächste Byte bereit ist
84
  rjmp  serout
85
  out  UDR,  zeichen  
86
  ret            ; zurücl zum Hauptprogramm
87
88
sync:
89
  ldi  r16,  0
90
sync_1:
91
  ldi  r17,  0
92
sync_loop:
93
  dec  r17
94
  brne  sync_loop
95
  dec  r16
96
  brne  sync_1
97
  ret

von S. Landolt (Gast)


Lesenswert?

> erhalte ich nur lauter "0" angezeigt

Tja - bei mir hier läuft "Test!" den Monitor hinunter; (der 
Zwillingsbruder) ATmega16 mit direkter Verbindung zum PC.

von AtmegaNoob (Gast)


Lesenswert?

Damke für die schnelle Antwort!



Liegt es vllt an (meiner) Verbindung vom Board (/Atmega) über den 
Adapter zum PC ? (Adapter->Board: GND->Pin 39, 5V ->Pin 40, TX/RX->Pin 
26/27)

Irdendwie kommt es mir gerade so vor, dass ich für das Offensichtliche 
zu blind bin duck und weg

Danke

von AtmegaNoob (Gast)


Angehängte Dateien:

Lesenswert?

-no Text-

von S. Landolt (Gast)


Lesenswert?

Zu Ihrer speziellen PC-Anbindung kann ich leider nichts sagen - ich habe 
nur besagte direkte sowie zwei andere per USB.

von S. Landolt (Gast)


Lesenswert?

? - Das um 19:14 gezeigte ist das alte HEX-File, das mit dem zweiten 
'out SPL, temp' statt des 'out UBRRL,temp'.

von S. Landolt (Gast)


Lesenswert?

Korrektur: das muss ein Zwischenstand sein, es entspricht meinem neuen 
File, mit Ausnahme dieser einen beschriebenen Zeile (und natürlich dem 
RAMEND (da ATmega16)).

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

Kehren wir das Vorgehen um - hier mein HEX-File, das muss bei Ihnen ohne 
Änderung laufen.

von Wolfgang (Gast)


Lesenswert?

AtmegaNoob schrieb:
> Liegt es vllt an (meiner) Verbindung vom Board (/Atmega) über den
> Adapter zum PC ?

Nimm einen Logik Analysator oder ein Oszilloskop und guck dir an, was 
dein ATmega rausgibt.
Dann ist der Adapter und die PC-Software raus - zwei Baustelle weniger.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

AtmegaNoob schrieb:
> Also ich habe kein Oszi zu Hause.
Beschaff dir eines. Denn nur mit einem Oszilloskop kannst du die 
Qualität des Signals bezüglich Pegel, Flankensteilheit, Überschwinger, 
Timing und Ströungen beurteilen. Wenn das alles passt, dann kann man 
im Protokoll weitersuchen.

Es ist mir ein völliges Rätsel, wie man serielle Busse ohne Oszilloskop 
anständig zum Laufen bekommen will.

AtmegaNoob schrieb:
> Auf einem Atmel Evalution Board
Welches "Board" von den vielen, die es gibt? Und wie ist das versorgt?

von M. K. (sylaina)


Lesenswert?

Lothar M. schrieb:
> Es ist mir ein völliges Rätsel, wie man serielle Busse ohne Oszilloskop
> anständig zum Laufen bekommen will.

Wie hat man es uns bei der BW beigebracht? Nur ein nicht abgegebener 
Schuss kann nicht treffen...ich glaube der ein und andere hat dieses 
Prinzip verinnerlicht und adaptiert es auf alles, was ihm zwischen die 
Finger kommt. Ich verstehe auch nicht, wie man ohne Oszi bei sowas 
wirklich effektiv weiter kommen will. In meinen Augen ist das zum Teil 
viel Stochern im Nebel in der Hoffnung mal nen Treffer zu landen.

von mitlesa (Gast)


Lesenswert?

Lothar M. schrieb:
> Welches "Board" von den vielen, die es gibt? Und wie ist das versorgt?

Das frage ich mich schon lange Zeit, und hinzu kommt die Aussage

AtmegaNoob schrieb:
> Adapter->Board: GND->Pin 39, 5V ->Pin 40, TX/RX->Pin 26/27

die zu "bezweifeln" ist. Ist denn Pin 39 ein echter bzw.
zulässiger Ground-Anschluss?

Wenn wir den TO dann endlich dazu bewegt haben ein Oszilloskop
zu kaufen oder wenigstens auszuleihen kommt dann eventell noch
die Aussage "ich habe alles mit dem Logikanalysator überprüft".
Nein, es muss ein Oszilloskop sein um den Spannungsverlauf
erkennen zu können.

von mitlesa (Gast)


Lesenswert?

Dann gibt es noch Zweifel ob es hier mit rechten Dingen zugeht:

AtmegaNoob schrieb:
> Adapter->Board: ........., 5V ->Pin 40, ........

Der VCC-Pin des FT232-Moduls hat - duch Jumper wählbar - entweder
3.3 oder 5V zu bieten. Das ist ein Ausgang, eine kleine
Quelle mit der man externe Controller versorgen kann. Werden
diese 5V an eine andere 5V-Quelle angeschlossen kommt es zu
einem Kampf der Giganten mit unvorhersehbaren Ausgang.

Merke: Ein FT232-Modul braucht keine Versorgung von aussen,
daher kann / sollte man den Vcc-Pin unbeschaltet lassen. Und
ein wie auch immer geartetes Eval-Board wird auch seine eigene
Versorgung mitbringen, einer von beiden Versorgern wird
zumindest irritiert reagieren können.

von S. Landolt (Gast)


Lesenswert?

Was auch immer an der Hardware fehlerhaft sein mag oder nicht - mit dem 
gestern abend gezeigten HEX-File läuft die UART mit 1.0 MBd, das kann 
nichts werden.

von Magnus M. (magnetus) Benutzerseite


Angehängte Dateien:

Lesenswert?

AtmegaNoob schrieb:
https://www.mikrocontroller.net/attachment/584886/fehler.png
> Mit folgendem (korrigiertem) Code erhalte ich nur lauter "0" angezeigt.
> (Config in hterm: 8 Data, 2 Stop, 9600 Baud)

Warum hast du in HTerm die Parität auf "EVEN" anstatt "NONE" gestellt?

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.