Forum: Mikrocontroller und Digitale Elektronik Befehle aus mehreren ASCII- Zeichen generieren?


von Alex M. (Gast)


Lesenswert?

Hallo sehr geehrte Community.
Ich stehe momentan vor einem Problem für das ich keine optimale Lösung 
habe,
die Suchanfrage hat auch nichts Sinnvolles rausgespuckt :-)
Und zwar habe ich einen Mega 16 so programmiert, dass er ASCII- Zeichen 
über RS232 empfängt und diese in einen 256 Byte Buffer ablegt. Übrigens 
alles in ASM.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Gewünschte Funktion:
Drei auf einander folgende Zeichen sollten als Befehl interpretiert 
werden. Das ist auch schon das hauptsächliche Problem.
Als Beispiel bestehen diese Befehle nur aus Zahlen und somit währen 999 
Befehle möglich. Für meine Anwendung reichen auch 100 Befehle.
Zu jeden dieser Befehle möchte ich eine Anwendung aufrufen und etwas 
ausführen.
Nur wie soll das gehen?

Bitte um Hilfe !!

von Matthias (Gast)


Lesenswert?

Wenn das nicht zwingend ASCII sein muss, dann bastel Dir eine "Wrapper 
Struktur" drum herum.

Beispiel:
Befehl:    L (z.B: LED)
Parameter: 01 oder 00 (für An und Aus)

Jetzt verpacken wir das mit Synczeichen und Endezeichen:
Sync: 0x16
Ende: 0x04

Jetzt braucht man nur noch einen Zustandsautomaten, der sich auf das 
Sync-Zeichen synchronisiert und nach dem Endezeichen den String an einen
Auswerter übergibt.

Alternativ kann man sich allerdings auch das Ganze etwas anders 
aufbauen, wenn keine "Maschine" die Kommandos sendet. So dass alles 
ASCII ist und
immer bei CR am Ende der Uaswerter angeworfen wird.

von Matthias (Gast)


Lesenswert?

Hoppla:

Das mit dem Verpacken ist noch nicht vollständig:

"SYN L 0 1 END" oder HEX: "0x16 0x4C 0x30 0x30 0x04"

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

wie weit bist du denn schon in deinen Überlegungen gekommen?

nach meinem Verständniss hast du folgende Teilthemen:

1. aus dem ankommenden Datenstrom "die richtigen" 3 Zeichen 
rauszufischen

2. bei ankommenden Steuerbefehlen eine bestimmte Subroutine aufrufen 
(ggf. Errorhandler)


Zu 1.
Das kannst nur du alleine wissen was du hast oder brauchst. 
Möglicherweise hast du Einfluss auf beide Seiten (Sender und Empfänger), 
dann wäre es möglich ein gewisses Minimal-Protokoll zu implementieren. 
Vielleicht ist ja aber auch das Sendeprotokoll  vorgegeben (das macht 
die Sache eventuell leichter)

:: woran erkennst du, welche 3 Zeichen zusammen gehören? Wenn z.B. im 
Datenstrom ankommt: "123 4 56"

- ist es dann 123 (weil dazwischen eine Pause ist zum nächsten Zeichen)
- oder 23 4 (weil deine Steuerkommandos immer mit 2xx anfangen)
- oder 3 4 5 (weil zwischen den einzelnen Ziffern deinen Steuerkommandos 
immer eine gewisse Pause sein muß)
- oder .... oder

(Zweckmäßigerweise könntest du Steuerbefehle mit einem bestimmten 
"Zauberwort" einleiten, so wie die Modems z.B. auf "AT" reagieren

:: was machst du mit den restlichen Zeichen (eventuell Müll) der da 
eingetroffen ist?

:: Was machst du wenn der Eingangspuffer deiner Befehlssequenzen voll 
ist (weil deine Subroutinen etwas länger brauchen)? Verwirfst du alle 
ankommenden weiteren Steuerzeichen bis wieder "Luft" ist, oder 
verwendest du eine Art Handshake, um den Sender zu signalisieren, daß er 
erst mal aufhören soll?

zu 2:
Da die Anzahl deiner Steuerzeichen gering ist, kannst du das über 
Sprungtabelle realisieren. Nachdem du erkannt hast daß PQ3 ein gültiger 
Steuerbefehl ist, wird dieser "übersetzt" zu "nutze Sprungvektor 9". Und 
von da aus hüpfst du los.

> für das ich keine optimale Lösung habe

Die Optimum-Kriterien solltes du vorher festlegen (Geschwindigkeit, 
Platzbedarf, Eleganz des Codes, ...)

von Ralf (Gast)


Lesenswert?

> Drei auf einander folgende Zeichen sollten als Befehl interpretiert
> werden. Das ist auch schon das hauptsächliche Problem.
> Als Beispiel bestehen diese Befehle nur aus Zahlen und somit währen 999
> Befehle möglich. Für meine Anwendung reichen auch 100 Befehle.
> Zu jeden dieser Befehle möchte ich eine Anwendung aufrufen und etwas
> ausführen.
Wenn du 000 mitzählst, sind es 1000 Befehle. Du legst eine 2-Byte 
Variable an. Der Befehl wird ermittelt, indem du aus der ASCII-Zahl den 
numerischen Wert bildest, also erstmal 0x30 davon abziehst, und 
entsprechend der Stelle mit 100, 10 oder 1 multplizierst. Das ergibt 
dann den kompletten numerischen Wert des Befehls, welcher in der 2-Byte 
Variablen abgelegt wird. Zum Schluss über einen Vergleich herausfinden, 
um welchen Befehl es sich handelt, und entsprechend reagieren.

Ralf

von Route_66 (Gast)


Lesenswert?

Hallo erstmal!
Ich kann auch nicht genau erkennen, womit deine Frage jetzt "auf den 
Punkt" zu beantworten wäre...
Wichtig ist: (was auch von den Vorrednern ausgeführt wurde) es muß eine 
eindeutige Trennung von Befehl und Parameter geben. Dies ist gerade auch 
im Hinblick auf Störungen im Übertragungskanal wichtig.
Oft wird dafür ein Startzeichen oder eine -sequenz benutzt, die sonst im 
Datenstrom nicht vorkommt. Intel-Hex nutzt dafür den Doppelpunkt [:]

Wenn also das Startzeichen / die Startsequenz erkannt wurde liest man 
entweder eine vorgegebene feste Anzahl an Zeichen (hier evtl. 3) oder 
bis zu einem erwarteten Trennzeichen (z.B. 'Space',20h).

Wenn dann der Befehl isoliert ist, könnte man ihn für Befehlsnummern von 
1...255 in HEX wandeln. dann kann man aus einer Tabelle die Zieladresse 
für die weitere Verarbeitung ablesen.


Das Byte 00 bietet sich als Endemarke füer die Tabelle an.
 z.B. so:

BEFTAB:
   .DEFB 1     ;Befehl "001"
   .DEFW prog1 ;wird hier ausgeführt
   .DEFB 3     ;Befehl "003"
   .DEFW prog7 ;hier
   .DEFB 11    ; usw.
   .DEFW prog23
   .DEFB 55
   .DEFW prog4
   .DEFB 178
   .DEFW prog37
   .DEFB 0     ;hier ist Schluss, wenn Befehl jetzt noch nicht gefunden,
dann Fehlerroutine.

Für allgemeine Methoden der Befehlsentschlüsselung mit variabler 
Befehlslänge und/oder -struktur (Buchstaben  Zeichen  Ziffern / 
Unterscheidung Groß-Kleinschreibung usw.) heißt das Zauberwort "Parser" 
oder auch Befehlsdekoder. So nennt sich das bei allen 
Programmiersprachen, Compilern, Assemblern oder wo sowas eingesetz wird.

von rene (Gast)


Lesenswert?


von Alex M. (Gast)


Lesenswert?

Guten Tag die Herren.

@Wegstaben Verbuchsler
sorry ich hätte die ganze Angelegenheit etwas Präziser umschreiben 
sollen,
und zwar ist es so das, dass Protokoll mein eigenes Hirngespenst ist :-)
 Das ganze sieht dann mal so aus:

Startkondition
Befehl bestehend aus 3 ASCII Zeichen
Daten variabler Länge
CRC (noch nicht implementiert)
Stoppkondition

Gegen überlauf ist das Ganze auch geschützt.


@Route_66
Eine eindeutige Trennung von Befehl und Parameter ist vorhanden(siehe 
Protokollaufbau oben).
Insofern ich deine Idee verstanden habe, empfiehlst du mir
die Empfangenen ASCII- Zeichen  in eine HEX- zu Wandeln. Das sollte kein 
Problem sein, da ich die Daten ständig für Docklight(Terminalprogramm) 
und andersrum aufbereiten muss.
Doch das mit der Tabelle ist mir nicht ganz klar. Ich kenne nur die 
Mehrfachverzweigung aus’m AVR- Tutorial oder die simpelste Art. Cpi, 
Breq : -)
Könntest du mir bitte deine Version anhand von einem Beispiel etwas 
genauer schildern. Währe echt super.
Das Zauberwort like Parser ist mir in der Tat nicht bekannt, doch mit 
Befehlsdecoder hab ich’s bereits probiert , ohne Erfolg weil 
Befehlsdecoder oft mit CPU- Befehlen in Verbindung gebraucht werden.

@Rene
THX für den Link

von spess53 (Gast)


Lesenswert?

Hi

>Als Beispiel bestehen diese Befehle nur aus Zahlen und somit währen 999
>Befehle möglich.

Wenn du deine 'Adresse' Hexadezimal auslegst hättest du sogar 4096 
mögliche Befehle. Für deine 100 würden zwei Stellen genügen. Die 
Auswertung würde sich dadurch auch vereinfachen. Du müsstest nur die 
ASCII-Ziffer in einen Hexwert umwandeln. Dann legst du dir eine Tabelle 
mit Sprüngen zu den entsprechenden Routinen an. Z mit dem Anfang der 
Tabelle laden und zu Z den doppelten Hexwert addieren. Mit 'icall' wird 
deine Routine aufgerufen. Geht ganz ohne Parsen.

MfG Spess

von Olaf (Gast)


Lesenswert?

> die Suchanfrage hat auch nichts Sinnvolles rausgespuckt :-)

Sowas heisst Parser oder lexical analyzer.

Weil so ein Problem sehr haeufig vorkommt gibt es tools (z.B flex) die 
soetwas automatisch machen. Du beschreibst dort also deine Sprache und 
das Tools erzeugt dir einen C-Source.
Unter Linux sollte dir 'man flex' weiterhelfen.

Olaf

von Christian B. (casandro)


Lesenswert?

Du bräuchtest einen Parser. Am einfachsten schreibst Du den erst einmal 
in Prolog und überlegst Dir dann, wie Du den in Assembler 
implementierst. Das Buch "Programming in Prolog" hat da eine schönes 
Kapitel zum Thema parsen, welches auch für Programmierer anderer 
Sprachen interessant ist.

von gtf (Gast)


Lesenswert?

@spess53
ne hexadezimal passt nicht! so müsste ich ASCII und HEX mischen und das 
kann nicht gut gehen ich bleibe lieber bei ASCII, weil auch schon alle 
Routinen mit PAP und Doku belegt sind.
Es ist mir schon klar, dass durch ASCII ein Mehraufwand betrieben wird, 
aber so kann ich mit Zeichen  „STX“, „EOT“ Handshakes ersetzten, da das 
ganze über RS232 läuft.


Schlussendlich werden jetzt 3 ASCII Zeichen, deren Gesamtwert nicht 255 
überschreiten darf
nach HEX gewandelt. Somit steht mir eine 8-Bit Zahl im Bereich von 0-255 
zur Verfügung,
dieser Wert wird in die Mehrfachverzweigung 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Mehrfachverzweigung 
geladen und anschließend durch die Tabelle zu Routinen umgeleitet.

Vielen dank für die zahlreichen guten Tipps. Ihr habt mir dazu verholfen 
mein Projekt einen Schritt weiter zu bringen.

//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XX  Ich wünsch euch allen noch ein Frohes Weihnachtsfest    XX
//XX         und einen guten rutsch ins neue Jahr!              XX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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.