-
Hallo,
Fehler lag bei mir ](*,) , so ist das wenn man den Code nicht genau testet, nur schnell überfliegt....
also :
in der Zeile mit ;springe über die Adressen
steht adiw ZL,3
soll stehen adiw ZL,2
sonst landet er ein Byte zu weit und vergleicht nur Dreck #-o
Außerdem überprüft die routine nicht, ob ein Leerzeichen am Ende ist oder nicht,
also hilfe + # ergibt 6 Bytes, also 3 Worte, ist ok. test + # ergibt 5 Bytes, der Assembler addiert noch ein null Byte hinten dran (müßte eigentlich als Warnung ausgegeben werden ),
dann stimmt die Adressierung mit adiw ZL,2 auch nicht mehr...
Lösungen:
Befehle benutzen, die ungerade Anzahl, der Bytes haben, damit das mit # wieder gerade gibt,
oder Befehle mit Leerzeichen am Ende , damit das Ergebnis immer gerade ist z.B.
"test# " , und dann danach prüfen und entsprechend 1 Byte weiterspringen...
Ich war heute Faul und habe aus Deinen test teste gemacht O:)
Hier nochmal Code, der Funktioniert:
Code:
.include "../../m8def.inc"
;Definition für Clock und Baudrate
.equ CLOCK = 10000000; Processortaktfrequenz
.equ BAUD = 9600 ; Serielle Schnittstelle Baudrate
.equ UBRRVAL = CLOCK / (BAUD*16)-1
;Definition für Flagregister und Flaggen
.def Flagregister = R16 ; Anzeige Flag Register
.def tmp = R17 ;universallregister
.equ zeileempfangen = 7 ; Eine vollständige Zeile über UART empfangen
;Definition für Zeichen
.equ enter = $0D ; Wagenrücklauf-Zeichen für UART
;Definition für SRAM Puffer
.equ pufferzeiger = $0060 ; UART Rx Pufferzeiger
.equ pufferanfang = $0061 ; Uart Rx Pufferanfang
.equ pufferende = $007E ; Uart Rx Pufferende
;Interrupt-Vektoren
.org 0x000
rjmp reset ;reset Vektor
.org URXCaddr
rjmp empfangen
reset:
;Stack
ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
;UART
;Baudrate einstellen
ldi tmp,UBRRVAL
out UBRRL,tmp
;Frameformat 8Bit
ldi tmp,(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
out UCSRC,tmp
;RX aktivieren
sbi UCSRB,RXEN
sbi UCSRB,RXCIE
;TX aktivieren
sbi UCSRB,TXEN
sei
loop: ;Hauptschleife
tst Flagregister ;Irgendeine Flagge gesetzt?
breq loop ;wenn nein langweilen
ldi tmp,LOW(loop) ; Schleifenanfang als Rücksprungadresse auf den Stapel
push tmp
ldi tmp,HIGH(loop)
push tmp
sbrs Flagregister,zeileempfangen ;teste, ob eine Zeile Komplet ist
ret ;wenn nein langweilen
befehlauswerten:
ldi tmp,LOW(UartRxRet) ; Rueckkehradresse UartRxRet auf Stapel
push tmp
ldi tmp,HIGH(UartRxRet)
push tmp
ldi ZH,HIGH(2 * Cmds) ; Z zeigt auf Befehlsliste
ldi ZL,LOW(2 * Cmds)
befehlauswerten1:
lpm ;Hole Zeichen
mov tmp,R0
cpi tmp,0xFF ; 0xFF signalisiert das ende der Befehlsliste
brne befehlauswerten3
befehlauswerten2: ;Ende der liste, unbekannter Befehl
ldi ZH,HIGH(2 * kennenicht) ;Sende Fehlermeldung
ldi ZL,LOW(2 * kennenicht)
rjmp UARTSend
befehlauswerten3: ;hier fangen wir an zu vergleichen
ldi XH,HIGH(pufferanfang) ;X auf empfangene Zeile
ldi XL,LOW(pufferanfang)
befehlauswerten4:
lds tmp,pufferzeiger;Pufferzeiger lesen
cp XL,tmp ;Ende des Puffers erreicht?
brcs befehlauswerten7 ;nein weiter
befehlauswerten5:
lpm ;lese nächstes Befehlszeichen
adiw ZL,1 ;Z auf nächstes zeichen
mov tmp,R0
cpi tmp,'#' ;Endzeichen erreicht?
brne befehlauswerten5
befehlauswerten6:
adiw ZL,2 ;Springe über die Adressen
rjmp befehlauswerten1 ;nächster Befehl
befehlauswerten7:
lpm
mov tmp,R0
cpi tmp,'#' ;Ende des Befehls?
breq befehlauswerten8
ld tmp,X+ ;lese nächstes Zeichen aus Puffer
cp tmp,R0 ;Vergleiche
brne befehlauswerten5
adiw ZL,1 ;nächstes Zeichen
rjmp befehlauswerten4
befehlauswerten8:
lds tmp,pufferzeiger ;ende des Puffers erreicht?
cpc XL,tmp
brcc befehlauswerten2
adiw ZL,1
lpm
push R0
adiw ZL,1
lpm
push R0
ret
UartSend:
lpm;lese aus dem Flash
adiw ZL,1
tst R0
brne UartSendR0
ret
UartSendR0:
mov tmp,R0
rcall UARTSendChar
rjmp UartSend
UartSendChar:
sbis UCSRA,UDRE
rjmp UartSendChar
out UDR,tmp
ret
UartRXret:
ldi tmp,LOW(pufferanfang)
sts pufferzeiger,tmp
cbr Flagregister,(1<<zeileempfangen)
ret
help:
ldi ZH,HIGH(2*UartTxtHelp) ; Hilfetext
ldi ZL,LOW(2*UartTxtHelp)
rjmp UartSend
test:
ldi ZH,HIGH(2*test_txt) ; Hilfetext
ldi ZL,LOW(2*test_txt)
rjmp UartSend
nochmal:
ldi ZH,HIGH(2*nochmal_txt) ;Befehl3
ldi ZL,LOW(2*nochmal_txt)
rjmp UartSend
empfangen:
push tmp ;rette universallregister
in tmp,SREG ;rette SREG
push tmp
in tmp,UDR ;Hole das empfangene Zeichen
out UDR,tmp ;Echo zurück
push ZH ;sichere Z-Register
push ZL ;dito
ldi ZH,HIGH(pufferanfang) ;position fürs nächste Zeichen MSB
lds ZL,pufferzeiger
st Z+,tmp ;Speichere Zeichen im sram
cpi ZL,LOW(pufferende+1) ;Pufferende erreicht ?
brcc empfangen_ ;Pufferüberlauf
sts pufferzeiger,ZL ;speichere nächste Pufferposition
empfangen_:
cpi tmp,enter ;Wagenrücklauf?
brne empfangen__
sbr Flagregister,(1<<zeileempfangen)
empfangen__:
pop ZL ;Stelle Z-Register wieder her
pop ZH ;dito
pop tmp ;Stelle SREG wieder her
out SREG,tmp ;dito
pop tmp ;stelle tmp wieder her
reti ;verlasse Routine und schalte Interrupts wieder ein
;Hier fangen die Befehle an:
;alle Befehle müssen mit # terminiert werden
Cmds:
.db "hilfe#"
.dw help
.db "teste#"
.dw test
.db "nochmal#"
.dw nochmal
;0xFFFF muß zum schluß stehen, um ende der liste zu erkennen
.dw 0xFFFF
;Ende der Befehldefinition
;Texte
UartTxtHelp:
.db "Das ist ein Hilfe Text ",0x0D,0x0A,0x00
test_txt:
.db "Das ist ein Test ",0x0D,0x0A,0x00
nochmal_txt:
.db "Ich hoffe, daß alles in Ordnung ist",0x0D,0x0A,0x00
kennenicht:
.db "Ich weiss nicht, was Du von mir willst ",0x0D,0x0A,0x00
So muß es klappen,ändere nur Clock und *inc.
Achso...
Willst Du mit dem Befehl, etwas machen, ohne ein Text zurückzuschicken muß am schluß von der entspechenden sprungroutine ein ret stehen und kein rjmp UartSend
Ich hoffe, daß ich helfen konnte
Gruß Sebastian
-
Danke. Werds gleich mal testen.
MfG
Christian
-
OK. Funktioniert so weit.
Wenn ich noch probleme habe rühre ich mich wieder.
Gruß
Christian
-
freut mich,
viel Spaß damit.
Gruß Sebastian