Forum: Mikrocontroller und Digitale Elektronik RS232 Eingabeaufforderung


von Max Mustermann (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Verschoben und nach oben gebracht

von Karl H. (kbuchegg)


Lesenswert?

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, ...


von Max Mustermann (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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



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.