mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RS232 Eingabeaufforderung


Autor: Max Mustermann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
.include "m8def.inc"                    ; bzw. 2333def.inc
 
.equ CLOCK = 7372800
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
 
.org 0x00
        rjmp inistart
 
.org URXCaddr                             ; Interruptvektor für UART-Empfang
        rjmp int_rxc
 
; Inizaliesierung
inistart:

        ldi r16, LOW(RAMEND)
        out SPL, r16
        ldi r16, HIGH(RAMEND)
        out SPH, r16
 
        ldi r16, 0xFF                    ; Port B = Ausgang
        out DDRB, r16
    mov r15, r16
 
        ; Baudrate einstellen
        ldi r16, LOW(UBRRVAL)
        out UBRRL, r16
        ldi r16, HIGH(UBRRVAL)
        out UBRRH, r16
 
        ; Frame-Format: 8 Bit
        ldi r16, (1<<URSEL)|(3<<UCSZ0)
        out UCSRC, r16
 
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
    sbi UCSRB, TXEN                   ; TX (Senden) aktivieren
        
        sei                               ; Interrupts global aktivieren
        
loop:   rjmp loop                         ; Endlosschleife
 
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
int_rxc:
        push r16                          ; temp auf dem Stack sichern
        in r16, UDR
 ;       out PORTB, r16             ; PortB zur Anzeige der Empfangenen Daten benutzen
    rcall serout
    cpi r16, 13                       ; empfangenes Byte mit 'Enter' vergleichen
        breq start                        ; wenn gleich, dann zu XXX springen
    ; *** Ab hier wird überprüft ob ein gültiger Befehl gefunden wird
        cpi r17, 0x00
    breq befehl1
    cpi r17, 0x01
    breq befehl2
    cpi r17, 0x02
    breq befehl3
    cpi r17, 0x03
    breq befehl4
    ; *** Ende der überprüfung // Abbruch Fehlt noch
back:   pop r16                           ; temp wiederherstellen
        reti                              ; Interrupt beenden 

binc:  inc r17
    out PORTB, r17
    rjmp back

befehl1:cpi r16, 'c'
    breq binc
    cpi r16, 'h'
    breq binc
    ;****
    ldi r16, 0xFD
    mov r15, r16
    rjmp binc

befehl2:cpi r16, 'l'
    breq binc
    cpi r16, 'e'
    breq binc
    ;****
    ldi r16, 0xFD
    mov r15, r16
    rjmp binc

befehl3:cpi r16, 's'
    breq b_cls
    cpi r16, 'l'
    breq binc
    ;****
    ldi r16, 0xFD
    mov r15, r16
    rjmp binc

befehl4:cpi r16, 'p'
    breq b_help
    ;****
    ldi r16, 0xFD
    mov r15, r16
    rjmp binc

b_help: mov r16, r15
    cpi r16, 0xFD
    breq back
        ldi r16, 0x01
    mov r15, r16
    rjmp back

b_cls:  mov r16, r15  ; Auf einen Fehler im Befehl prüfen Zeichen vorher
    cpi r16, 0xFD ; ^^
    breq back    ; ^^  
        ldi r16, 0xFF ; Befehl ausfürhen aber noch auf Enter warten
    mov r15, r16  ; R15 gibt den Befehl nach Enter weiter
    rjmp back

; print: sendet die durch den Z-Pointer adressierte Zeichenkette
start:  mov r16, r15
    clr r17
    cpi r16, 0x01
    breq help
    cpi r16, 0xFE
        breq prompt
    cpi r16, 0xFD
    breq fehler
    ldi ZL, LOW(dbdaten*2)
    ldi ZH, HIGH(dbdaten*2)
    ldi r16, 0xFE
    mov r15, r16
            
wilkom:  lpm r16, z+                       ; Erstes Byte des Strings nach r16 lesen
        tst r16                           ; r16 auf 0 testen
        breq prompt                       ; wenn 0, dann prmpt zeichenn
        rcall serout                      ; UART-Sendefunktion aufrufen
    rjmp wilkom                        ; wieder zum Anfang springen

weghier:rjmp back

prompt: ldi ZL, LOW(dbprompt*2)               ; Adresse des Strings in den
        ldi ZH, HIGH(dbprompt*2)              ; Z-Pointer laden
zeigerp:lpm r16, z+
    tst r16
    breq weghier
    rcall serout
    rjmp zeigerp

zeiger: lpm r16, z+
    tst r16
    breq prompt
    rcall serout
    rjmp zeiger

fehler: ldi ZL, LOW(dbnobef*2)
    ldi ZH, HIGH(dbnobef*2)
    ldi r16, 0xFE
    mov r15, r16
    rjmp zeiger

help  : ldi ZL, LOW(dbhelp*2)
    ldi ZH, HIGH(dbhelp*2)
    ldi r16, 0xFE
    mov r15, r16
    rjmp zeiger

; Senderoutine wird mit rcall serout aufgerufen
serout:
        sbis UCSRA,UDRE                   ; Warten bis UDR für das nächste Byte bereit ist
        rjmp serout
        out UDR, r16
        ret          

; 12 cls
; 10 neue Zeile
; 13 cursor auf pos1
dbdaten: .db 12,"Wilkommen im Bits & Beitz Hausbus System",10,13,10,"Sie befinden sich im Debug Modus",10,13,10,0
dbprompt:.db 10,13,"Atmega8@Slave>",0 
dbhelp:  .db 10,13,"cls",9,"Löscht den Bildschirm",10,13,"help",9,"Gibt diese Hilfe Aus",10,13,0
dbnobef: .db 10,13,"Befehl nicht Vorhanden",10,13,0

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verschoben und nach oben gebracht

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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, ...


Autor: Max Mustermann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
Commands:
cmdCls:
       .db    "cls", 0                 ; Kommandotext
       .dw    cmdHelp                  ; Adresse des nächsten Kommandos
       .dw    funcCls                  ; Adresse der Routine die CLS bearbeitet
       .db    "Loescht den Schirm", 0  ; Hilfetext

cmdHelp:
       .db    "help", 0                ; Kommandotext
       .dw    cmdReset                 ; Adresse des nächsten Kommandos
       .dw    funcHelp                 ; Adresse der Routine die HELP behandelt
       .db    "Zeigt die Hilfe an", 0  ; Hilfetext

cmdReset:
       .db    "reset", 0               ; Kommandotext
       .dw    0                        ; 0 zeigt an, dass dies das letzte Kommando war
       .dw    funcReset                ; Adresse der Routine die RESET behandelt
       .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



Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.