Kann man solch eine Eingabeafforderung auch noch etwas einfacher
gestallten? So das ich im Flasch zB irgendwo die Befehle hinterlege und
die dann überprüfe? Funktionieren tut das ganze so ja schon mal ganz
gut... Getestet auf STK 500
Bekannter Bug: Befehle wie cllp werden als help interpretiert da dafür
keine abrage stadtfindet.
Baut wie aus dem Tut ausser anderer Quarz.
Hyperterminal wie im Tut
Aktuelle Befehle: help, cls
1
.include "m8def.inc" ; bzw. 2333def.inc
2
3
.equ CLOCK = 7372800
4
.equ BAUD = 9600
5
.equ UBRRVAL = CLOCK/(BAUD*16)-1
6
7
.org 0x00
8
rjmp inistart
9
10
.org URXCaddr ; Interruptvektor für UART-Empfang
11
rjmp int_rxc
12
13
; Inizaliesierung
14
inistart:
15
16
ldi r16, LOW(RAMEND)
17
out SPL, r16
18
ldi r16, HIGH(RAMEND)
19
out SPH, r16
20
21
ldi r16, 0xFF ; Port B = Ausgang
22
out DDRB, r16
23
mov r15, r16
24
25
; Baudrate einstellen
26
ldi r16, LOW(UBRRVAL)
27
out UBRRL, r16
28
ldi r16, HIGH(UBRRVAL)
29
out UBRRH, r16
30
31
; Frame-Format: 8 Bit
32
ldi r16, (1<<URSEL)|(3<<UCSZ0)
33
out UCSRC, r16
34
35
sbi UCSRB, RXCIE ; Interrupt bei Empfang
36
sbi UCSRB, RXEN ; RX (Empfang) aktivieren
37
sbi UCSRB, TXEN ; TX (Senden) aktivieren
38
39
sei ; Interrupts global aktivieren
40
41
loop: rjmp loop ; Endlosschleife
42
43
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
44
int_rxc:
45
push r16 ; temp auf dem Stack sichern
46
in r16, UDR
47
; out PORTB, r16 ; PortB zur Anzeige der Empfangenen Daten benutzen
48
rcall serout
49
cpi r16, 13 ; empfangenes Byte mit 'Enter' vergleichen
50
breq start ; wenn gleich, dann zu XXX springen
51
; *** Ab hier wird überprüft ob ein gültiger Befehl gefunden wird
52
cpi r17, 0x00
53
breq befehl1
54
cpi r17, 0x01
55
breq befehl2
56
cpi r17, 0x02
57
breq befehl3
58
cpi r17, 0x03
59
breq befehl4
60
; *** Ende der überprüfung // Abbruch Fehlt noch
61
back: pop r16 ; temp wiederherstellen
62
reti ; Interrupt beenden
63
64
binc: inc r17
65
out PORTB, r17
66
rjmp back
67
68
befehl1:cpi r16, 'c'
69
breq binc
70
cpi r16, 'h'
71
breq binc
72
;****
73
ldi r16, 0xFD
74
mov r15, r16
75
rjmp binc
76
77
befehl2:cpi r16, 'l'
78
breq binc
79
cpi r16, 'e'
80
breq binc
81
;****
82
ldi r16, 0xFD
83
mov r15, r16
84
rjmp binc
85
86
befehl3:cpi r16, 's'
87
breq b_cls
88
cpi r16, 'l'
89
breq binc
90
;****
91
ldi r16, 0xFD
92
mov r15, r16
93
rjmp binc
94
95
befehl4:cpi r16, 'p'
96
breq b_help
97
;****
98
ldi r16, 0xFD
99
mov r15, r16
100
rjmp binc
101
102
b_help: mov r16, r15
103
cpi r16, 0xFD
104
breq back
105
ldi r16, 0x01
106
mov r15, r16
107
rjmp back
108
109
b_cls: mov r16, r15 ; Auf einen Fehler im Befehl prüfen Zeichen vorher
110
cpi r16, 0xFD ; ^^
111
breq back ; ^^
112
ldi r16, 0xFF ; Befehl ausfürhen aber noch auf Enter warten
113
mov r15, r16 ; R15 gibt den Befehl nach Enter weiter
114
rjmp back
115
116
; print: sendet die durch den Z-Pointer adressierte Zeichenkette
117
start: mov r16, r15
118
clr r17
119
cpi r16, 0x01
120
breq help
121
cpi r16, 0xFE
122
breq prompt
123
cpi r16, 0xFD
124
breq fehler
125
ldi ZL, LOW(dbdaten*2)
126
ldi ZH, HIGH(dbdaten*2)
127
ldi r16, 0xFE
128
mov r15, r16
129
130
wilkom: lpm r16, z+ ; Erstes Byte des Strings nach r16 lesen
131
tst r16 ; r16 auf 0 testen
132
breq prompt ; wenn 0, dann prmpt zeichenn
133
rcall serout ; UART-Sendefunktion aufrufen
134
rjmp wilkom ; wieder zum Anfang springen
135
136
weghier:rjmp back
137
138
prompt: ldi ZL, LOW(dbprompt*2) ; Adresse des Strings in den
139
ldi ZH, HIGH(dbprompt*2) ; Z-Pointer laden
140
zeigerp:lpm r16, z+
141
tst r16
142
breq weghier
143
rcall serout
144
rjmp zeigerp
145
146
zeiger: lpm r16, z+
147
tst r16
148
breq prompt
149
rcall serout
150
rjmp zeiger
151
152
fehler: ldi ZL, LOW(dbnobef*2)
153
ldi ZH, HIGH(dbnobef*2)
154
ldi r16, 0xFE
155
mov r15, r16
156
rjmp zeiger
157
158
help : ldi ZL, LOW(dbhelp*2)
159
ldi ZH, HIGH(dbhelp*2)
160
ldi r16, 0xFE
161
mov r15, r16
162
rjmp zeiger
163
164
; Senderoutine wird mit rcall serout aufgerufen
165
serout:
166
sbis UCSRA,UDRE ; Warten bis UDR für das nächste Byte bereit ist
167
rjmp serout
168
out UDR, r16
169
ret
170
171
; 12 cls
172
; 10 neue Zeile
173
; 13 cursor auf pos1
174
dbdaten: .db 12,"Wilkommen im Bits & Beitz Hausbus System",10,13,10,"Sie befinden sich im Debug Modus",10,13,10,0
175
dbprompt:.db 10,13,"Atmega8@Slave>",0
176
dbhelp: .db 10,13,"cls",9,"Löscht den Bildschirm",10,13,"help",9,"Gibt diese Hilfe Aus",10,13,0
177
dbnobef: .db 10,13,"Befehl nicht Vorhanden",10,13,0
Max Mustermann wrote:
> Kann man solch eine Eingabeafforderung auch noch etwas einfacher> gestallten? So das ich im Flasch zB irgendwo die Befehle hinterlege und> die dann überprüfe?
Genau so würde ich das machen:
Im Flash eine Tabelle der Befehle ablegen:
Befehlstext
Adresse der Funktion
Hilfetext
Beim Empfangen von Zeichen werden diese erst mal in einem
Zwischenspeicher zusammengefasst, so lange bis ein CR
empfangen wird. Mit dem jetzt bekannten Befehlstext wird
dann die Tabelle abgesucht, mit welchem Befehl das Ganze
übereinstimmt um dann die entsprechende Funktion (deren
Adresse ja ebenfalls in der Tabelle steht) auszuführen.
Allerdings würde ich das Ganze in C machen. In Assmebler
ist mir das zu aufwändig :-)
Obwohl: Das wär mal was fürs Tutorial. Da kommt so ziemlich
alles zusammen: UART behandeln, arbeiten mit dem SRAM, arbeiten
mit dem Flash, LCD Ansteuerung, ...
Leider kann ich kein C Programmieren. Ich kann Delphi, Basic aber am
liebsten mag ich Assember, dort sind die Befehle viel übersichtlicher.
Das EEPROM wird in dem Programm später auch noch benutzt um die Adressen
der einzelnen µC zu hinterlegen. Der Prompt sollte sich dann natürlich
auch entsprechend ändern.
z.B.
RS-232@192.168.0.5> eventuell werde ich auch alias namen dafür benutzen.
Alerdings ist mir noch nicht so ganz klar wie ich zB wenn ich in die
register r0 bis r7 den befehl ablege dies dann mit dem hinterlegten
befehl im flash, sram oder wo auch immer vergleichen kann, dazu brauche
ich ja den zl, low und zh, high und die anfangsadresse heraus zu
bekommen.
Max Mustermann wrote:
> Leider kann ich kein C Programmieren. Ich kann Delphi, Basic aber am> liebsten mag ich Assember, dort sind die Befehle viel übersichtlicher.> Das EEPROM wird in dem Programm später auch noch benutzt um die Adressen> der einzelnen µC zu hinterlegen. Der Prompt sollte sich dann natürlich> auch entsprechend ändern.>> z.B.>> RS-232@192.168.0.5> eventuell werde ich auch alias namen dafür benutzen.> Alerdings ist mir noch nicht so ganz klar wie ich zB wenn ich in die> register r0 bis r7 den befehl ablege
Das hast du falsch verstanden:
Lege die empfangene Zeichenkette im SRAM ab.
Der Rest ist dann ein reiner Textvergleich, wobei der
eine Text im Flash steht, der andere im SRAM (beide Texte würde
ich mit einem 0 Byte abschliessen). Es werden solange
Zeichen verglichen bis
* die Zeichen nicht übereinstimmen -> Texte sind nicht identisch
* das nächste Zeichen im Flash ein 0 ist
ist das nächste Zeichen im SRAM ebenfalls 0
Ja: Texte sind identisch
Nein: Texte sind nicht identisch
* das nächste Zeichen im SRAM ein 0 ist
Texte sind nicht identisch
Das ganze in einer Schleife für alle Zeichen, bis feststeht ob
die Texte identisch sind oder nicht.
> Leider kann ich kein C Programmieren. Ich kann Delphi
Wenn du Delphi kannst, dann sollte doch C kein Problem sein.
So gross sind die Unterschiede auch wieder nicht. String
ehandlung ist anders.
> dort sind die Befehle viel übersichtlicher
Die Befehle schon, aber das Programm wird elends lang und mit
der Zeit leidet die Übersichtlichkeit, weil man vor lauter
Bäumen nicht mehr den Wald sieht. Insbesondere dann, wenn man
etwas kompliziertere Datenstrukturen aufbaut.
Aber: Das musst du für dich selbst entscheiden.
> dies dann mit dem hinterlegten> befehl im flash, sram oder wo auch immer vergleichen kann, dazu brauche> ich ja den zl, low und zh, high und die anfangsadresse heraus zu> bekommen.
Ganz genau
Man könnte zb so was machen:
1
Commands:
2
cmdCls:
3
.db "cls", 0 ; Kommandotext
4
.dw cmdHelp ; Adresse des nächsten Kommandos
5
.dw funcCls ; Adresse der Routine die CLS bearbeitet
6
.db "Loescht den Schirm", 0 ; Hilfetext
7
8
cmdHelp:
9
.db "help", 0 ; Kommandotext
10
.dw cmdReset ; Adresse des nächsten Kommandos
11
.dw funcHelp ; Adresse der Routine die HELP behandelt
12
.db "Zeigt die Hilfe an", 0 ; Hilfetext
13
14
cmdReset:
15
.db "reset", 0 ; Kommandotext
16
.dw 0 ; 0 zeigt an, dass dies das letzte Kommando war
17
.dw funcReset ; Adresse der Routine die RESET behandelt
18
.db "Ruecksetzen des Systems", 0 ; Hilfetext
Wenn du also den Einstieg bei 'Commands' hast und der per UART
empfangene Text im SRAM unter 'Zeile' abgelegt wurde:
1 tmp = Commands
2 Ist die empfangene Zeile identisch mit dem Text, der bei tmp
beginnt?
Nein: Lies die nächsten 2 Bytes nach dem Text
War das 0 ?
Ja: das war das letzte Kommando -> Fehlermeldung ausgeben
Kommandoauswertung beenden
Nein: tmp <- die beiden gelesenen Bytes
Weiter bei 2
Ja: Überlies die nächsten 2 Bytes und hole dann die darauffolgenden
2 Bytes. Die Funktion unter dieser Adresse ausführen.
Kommandoauswertung beenden