Atmega Uart - Falsche Byte Übertragung

Gast #7317725
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!

#7317740
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.

Gast #7317772
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.

Gast #7317775
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.

Gast #7319569
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
Angehängte Dateien:
Gast #7319605
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

Moderator (Firma: Titel) Persönliche Seite #7319942
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?

#7320038
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.

Gast #7320054
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.

Gast #7320085
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren