Forum: Mikrocontroller und Digitale Elektronik zahl aus uart string ermitteln


von Felix (Gast)


Lesenswert?

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?

von Cyblord -. (cyblord)


Lesenswert?

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!

von Uff Basse (Gast)


Lesenswert?

Bitte halte dich an die Netiquette und schreibe anständig
gross und klein.

So ein hingeschissenes Geschreibsel ist kaum zu entziffern.

von Joachim B. (jar)


Lesenswert?

Felix schrieb:
> en. Da

Uff Basse schrieb:
> schreibe anständig
> gross und klein.

hat er doch, nach "." und mit "Dazu"

Felix schrieb:
> aktor1

ist seine kleingeschriebene Variable!

Felix schrieb:
> uart variablen

Sind also Schreib oder Flüchtigkeitsfehler die kaum behindern, da gibt 
es Schlimmeres.
https://www.n-joy.de/leben/Deutsche-Sprache-12-Beweise-dass-Kleinigkeiten-Unterschied-machen,deutschesprache126.html
https://www.n-joy.de/leben/Warum-Kommas-so-wichtig-sind,deutschesprache150.html

Cyblord -. schrieb:
> Du kannst atoi doch auf jeden Startpunkt im String setzen. Einfach mit
> dem Plus Zeichen. Pointer sind doch Basiswissen in C. Nutze sie!

dito +1

Felix schrieb:
> strncmp(input, "aktor1", 6)

wie wäre es mit

strchr(input, ' ') +1 als Startwert für atoi?

von Uff Basse (Gast)


Lesenswert?

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

von Joachim B. (jar)


Lesenswert?

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)

von Bauform B. (bauformb)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

Felix schrieb:
> ich möchte gerne über uart variablen vorgeben

Bauform 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!

von Dirk B. (dirkb2)


Lesenswert?

Joachim B. schrieb:
> strchr(input, ' ') +1 als Startwert für atoi?

das +1 ist nicht mal nötig.
1
int aktor1;
2
if (sscanf(input, "aktor1%d", &aktor1) == 1)
3
{  // aktor1 wurde in input genannt
4
}
kommt mit und ohne Whitespace (Leerzeichen) klar.

Wenn du nur einlesen willst, kannst du auf das if verzichten.

von Joachim B. (jar)


Lesenswert?

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.

von Michael B. (laberkopp)


Lesenswert?

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
1
--+--(a)--(k)--(t)--(o)--(r)--+--(1)--+--(=)--+--(0)--+--+-------+--+-------+--+--(\r)--(\n)--
2
  |                           |       |       |       |  |       |  |       |  |
3
  |                           +--(2)--+       +--(1)--+  +--(0)--+  +--(0)--+  |
4
  |                                           |       |  |       |  |       |  |
5
  |                                           +--(2)--+  +--(1)--+  +--(1)--+  |
6
  |                                           :       :  :       :  :       :  |
7
  |                                           +--(9)--+  +--(9)--+  +--(9)--+  |
8
  |                                                                            |
9
  +--(i)--(n)--(p)--(u)--(t)--+--(1)--+----------------------------------------+
10
  |                           |       |                                        |
11
  |                           +--(2)--+                                        |
12
  |                                                                            |
13
  +--(e)--(x)--(i)--(t)--------------------------------------------------------+
Jedem dieser Kringel gibt man eine Nummer
1
--+--(a)--(k)--(t)--(o)--(r)--+--(1)--+--(=)--+--(0)--+--+-------+--+-------+--+--(\r)--(\n)--
2
0 |   1    2    3    4    5   |   6   |   8   |   9   |  |       |  |       |  |   39    40
3
  |                           +--(2)--+       +--(1)--+  +--(0)--+  +--(0)--+  |
4
  |                               7           |  10   |  |  19   |  |  29   |  |
5
  |                                           +--(2)--+  +--(1)--+  +--(1)--+  |
6
  |                                           :  11   :  :  20   :  :  30   :  |
7
  |                                           +--(9)--+  +--(9)--+  +--(9)--+  |
8
  |                                              18         28         38      |
9
  +--(i)--(n)--(p)--(u)--(t)--+--(1)--+----------------------------------------+
10
  |  41   42   43   44   45   |  46   |                                        |
11
  |                           +--(2)--+                                        |
12
  |                              47                                            |
13
  +--(e)--(x)--(i)--(t)--------------------------------------------------------+
14
     48   49   50   51
das sind Zustände die man mit einer Zustandsmaschine abarbeitet
1
ch=getchar(); // vom UART
2
switch(zustand)
3
{
4
case 0:
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
case 1:
14
    switch(ch)
15
    {
16
    case 'k': zustand=2; break;
17
    default: zustand=0;
18
    }
19
    break;
20
case 2:
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
case 5:
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
case 10:
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.

von W.S. (Gast)


Lesenswert?

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
char match (char* item, char** Zptr)
2
{ char* P;
3
  IgnoreSpace(Zptr);
4
  P = *Zptr;
5
  if (UpCase(*P) != *item) return 0;
6
  while (*item) { if (UpCase(*P++)!=(*item++)) return 0; }
7
  *Zptr = P;
8
  IgnoreSpace(Zptr);
9
  return 1;
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.

von Felix (Gast)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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!

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

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?!

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.