Lektor
28.07.2006, 10:51
Mein UART überträgt falsche Daten. Woran könnte es liegen und wie kann ich es beheben?
Zur Emulation meiner Solaranlage habe ich ein Programm in meinen µC geschrieben, welches wie die Solaranlage, im Sekundentakt 58 Bytes über die serielle Schnittstelle an den PC senden soll. Damit ich nicht die ganze Zeit im Keller verbringe sollte der µC in gleicher Weise Daten an den PC schicken, wie es auch die Solaranlage tut, damit ich im Büro ein Labviewprogramm erarbeiten kann.
Hier mal der einfache Code des Programms. Am Ende des Codebeispiels habe ich nochmal übersichtlich aufgelistet, welche Bytes gesendet werden sollen und welche Bytes HTerm anzeigt.
.include "m8def.inc"
.def temp = r16
.equ CLOCK = 8000000 ; interner Oszi
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
reset: ; Stackpointer initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
;---------------Uart---------------------
; Baudrate einstellen
ldi temp, LOW(UBRRVAL)
out UBRRL, temp
ldi temp, HIGH(UBRRVAL)
out UBRRH, temp
; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren
;--------------/Uart----------------------
loop:
rcall onesekond
;zu sendende Bytefolge (58 Bytes)
;AA 10 00 10 52 10 00 01 08 74 0B 01 77 01 01 7A 06 01 38 22 05 19 5C
;00 00 64 01 3E 00 00 2D 01 00 51 00 00 00 00 00 7F 00 00 01 0D 00 71
;00 00 00 02 00 7D 21 02 21 02 05 34
ldi temp, 0xAA
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x00
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x52
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x00
rcall serout
ldi temp , 0x01
rcall serout
ldi temp , 0x08
rcall serout
ldi temp , 0x74
rcall serout
ldi temp , 0x0B
rcall serout
rjmp loop
serout:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp serout
out UDR, temp
ret ; zurück zum Hauptprogramm
onesekond:
; =============================
; delay loop generator
; 8000000 cycles:
; -----------------------------
; delaying 7999992 cycles:
ldi R17, $48
WGLOOP0: ldi R18, $BC
WGLOOP1: ldi R19, $C4
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 6 cycles:
ldi R17, $02
WGLOOP3: dec R17
brne WGLOOP3
; -----------------------------
; delaying 2 cycles:
nop
nop
; =============================
ret
;----------------------------------
;gewünscht war
;AA 10 00 10 52 10 00 01 08 74 0B
;Resultat mit HTerm ausgelesen
;AA 90 80 90 D2 90 80 81 88 F4 0B
;AA 10 00 10 D2 90 80 81 88 F4 8B
;AA 90 80 90 D2 90 80 01 08 74 0B
;AA 90 80 10 52 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 88 F4 8B
;AA 90 80 90 D2 90 80 81 88 74 0B
;AA 90 80 90 D2 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 08 F4 8B
;AA 90 80 90 D2 90 80 81 88 F4 8B
;-----------------------------------
Das AA am Anfang war komischerweise immer richtig.
Könnte mir folgende Fehlermöglichkeiten vorstellen.
-Störungen auf den Leitungen, da ziemlich provisorisch auf Steckbrett aufgebaut.
-Takt stimmt nicht 100%ig und die 9600 Baut werden nicht eingehalten.
Ihr habt sicherlich wesentlich mehr Erfahrung mit RS232 und vielleicht könnt ihr mir ja beantworten, wie man dieses Problem vermeidet.
Zur Emulation meiner Solaranlage habe ich ein Programm in meinen µC geschrieben, welches wie die Solaranlage, im Sekundentakt 58 Bytes über die serielle Schnittstelle an den PC senden soll. Damit ich nicht die ganze Zeit im Keller verbringe sollte der µC in gleicher Weise Daten an den PC schicken, wie es auch die Solaranlage tut, damit ich im Büro ein Labviewprogramm erarbeiten kann.
Hier mal der einfache Code des Programms. Am Ende des Codebeispiels habe ich nochmal übersichtlich aufgelistet, welche Bytes gesendet werden sollen und welche Bytes HTerm anzeigt.
.include "m8def.inc"
.def temp = r16
.equ CLOCK = 8000000 ; interner Oszi
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
reset: ; Stackpointer initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
;---------------Uart---------------------
; Baudrate einstellen
ldi temp, LOW(UBRRVAL)
out UBRRL, temp
ldi temp, HIGH(UBRRVAL)
out UBRRH, temp
; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren
;--------------/Uart----------------------
loop:
rcall onesekond
;zu sendende Bytefolge (58 Bytes)
;AA 10 00 10 52 10 00 01 08 74 0B 01 77 01 01 7A 06 01 38 22 05 19 5C
;00 00 64 01 3E 00 00 2D 01 00 51 00 00 00 00 00 7F 00 00 01 0D 00 71
;00 00 00 02 00 7D 21 02 21 02 05 34
ldi temp, 0xAA
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x00
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x52
rcall serout
ldi temp , 0x10
rcall serout
ldi temp , 0x00
rcall serout
ldi temp , 0x01
rcall serout
ldi temp , 0x08
rcall serout
ldi temp , 0x74
rcall serout
ldi temp , 0x0B
rcall serout
rjmp loop
serout:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp serout
out UDR, temp
ret ; zurück zum Hauptprogramm
onesekond:
; =============================
; delay loop generator
; 8000000 cycles:
; -----------------------------
; delaying 7999992 cycles:
ldi R17, $48
WGLOOP0: ldi R18, $BC
WGLOOP1: ldi R19, $C4
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 6 cycles:
ldi R17, $02
WGLOOP3: dec R17
brne WGLOOP3
; -----------------------------
; delaying 2 cycles:
nop
nop
; =============================
ret
;----------------------------------
;gewünscht war
;AA 10 00 10 52 10 00 01 08 74 0B
;Resultat mit HTerm ausgelesen
;AA 90 80 90 D2 90 80 81 88 F4 0B
;AA 10 00 10 D2 90 80 81 88 F4 8B
;AA 90 80 90 D2 90 80 01 08 74 0B
;AA 90 80 10 52 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 88 F4 8B
;AA 90 80 90 D2 90 80 81 88 74 0B
;AA 90 80 90 D2 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 08 74 0B
;AA 10 00 10 52 10 00 01 08 F4 8B
;AA 90 80 90 D2 90 80 81 88 F4 8B
;-----------------------------------
Das AA am Anfang war komischerweise immer richtig.
Könnte mir folgende Fehlermöglichkeiten vorstellen.
-Störungen auf den Leitungen, da ziemlich provisorisch auf Steckbrett aufgebaut.
-Takt stimmt nicht 100%ig und die 9600 Baut werden nicht eingehalten.
Ihr habt sicherlich wesentlich mehr Erfahrung mit RS232 und vielleicht könnt ihr mir ja beantworten, wie man dieses Problem vermeidet.