PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ASCII-Zeichen-String auswerten in Assembler



Kagerer
05.07.2005, 17:52
Hallo,

ist es auf einfache Weise möglich, wenn ich über das UART z.B. "+cbc: 1,100" empfange, dass der AVR dann einen Befehl ausführt (z.B. rjmp Netzbetrieb)?

MfG
Christian

PicNick
05.07.2005, 18:10
"einfach" ist eine Intepretationssache. Im Assembler ist das bestimmt ein Gefummel, das nicht jeder gerne mag.
BasCom z.B. bietet für solche Stringvergleiche einige Komfort.
Wenn du also nicht auf dem letzten Drücker an Geschwindigkeit arbeitest, würde ich dir raten, dich mit einer solchen höheren Sprache anzufreunden.
Ich sag' das nicht, um dich abzuwimmeln. Aber Assembler ist schon eine etwas verschärfte Angelegenheit.

Florian
05.07.2005, 18:26
Hallo Christian!
Ich hab das ganze mal programmiert, dass nach einem '#' ein befehl steht, mal sehn, ob ich den Code noch irgendwo finde!
Sobald ich dann mit einem Terminalprogramm ein '#' gesendet habe, sprang der AVR in eine Routine, in der abgefragt wurde, was die nächsten 3 Zeichen waren, und dann wurde das mit einer Tabelle aus dem Speicher verglichen und ausgeführt.
War kein '#', dann führte der AVR keinen Befehl aus, sondern stellte nur das ASCII-Zeichen auf dem LCD dar!

*ich suche mal ... bzw. heute werde ich es nicht mehr schaffen die CD's durchzusehen, vielleicht hilft es Dir ja so weiter!?*

Kagerer
05.07.2005, 19:29
Hi! Danke für die schnellen Antworten.

@PicNick
Hab momentan eigentlich nicht vor auf eine eine höhere Programmiersprache umzusteigen. Ich versuche mir momentan C++ beizubringen. Denke nicht, dass es eine gute Idee ist nebenbei auch noch BasCom oder C für AVR zu lernen. Wenn ich C++ mal kann dürfte es ja nicht mehr so schwer sein auch C für AVR's zu erlernen.

@Florian
Wäre super, wennst du den Code findest. Würde mir bestimmt helfen.

Gruß
Christian

Florian
05.07.2005, 21:21
Hallo Christian!
Ich finde den Code leider zwischen den ganzen Daten der Backup-CD's leider nicht mehr! :o(
Ich werde versuchen ihn morgen wieder neu zu schreiben, der Code war aber glaube ich kein allzu großes Problem!

Kagerer
06.07.2005, 18:13
Danke Florian!

Hab zwar auch schon eine Idee, muss aber erst noch am Wochenende ausprobieren obs funktioniert.

MfG
Christian

Florian
06.07.2005, 18:51
Hallo Christian!
Ist es schlimm, wenn ich Dir den Code erst Anfang nächster Woche liefere?
Ich stecke gerade in Vorbereitungen für meinen Geburtstag bzw. die Feier dazu und das Wochenende wird gefeiert, also kaum eine Chance bzw. Energie, um den Code zu schreiben!
Ich versuche den Code zu Montag hinzubekommen, versprechen kann ich natürlich nichts! ;o)

Kagerer
06.07.2005, 19:23
Ist natürlich nicht schlimm ;-)

Ich kann ja warten! Is ja auch nicht so wichtig. Werd am Wochenende auch selber mal was ausprobieren.

MfG
Christian

Florian
07.07.2005, 14:35
Hallo Christian!
Ich bin jetzt fast fertig mit dem Code! :o)
Ich muss nur noch ein problem mit der Sprungreichweite lösen, dann ist der Code fertig! ;o)

*habe mich extra beeilt*

Kagerer
07.07.2005, 16:46
Danke, ist super nett von dir. Hättest dich aber gar nicht so beeilen müssen.

MfG
Christian

James
07.07.2005, 19:17
also ich habs so gemacht:
ich hab geschaut was das erste zeichen ist. dann bin ich in die entsprechende unterroutine gesprungen und die hat dann das nächste zeichen angeschaut und dann wieder in die entsprechende unterroutine. wenn die strings nur aus 2 oder 3 bytes bestehen, geht das ganz gut.
ansonsten must du dir halt so vergleichsroutinen schreiben.

mfg
Bernhard

Florian
07.07.2005, 19:20
Hallo Christian, hallo Bernhard!
ich müsste gleich fertig sein, ich versehe den Code gerade noch mit Kommentaren!
Ich bin gespannt, was ihr dazu sagt! ;o)

Florian
07.07.2005, 19:56
Hallo Christian, hallo Bernhard!
Ich bin endlich fertig! *freu*
Was haltet ihr von dem Code?
Habt ihr Fragen?
Ich habe den Code mehrere Male simuliert, aber noch nicht in Real ausprobiert!
Ich bin gespannt!

Viel Spass damit
Florian



PS: Ich hatte selber daran interessiert den Code zu programmieren, ich brauche ihn nämlich demnächst auch mal wieder!
Außerdem hatte ich ein wenig Zeit übrig und der Spass kam auch nicht zu kurz! ;o)

izaseba
07.07.2005, 20:48
Hallo Florian,
Ich habe mir Deinen Code angeschaut, und hätte da ein paar Verbeserungsvorschläge,
ich habe bis jetzt keine Routine dieser Art geschrieben, aber erst vor kurzem ein Code analysiert und man hat es folgendermaßen gelöst:
- Kein extra Register für jedes Zeichen sondern ein Puffer im Sram, wo die empfangenen Zeichen verschoben werden.
- In der Interrupt Routine wird nur geprüft, ob ein Wagenrücklauf gesendet wurde oder der Puffer nicht überläuft, was auch das Ende des Befehls bedeuten würde, sollte das eintreffen, wird eine Befehlkomplett Flagge gesetzt, die in dem Hauptprogramm entsprechend überprüft wird,
außerdem wird dort das empfangene Zeichen zurück in UDR geschoben, um es an das Terminalfenster zurückzuschicken (echo)
Vorteil: Kurze Interruptroutine und keine rcalls daraus, was man sowieso nicht machen sollte.

Wenn dann die Befehl komplett Flagge im Hauptprogramm erkannt wird, kann man den Pufferinhalt mit den Befehlen, die in .db , oder wo auch immer liegen vergleichen, und entsprechend verzweigen.

Ich hoffe, ich hab mich verständlich ausgedrückt.
Bei Bedarf kann ich den Schnipsel raussuchen und hier reinsetzen.

Gruß Sebastian

Florian
07.07.2005, 21:21
Hallo Sebastian!
Ich werde versuchen demnächst (nach der ganzen Partyzeit) den Code zu verbessern!
Ich habe zwar auch schon davon gehört, dass man keine rcalls in Interruptroutinen verwenden soll, aber ich kann das nicht nachvollziehen!


Bei Bedarf kann ich den Schnipsel raussuchen und hier reinsetzen.Das wäre natürlich noch besser! ;o)

izaseba
08.07.2005, 00:36
Hallo Florian,

Da ich sowieso nicht schlafen konnte, habe ich hier ein Beispielprogramm geschrieben.
Es arbeiet mit einem sram Puffer, hollt also alle Zeichen, die empfangen werden in den Speicher, und erst nachdem man Return betätigt hat wird der Puffer ausgewertet.
Es hat auch eine kurze interrupt routine, und verwendet Flags bzw. nur eine Flagge, die in der loop routine permanent abgefragt wird.
Zugegeben, so schlau bin ich noch nicht, um mir das ganze so auszudenken, :-b
Den Code habe ich mir hier (http://www.avr-asm-tutorial.net/avr_de/index.html) unter Akkuloader abgeschaut und etwas abgeändert.
Das hat der Gerd richtig gut programmiert.
Als Beispiel empfängt es zeichen , wenn man hilfe eintipt wird ein Text ausgegeben, amsonsten eine Fehlermeldung.
Man kann sehr einfach weitere Befehle interpretieren und nach ein paar kleinen Änderungen auch Parameter übergeben...
Ich hoffe, daß ich es ausreichend kommentiert habe, wenn Fragen auftretten, frag mal ruhig, vielleicht kann ich sie auch beantworten.
Was man für sich ändern muß ist nur der Pfad zu der *.inc Datei, sowie Clock und Baudrate.

Gruß Sebastian


.include "../../m8def.inc"

;Definition für Clock und Baudrate
.equ CLOCK = 12000000 ; 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,3 ;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

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
;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
kennenicht:
.db "Ich weiß nicht, was Du von mir willst",0x0D,0x0A,0x00

Florian
08.07.2005, 06:01
Hallo Sebastian!
Danke für den Code!
Ich werde ihn mir wohl leider erst Sonntag ansehen können!

Kagerer
08.07.2005, 13:42
Danke Leute!!!

Ich werd mir die Codes gleich mal anschauen.


also ich habs so gemacht:
ich hab geschaut was das erste zeichen ist. dann bin ich in die entsprechende unterroutine gesprungen und die hat dann das nächste zeichen angeschaut und dann wieder in die entsprechende unterroutine. wenn die strings nur aus 2 oder 3 bytes bestehen, geht das ganz gut.
ansonsten must du dir halt so vergleichsroutinen schreiben.

So hätte ich es auch selber versucht. Wollt dann nur mal wissen ob es eine elegantere Lösung gibt.

MfG
Christian

Kagerer
10.07.2005, 10:59
Also die Codes sind beide nicht schlecht. Aber um den von izaseba ganz zu kapieren werde ich wohl noch eine weile brauchen ;-).

MfG
Christian

izaseba
10.07.2005, 13:04
Aber um den von izaseba ganz zu kapieren werde ich wohl noch eine weile brauchen

Hmmm, was verstehst Du nicht?

Geh mal den Assemblertutorial auf der von mir oben genannten Seite mal durch,
dann wirst Du mehr verstehen O:)

Gruß Sebastian

Kagerer
10.07.2005, 15:11
Danke hab mir das Tutorial schon mal ausgedurck, bin bloß noch nicht durch. Ich beschäftige mich ja auch erst seit kurzen mit µC.

Momentan hab ich aber ein anderes Problem, dass ich erst lösen muss. Ich hab irgendwie meinen USBisp eliminiert. Er will nix mehr programmieren :-(

MfG
Christian

Kagerer
14.07.2005, 19:16
Ich glaub ich hab den Code jetzt gecheckt. Wenn ich beim umschreiben für meine Anwendung noch auf Probleme stoße, melde ich mich nochmal.

MfG
Christian

SprinterSB
15.07.2005, 09:59
So was in der Richtung?
Für avr-as


.arch atmega8

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

.section .progmem.data,"a",@progbits

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

.type STR_1, @object
.size STR_1, 8
STR_1:
.string "blubb 1"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

.type STR_2, @object
.size STR_2, 10
STR_2:
.string "blubber 2"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

.type labels, @object
.size labels, 12

labels:
.word pm(.LABEL_1)
.word STR_1

.word pm(.LABEL_2)
.word STR_2

; ...

.word 0
.word -1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

; my_strcmp: Vergleiche zwei Strings
; r25:r24 ist Adresse eines Strings im RAM
; r23:r22 ist Adresse eines Strings im FLASH
; ret=r24=0: ungleich
; ret=r24=1: gleich
; veränderte Register: 24, 25, X, Z

.text
.global my_strcmp
.type my_strcmp, @function
my_strcmp:

movw r26,r24
movw r30,r22
0:
; 1 Zeichen aus RAM
ld r25, X+

; 1 Zeichen aus FLASH
lpm r24, Z+

; vergleichen
cp r25,r24
brne 0f

; bei Gleichheit: ist String zu Ende?
tst r25
; nein: weiter vergleichen
brne 0b

; ja: Übereinstimmung
ldi r24,lo8(1)
ret
0:
; bei Ungleichheit: return 0
ldi r24,lo8(0)
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

; jump_if: Vergleicht den String cmd im RAM mit den
; Strings STR_1, STR_2, ... ausm Flash und springt bei
; Übereinstimmung zu .LABEL_1 bzw LABEL_2 bzw ...
; ret=r24=0: cmd nicht gefunden
; ret=r24=1: cmd gefunden und ausgeführt
; Veränderte Register: 22 -- 31

.text
.global jump_if
.type jump_if, @function
jump_if:

ldi r28,lo8(labels)
ldi r29,hi8(labels)
.loop
movw r30,r28
adiw r30,2

; Adresse eines Strings ausm Flash nach r23:r22
lpm r22, Z+
lpm r23, Z

; Ende der Liste? (cmd nicht gefunden)
ldi r24,hi8(-1)
cpi r22,lo8(-1)
cpc r23,r24
breq .not_found

; Zeiger auf labels 1 weiter
adiw r28,4

; Adresse von cmd nach r25:r24
ldi r24,lo8(cmd)
ldi r25,hi8(cmd)

; Vergleichen von cmd mit STR_n
rcall my_strcmp
tst r24

; keine Übereinstimmung (r24=0): weiter suchen
breq .loop

; Gefunden: Sprungadresse laden und indirekter Sprung
movw r30,r28
lpm r24, Z+
lpm r25, Z
push r24
push r25
ret

.LABEL_1:
; Code fuer STR_1
rjmp .done

.LABEL_2:
; Code fuer STR_2
rjmp .done

.not_found:
; Code fuer cmd nicht gefunden
ldi r24,lo8(0)

.done:
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;

.comm cmd,20,1

Kagerer
15.07.2005, 13:25
Danke.

Wenn ichs nicht schaffe den anderen Code für meine Anwendung anzupassen, werde ich mir deinen mal genauer anschauen.

MfG
Christian

Kagerer
16.07.2005, 15:59
Hallo.

Hab den Code anscheinend doch nicht so gut begriffen wie ich gemeint hätte.

Ich schaffe es jetzt doch nicht den Code von Sebastian so umzuschreiben, dass er wenn er "+CBC: 0,80" anstatt wie im Beispiel "hilfe#" zu etwas springt. Bekomme es ja nicht mal hin das er anstatt bei "hilfe#" bei "hilfe" zu help springt. Kann das Ende eines Befehls mit "#" leider bei meiner Anwendung nicht realisieren. Hab nämlich ein Handy an meinem µC hängen.

MfG
Christian

izaseba
16.07.2005, 16:33
dann nimm doch ein anderes zeichen als Abschluß.....

Kagerer
16.07.2005, 18:25
Das ist ein gutes Argument ;-) Ich brauche ja blos eine "0" nehmen.

Aber trozdem bekomme ich es nicht zusammen das Prog von "hilfe#" auf "test#" umzuschreiben. Muss ich da mehr austauschen als nur das "hilfe#" unter Cmds? Und wie geht es eigetlich, dass er bei "hilfe#" zu help springt und bei "test#" zu test?

MfG
Christian

izaseba
16.07.2005, 18:53
Muss ich da mehr austauschen als nur das "hilfe#" unter Cmds?


Pass auf, ganz unten steht ja
db "hilfe#"
dw help

Das heißt wenn hilfe empfangen wurde soll er zu Label help springen.
Du kannst direkt drunter
db "test#"
dw test
schreiben, dann mußt Du irgendwo in Code ein label mit test: setzen der mit ret beendet wird.
Ich hoffe, daß du es jetzt besser verstehst.

Gruß Sebastian
und wenn Du # gegen was anderes wechseln willst mußt Du bei befehlauswerten5 und befehlauswerten7
die Zeichen auch wechseln, die dürfen aber nicht im Befelh stehen, sonst klappt es nicht also nicht als abschluß 0 nehmen und dann Befehle wie fahre200

Kagerer
16.07.2005, 19:19
OK Danke. Werd ich dann mal versuchen.

Das mit dem # mit 0 auszutauschen war ausnahmsweise mal klar ;-).

Ich sehe schon, ich muss mich mehr mit Assembler beschäftigen.

Gruß
Christian

Kagerer
17.07.2005, 11:07
Hallo.

Ich hab jetzt mal versucht, dass er bei "test#" zu "test:" springt. Er gibt aber wenn ich test# eingebe immer nur aus "Ich weiss nicht, was Du von mir willst" anstatt "Das ist ein Test". Hier mal der Code:



.include "m16def.inc"

;Definition für Clock und Baudrate
.equ CLOCK = 16000000 ; 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,3 ;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

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 "test#"
.dw test
;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
kennenicht:
.db "Ich weiss nicht, was Du von mir willst",0x0D,0x0A,0x00


MfG
Christian

izaseba
17.07.2005, 14:28
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:



.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

Kagerer
17.07.2005, 17:27
Danke. Werds gleich mal testen.

MfG
Christian

Kagerer
17.07.2005, 17:39
OK. Funktioniert so weit.

Wenn ich noch probleme habe rühre ich mich wieder.

Gruß
Christian

izaseba
17.07.2005, 18:04
freut mich,
viel Spaß damit.

Gruß Sebastian