Hallo,
ich möchte gerne über uart variablen vorgeben. Dazu werden als ascii
befehle und der wert gesendet.
z.B.
aktor1 100
aktor1 kann ich mittels strncmp ermitteln
strncmp(input, "aktor1", 6)
aber wie komme ich an die 100?
wenn nur die zahl da wäre, könnte ich es mit atoi machen. Gibt es da
auch was, wo man die stelle mit angeben kann?
Felix schrieb:> Gibt es da> auch was, wo man die stelle mit angeben kann?
Du kannst atoi doch auf jeden Startpunkt im String setzen. Einfach mit
dem Plus Zeichen. Pointer sind doch Basiswissen in C. Nutze sie!
Joachim B. schrieb:> Sind also Schreib oder Flüchtigkeitsfehler die kaum behindern, da gibt> es Schlimmeres.
Wenn man die Fehler noch dazu zählt die du übersehen hast dannn ...
Uff Basse schrieb:> Wenn man die Fehler noch dazu zählt die du übersehen hast dannn ...
meint der Unangemeldete mit 3n in dannn
Glashaus, du weisst schon :)
Felix schrieb:> aktor1 100
also
Joachim B. schrieb:> strchr(input, ' ') +1 als Startwert für atoi?
gäbe
print("was: %s, wieviel: %d \r\n", input, atoi(strchr(input, ' ') +1));
oder so, c mal vorausgesetzt. (kann trotzdem noch Fehler enthalten ohne
den Dialekt zu kennen)
Joachim B. schrieb:> strchr(input, ' ') +1 als Startwert für atoi?
Geht nicht. Manchmal kommt im String kein ' ' vor.
Deswegen gebe ich die Cortex-M-MPU nicht wieder her.
Felix schrieb:> ich möchte gerne über uart variablen vorgebenBauform B. schrieb:> Geht nicht. Manchmal kommt im String kein ' ' vor.
anderer User anderes Problem!
also was soll das?
Der TO möge bitte alles nennen, sonst ist jede Antwort Spekulatius.
Aber für jede CPU und jede Programmiersprache findet sich eine Lösung!
Dirk B. schrieb:> das +1 ist nicht mal nötig.
danke stimmt, war ohne Test aus dem Gedächnis nur zur Sicherheit, aber
vorlaufende space ignoriert atoi ja.
Felix schrieb:> aktor1 kann ich mittels strncmp ermitteln> aber wie komme ich an die 100?
Üblicherweise kommen die Zeichen aus einem UART einzelzeichenweise und
man möchte sie auch gleich verarbeiten damit man sie nicht unnötig
speichern muss und ndafür Pufferspeicher (unbekannter Länge) reservieren
muss.
Man malt sich am besten auf, welche Zeichen in welcher Reihenfolge
kommen dürfen
das sind Zustände die man mit einer Zustandsmaschine abarbeitet
1
ch=getchar();// vom UART
2
switch(zustand)
3
{
4
case0:
5
switch(ch)
6
{
7
case'a':zustand=1;break;
8
case'i':zustand=41;break;
9
case'e':zustand=48;break;
10
default:zustand=0;
11
}
12
break;
13
case1:
14
switch(ch)
15
{
16
case'k':zustand=2;break;
17
default:zustand=0;
18
}
19
break;
20
case2:
21
switch(ch)
22
{
23
case't':zustand=3;break;
24
default:zustand=0;
25
}
26
break;
27
:
28
}
an manchen Stellen an denen man was erkannt hat sind gesonderte Aktionen
nötig, um sich zu merken, was man erkannt hat, z.B.
1
case5:
2
switch(ch)
3
{
4
case'1':aktornummer=1;zustand=6;break;
5
case'2':aktornummer=2;zustand=7;break;
6
default:zustand=0;
7
}
8
break;
9
case10:
10
switch(ch)
11
{
12
case'\r':zustand=39;break;
13
case'0':wert=10*wert;zustand=19;break;
14
case'1':wert=10*wert+1;zustand=20;break;
15
case'2':wert=10*wert+2;zustand=21;break;
16
case'3':wert=10*wert+3;zustand=22;break;
17
case'4':wert=10*wert+4;zustand=23;break;
18
case'5':wert=10*wert+5;zustand=24;break;
19
case'6':wert=10*wert+6;zustand=25;break;
20
case'7':wert=10*wert+7;zustand=26;break;
21
case'8':wert=10*wert+8;zustand=27;break;
22
case'9':wert=10*wert+9;zustand=28;break;
23
default:zustand=0;
24
}
25
break;
Auf die Art wird das ankommende Zeichen sofort verarbeitet, man muss
nichts speichern ausser dem Zustand und sogenannter Attributwerte, wie
hier aktornummer und wert, und die haben bekannte Speichergrösse.
Der ganze switch-Aufwand lässt sich stark vereinfachen als Tabelle
'tabellengesteuerte Zustandsmaschine' oder statisch verkette Liste, und
man hat immer die Möglichkeit, mehr Attribute und weniger Zustände
gegeneinander aufzurechnen.
Ganze Compiler arbeiten so, und die auswertenden Programmstücke bzw.
Tabellen werden automatisch aus der Syntax generiert.
Felix schrieb:> aktor1 100>> aktor1 kann ich mittels strncmp ermitteln> strncmp(input, "aktor1", 6)>> aber wie komme ich an die 100?
Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:
Wenn du das so herum schreiben willst, dann brauchst etwas, das dir
deine Eingabezeile auseinandernimmt, also einen Parser. Das ist nicht
schwer, will aber erstmal getan sein.
Hier ein Beispiel dafür:
1
charmatch(char*item,char**Zptr)
2
{char*P;
3
IgnoreSpace(Zptr);
4
P=*Zptr;
5
if(UpCase(*P)!=*item)return0;
6
while(*item){if(UpCase(*P++)!=(*item++))return0;}
7
*Zptr=P;
8
IgnoreSpace(Zptr);
9
return1;
10
}
Die Benutzung ist leicht:
char* Cpt;
...
if (match("DIR",&Cpt)) { DoDir(wo); return;}
if (match("LIST",&Cpt)) { DoList(wo); return;}
if (match("COPY",&Cpt)) { DoCopy(wo); return;}
if (match("DEL",&Cpt)) { DoDelete(wo); return;}
na und so weiter.
In gleicher Weise kannst du dir auch einen Eingabekonverter schreiben
für Integerzahlen. Prinzip dabei ist, daß du über das Argument char**
Zptr den Zeiger in der Zeile weiterstellst, so daß du vom aufrufenden
Programm her dich nicht kümmern mußt, wie lang deine Schlüsselworte sind
und wieviele Leerzeichen dazwischen stehen.
Aber für deinen Fall würde ich das Ganze völlig anders herum
organisieren: Nämlich eben NICHT zeilenorientiert, sondern formatfrei
nach folgender Regel:
1. zuerst kommt das Argument als reine Integerzahl, dann kommt ein
Kennbuchstabe für das, was du stellen willst.
2. jeder Kennbuchstabe führt nach seiner Ausführung zum Ablöschen des
Arguments.
3. alles was dein Algorithmus nicht kennt, wird stillschweigend
ignoriert und das eventuelle Argument gelöscht.
Beispiel:
A sei der Kennbuchstabe für Aktor 1, B sei derjenige für Aktor 2 usw.
4711A0815B
Das setzt Aktor A auf 4711 und Aktor B auf 815. Das Ganze erinnert ein
bissel an das Gerber-Format für's Leiterplatten anfertigen.
W.S.
W.S. schrieb:> Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:
na so schlimm ist es noch nicht ;)
Cyblord -. schrieb:> Du kannst atoi doch auf jeden Startpunkt im String setzen.
Da hätte ich auch drauf kommen müssen.
Habe es vorerst so gelöst. Die daten speichere ich alle im puffer, mit
strncmp frage ich ab wonach und mit atoi hole ich mir dann den Wert.
Momentan alles noch sehr hart. Also aktor1 darf z.B. nicht akt1
umbenannt werden, da sonst die Länge nicht mehr passt.
Michael B. schrieb:> Üblicherweise kommen die Zeichen aus einem UART einzelzeichenweise und> man möchte sie auch gleich verarbeiten damit man sie nicht unnötig> speichern muss und ndafür Pufferspeicher (unbekannter Länge) reservieren> muss.
Habe es so gelernt, dass Auswertungen nicht in einer ISR gemacht werden
sollen.
Werde mir aber auch deine Lösung mal ansehen und versuchen umzusetzen
Felix schrieb:> Momentan alles noch sehr hart. Also aktor1 darf z.B. nicht akt1> umbenannt werden, da sonst die Länge nicht mehr passt.
Tja, eben.
Schreib deinen Quellcode so, daß du dich möglichst nicht auf feste
Längen, feste Zeichenpositionen, festes groß/klein etc. selbst
festnagelst.
Sowas ist extrem unflexibel, verbaut dir ein leichtes Erweitern, ist
anfällig für Tippfehler auf der PC-Seite und so weiter.
W.S.
Felix schrieb:> Habe es so gelernt, dass Auswertungen nicht in einer ISR gemacht werden> sollen.
Das ist grundsätzlich auch richtig. Gib deinem UART-Treiber deshalb zwei
Ringpuffer für TX und RX je einen, damit der einige Zeichen eben puffern
kann. Normalerweise reichen für den RX Puffer 8 Zeichen völlig aus. Und
ausgewertet wird in einer Funktion, die du von main aus aufrufst.
W.S.
W.S. schrieb:> Nachdem die anderen dich fast vergrault haben,
Blödsinn (vor allem "DIE ANDEREN")
auch ein W.S. kann das locker an vielen Stellen!
W.S. schrieb:> Gib deinem UART-Treiber deshalb zwei> Ringpuffer für TX und RX je einen
sinnvoll!
Felix schrieb:> Habe es so gelernt, dass Auswertungen nicht in einer ISR gemacht werden> sollen.
richtig!
W.S. schrieb:> Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:
Da meldet sich aber wiklich der Richtige!
Wenn hier wer Foristen dumm von der Seite anmachst dann bist du das.
W.S. schrieb:> char match (char* item, char** Zptr)> { char* P;> IgnoreSpace(Zptr);> P = *Zptr;> if (UpCase(*P) != *item) return 0;> while (*item) { if (UpCase(*P++)!=(*item++)) return 0; }> *Zptr = P;> IgnoreSpace(Zptr);> return 1;> }
Was ist das denn jetzt schonwieder für ein Nichtskönner Code?
Schonmal was von der string.h gehört/gelesen?!