Liebe Mitleser ;)
als Hobby C-Progger bin ich gerade dabei, mir einen
Kommandozeilen-Interpreter zu bauen.
Man findet tatsächlich nur schwer etwas zu diesem Thema.
In der Codesammlung habe ich einen Beitrag gefunden
Beitrag "Einfacher Interpreter für Komandozeilen/Befehlszeilen"
und bei RN im wiki gibt es einen Anhaltspunkt:
http://www.rn-wissen.de/index.php/Avr-gcc (Section 31 Sprungtabelle)
Bei AT Befehlen, wie man sie bei Modems zB. eingibt,
lässt sich ja generell mit:
1) AT+xyz=? der erlaubte Bereich des Parameters abfragen
2) AT+xyz? der aktuelle Wert von "xyz" abfragen
3) AT+xyz=100 den Wert von "xyz" mit 100 festlegen
4) AT+xyz= 1,2,"0000",5 der Funktione, die hinter "xyz" steht,
mit Werten und Parametern füttern.
Hinzu kommt dann noch "AT*" irgentwas, "AT^", "ATA", usw. also Befehle,
bei denen das "PLUS" Zeichen als Befehlstrenner fehlt.
Was soll ich nun in die Sprungtabelle eintragen, wenn ich das Beispiel
ausm RN als Grundlagen nehmen würde?
Eigentlich müsste ich in diese Sprungtabelle
1) AT+
2) AT*
3) ATA
4) ATH
usw. eintragen und das, was danach kommt, also
1) xyz
2) test1
3) test2
usw. in eine zweite Sprungtabelle?
Was mache ich mit den unterschiedlichen Parametern, welche ja als Zahl
oder als String vorliegen können un dauch noch von der Anzahl her
unterschiedlich sein können?
Dem Beispiel in der Codesammlung konnte ich entnehmen, das es dieses
Problem wohl schon mal gegeben hat.
Beitrag "Einfacher Interpreter für Komandozeilen/Befehlszeilen"
Leider sind hier verschiedene Punkte für mich unverständlich, da hier
ganz viel Pointerrechnerei betrieben wurde und viele vorhandene
String-Funktionen selbst geschrieben wurde und ich bei denen leider mit
meinen bescheidenen C-Kenntnissen nicht wirklich durchsteige.
Ein ganz simples Beispiel aus dem Thread:
1
int8_t execute_cmd_interface(char *string){
2
/* local variables */
3
register uint8_t ui8_cnt =0;
4
register char act_char =1;
5
register int8_t cmd_ret_val =0;
6
register uint8_t cmd_count =0;
7
int8_t ret_val =0;
8
/* start reading string */
9
act_char=string[ui8_cnt++]; /* Read next sign */
Speziell /* Read next sign */
um welches Vorzeichen handelt es sich? Ich dachte char ist deshalb
Vorzeichen behaftet, weil die Druckbaren Zeich im 7Bit Bereich liegen,
also bis 127 gehen.
So wird auch viel hin-und herkopiert -k.A. ;)
Ich werde nun versuchen, mit Hilfe der Standardbefehle vom WINAvr, mir
das nochmal aufzudröseln. Auwei - ob ich das hinbekomme?
Aber mit:
1
if (buffer[i] =='+' $$ buffer[i-1]=='T' && buffer[i-2] =='A')
wollte ich eben diesmal nicht machen, hmm.
Hat evtl. jemand solch eine Kommandoschnittstelle schon einmal
implementiert?
BTW. Muss ja nicht mit "AT+ oder "AT*" laufen. Das sollte nur als
Beispiel dienen. Auch andere Kommadostrukturen wären sicher denkbar.
Danke fürs Lesen
Axelr.
Frohe Pfingsten
Hallo Axel...
ohne zu wissen was du wie mit den AT Befehehlen machen möchtest - hier
mein Vorschlag wie du mit meinem "Pointern"-Beispiel ;O) es hinbekommen
könntest.
1
irgendwo in main
2
/* add command-functions to command-interface */
3
cmd_interface_add_cmd("ATA", &command_0);
damit wäre der Befehl schon mal bekannt.. die Anzahl der Argumente
interessieren den Code erst mal nicht, du musst aber den Funktionszeiger
&command_0 mit Leben füllen, indem du eine eine Funktion dazu
schreibst...
Beispiel - machen das Leben leichter ;O)
/*Sende Parameter so wie sie eingegeben wurden ohne Trennzeichen */
6
for (ui8_cnt=0; argc>ui8_cnt; ui8_cnt++){
7
USART_SENDEFUNKTION(argval[ui8_cnt]);
8
}
9
return 0;
10
}
uint8_t command_0(int8_t argc, char *argval[])
die Parameterliste muss so bleiben, das bestimmt mein Code so.
argc - hier bekommst du die Anzahl der Parameter
argval - hier bekommst du die pointer auf die verschidenen Strings
deiner Argumente/Parameter
Beispiel: ATA P1,p2 - keine Ahnung ob das Sinn macht
argval[0] = "P1"
argval[1] = "p2"
Hilft dir das?
Gruss Gary
Hallo Gary,
>ohne zu wissen was du wie mit den AT Befehehlen machen möchtest
Ich will ein SIEMENS TC35 emulieren.
Mir geht es in erster Linie um die Herangehensweise. Deinen BeispielCode
habe ich ans Laufen gebracht. Habs an meinen Mega128 angepasst.
Der Befehl "ATA" nimmt gerade bei der Abarbeitung eine Sonderstellung
ein, so wie alle Befehle, die halt einen Buchstaben mehr haben, als eben
nur AT.
Ich werde nun doch eine Statemachine programmieren, in der ich
AT, AT*, AT^, AT+, AT& ...
usw erkenne.
Wenn keines davon dabei war, nehm ich mir die restlichen bleibenden
ATA, ATH, ATE, usw. vor.
Dann werde ich nachsehen, ob Kommas drinn sind und wieviele Zeichen
zwischen den Kommas.
Hier hatte ich schon einst einen NMEA GPS String Auswerter (APRS nach
N4TXI) gebastelt. Den leihe ich mir dafür aus.
Dann wären noch das "=" interessant und das "?".
Hieran werde ich entscheiden, ob die dahinterstehende Funktion ein GET,
ein SET oder ein Report bringen muss.
Im Anschluss daran die Funktionszeigertabelle, die dann die
entsprechende Funktion anspringt.
Nunja - diese Verbindung zwischen Statmachine und Funktionszeigertabelle
bereitete mir etwas Kopfzerbrechen.
Vielen Dank und viele Grüße
Axelr.
Axel Rühl schrieb:> Nunja - diese Verbindung zwischen Statmachine und Funktionszeigertabelle> bereitete mir etwas Kopfzerbrechen.
Die Sache mit der Tabelle würde ich mir etwa so vorstellen:
1
#include<stdlib.h>
2
#include<stddef.h>
3
#include<stdio.h>
4
#include<string.h>
5
6
// Z.B. Typ einer Funktion, die ein Kommando bekommt (erster Parameter
7
// ist das Kommando, zweiter der Rest der Kommandozeile).
8
// Rückgabe: eine int als Fehlerkennung
9
// Könnte auch anders sein, aber alle Funktionen müssen
Nach diesem Strickmuster kann man leicht neue Kommandos hinzufügen.
Mit wenig Änderung (Feld verlängerbar) könnte man sogar zur
Laufzeit neue Kommandos dazubauen. Nach dem Verlängern des Feldes
muß man wieder qsort() aufrufen, damit das Feld sortiert ist und
bsearch() wieder die Kommandos findet.