Forum: Mikrocontroller und Digitale Elektronik ATmega8: UART Übertragung fehleranfällig


von Stephan_S (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich beschäftige mich gerade mit der Kommunikation zwischen ATmega8 und 
dem PC. Ich verwende das Starterkit aus dem Microcontroller.net Shop 
sowie den obersten Code aus dem UART-Kapitel im AVR-Tutorial 
(http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART) Die einzige 
Anpassung habe ich beim Einstellen der Taktfrequenz des externen Takts 
vorgenommen, der bei 8Mhz liegt.

Mein Problem ist, dass die Übertragung zum PC nur sporadisch 
funktioniert und äußerst fehleranfällig ist, wie z.B. auf dem 
angehängten Screenshot zu sehen ist.

Die korrekte Übertragung müsste Test! in jeder Zeile liefern.

Hat jemand von den Experten eine Idee, was hier das Problem sein könnte?
Vielen Dank für Eure Hilfe!

Stephan

von Karl H. (kbuchegg)


Lesenswert?

Sieht mir entweder nach einem Wackelkontakt oder einem nicht stabilen 
Takt aus. Die Verwendung des internen 8Mhz RC-Schwingkreises könnte zb 
sowas erzeugen.

von Meisel (Gast)


Lesenswert?

Solche Zeichenwildwüchse deuten oft auf einen Stringüberlauf hin.

Aber da müsstest du schon deinen ganzen Quelltext zeigen.

Ansonsten: Woher hast du den Wert für das UBRR Register? Selbst 
ausgerechnet?
Im Datenblatt des Atmels sind sämtliche Werte für die gängigsten Quarze 
zu finden (+ Angabe zum prozentualen Fehler).

von Stephan_S (Gast)


Lesenswert?

Vielen Dank erst mal!
Hier der gesamte Quelltext:
1
 
2
.include "m8def.inc"
3
 
4
.def temp = R16
5
 
6
.equ F_CPU = 8000000                            ; Systemtakt in Hz
7
.equ BAUD  = 9600                               ; Baudrate
8
 
9
; Berechnungen
10
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
11
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
12
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
13
 
14
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
15
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
16
.endif
17
 
18
    ; Stackpointer initialisieren
19
 
20
    ldi     temp, HIGH(RAMEND)
21
    out     SPH, temp
22
    ldi     temp, LOW(RAMEND)
23
    out     SPL, temp
24
 
25
    ; Port D = Ausgang
26
 
27
    ldi     temp, 0xFF
28
    out     DDRD, temp
29
 
30
    ; Baudrate einstellen
31
 
32
    ldi     temp, HIGH(UBRR_VAL)
33
    out     UBRRH, temp
34
    ldi     temp, LOW(UBRR_VAL)
35
    out     UBRRL, temp
36
 
37
    ; Frame-Format: 8 Bit
38
 
39
    ldi     temp, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
40
    out     UCSRC, temp
41
 
42
    sbi     UCSRB, RXEN                     ; RX (Empfang) aktivieren
43
 
44
receive_loop:
45
   sbis     UCSRA, RXC                      ; warten bis ein Byte angekommen ist
46
   rjmp     receive_loop
47
   in       temp, UDR                       ; empfangenes Byte nach temp kopieren
48
   out      PORTD, temp                     ; und an Port D ausgeben.
49
   rjmp     receive_loop                    ; zurück zum Hauptprogramm

Ich verwende nicht den internen RC-Oszillator sondern einen externen 
Quarz. Dieser müsste eigentlich die geforderte Genauigkeit liefern.

von H.Joachim S. (crazyhorse)


Lesenswert?

Hm, das passt aber nicht zu deiner Terminalausgabe - du sendest doch gar 
nichts?

von Stephan_S (Gast)


Lesenswert?

Oh sorry, tut mir leid: Hab beim Kopieren im Eifer des Gefechts einen 
Codeteil unterschlagen. Hier nochmal der ganze Code:

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

Zum Thema Wackelkontakt: Hab jetzt mal alle unschönen Lötstellen nochmal 
nachgelötet, gebracht hats bisher leider nichts...

von Krapao (Gast)


Lesenswert?

Das sieht nach Störungen aus, die nicht von der Software kommen.

Ich würde an deiner Stelle die Hardware näher untersuchen, also den 
Aufbau des µC Boards und die Verbindung zwischen PC und µC. Bei COM14 
vermute ich, dass zusätzlich ein USB-RS232 Wandler im Spiel ist.

> Starterkit aus dem Microcontroller.net Shop

Dieses?

AVR Starterkit (inkl. USB Programmer)
http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=108

Dort kannst du den AVR aus der IC-Fassung entfernen und RXD-TXD an der 
Fassung brücken. Alle vom PC aus gesendeten Zeichen müssen dann 
fehlerfrei an den PC zurück kommen, wenn der Rest der Hardware OK ist 
(Loopback-Test).

von Karl H. (kbuchegg)


Lesenswert?

Auch mal an allen Kabeln und Steckern wackeln.

Ich hab zb einen USB Stick, den ich beim Einstecken etwas in eine 
Richtung 'verkanten' muss, sonst wird der Stick nicht korrekt erkannt. 
Nachweislich auf 5 Rechnern ausprobiert. Es liegt am Stick und dessen 
mechanischem Steckeraufbau.

von Falk B. (falk)


Lesenswert?

@  Karl Heinz Buchegger (kbuchegg) (Moderator)

>Ich hab zb einen USB Stick, den ich beim Einstecken etwas in eine
>Richtung 'verkanten' muss, sonst wird der Stick nicht korrekt erkannt.
>Nachweislich auf 5 Rechnern ausprobiert. Es liegt am Stick und dessen
>mechanischem Steckeraufbau.

Klingt nach Wackelkontakt oder kalter Lötstelle. Würde ich umgehend 
entsorgen.

von Stephan_S (Gast)


Lesenswert?

Vielen Dank für die weiteren Tipps!

Krapao schrieb:
>> Starterkit aus dem Microcontroller.net Shop
>
> Dieses?
>
> AVR Starterkit (inkl. USB Programmer)
> http://shop.embedded-projects.net/index.php?module...
>
> Dort kannst du den AVR aus der IC-Fassung entfernen und RXD-TXD an der
> Fassung brücken. Alle vom PC aus gesendeten Zeichen müssen dann
> fehlerfrei an den PC zurück kommen, wenn der Rest der Hardware OK ist
> (Loopback-Test).

Ja genau dieses Starterkit verwende ich! Den Loopback-Test habe ich 
durchgeführt -> Funktioniert! Wenn ich RXD und TXD brücke, dann kommen 
genau die eingegebenen Zeichen zurück (ohne Störungen)! (Ach ja, ein 
USB-RS232 ist auch im Spiel, aber an dem dürfte es ja dann auch nicht 
liegen,oder?)

Die richtige Folgerung wäre doch eigentlich, dass irgendwas an der 
Ausgabe des Controllers nicht stimmt!?! Um Verbindungsfehler 
auszuschließen habe ich auch die entscheidenden Pins zwischen MAX232 und 
µC direkt verbunden... erfolglos...
Oder der externe Quarz auf dem Board ist zu ungenau? Würde mich aber 
wundern, wenn das noch keinem zuvor aufgefallen wäre...

von spess53 (Gast)


Lesenswert?

Hi

>Oder der externe Quarz auf dem Board ist zu ungenau? Würde mich aber
>wundern, wenn das noch keinem zuvor aufgefallen wäre...

Unwahrscheinlich. Bist du Sicher, das der Quarzoszillator wirklich (per 
Fuse) aktiviert ist?

MfG Spess

von Stephan_S (Gast)


Lesenswert?

spess53 schrieb:
> Unwahrscheinlich. Bist du Sicher, das der Quarzoszillator wirklich (per
> Fuse) aktiviert ist?

Ich sag mal zu 99% ja.
Ich setz die Fuses übers AVR-Studio. Bei der Option SUT_CKSEL habe ich 
"Ext. Crystal/Resonator high Freq; Start-up time: 16 CK + 64ms" 
eingestellt. An den andren Fuses habe ich nichts verändert.
Dies führt dann zu folgender Bitkombination:

HIGH: 0xD9
LOW:  0x3F

Diese wiederum entspricht den Empfehlungen im Tutorial...
Weiß jetzt irgendwie nicht mehr weiter...

von Kai K. (klaas)


Lesenswert?

Mit dem Oszi mal angeschaut, was am Ende des Kabels ankommt? Stimmt das 
Timing für 9600 Baud? Ist da ein Wackler im Kabel? Gehts mit einem 
anderen Kabel?

von Paul B. (paul_baumann)


Lesenswert?

Miss mal von Anschluß 2 und Anschluß 6 des MAX232 gegen Masse, ob da
ca +10 Volt bzw. -10 Volt anstehen.

Ich hatte auch mal so ein Fehlerbild wie Du und da lag es an dem MAX232.
Von 10 Stück hatte einer eine Macke.

MfG Paul

von Stephan_S (Gast)


Lesenswert?

Also ich hab jetzt nochmal etwas rumgespielt und verschiedenste Sachen 
ausprobiert (auch Kabel z.T. erneuert etc.) und jetzt funktioniert es 
tatsächlich.

Vielen Dank nochmal für eure Hilfe!

von Kai K. (klaas)


Lesenswert?

>Also ich hab jetzt nochmal etwas rumgespielt und verschiedenste Sachen
>ausprobiert (auch Kabel z.T. erneuert etc.) und jetzt funktioniert es
>tatsächlich.
>
>Vielen Dank nochmal für eure Hilfe!

Und woran lag es jetzt?

von Stephan_S (Gast)


Lesenswert?

So wie es aussieht war es tatsächlich ein Wackelkontakt an einer 
Lötstelle, wie bereits von ein paar Seiten vermutet wurde.

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.