Forum: Mikrocontroller und Digitale Elektronik Zahl im String finden


von Peter H. (Gast)


Lesenswert?

Hallo an alle!

Hab da ein Problem und ich komm nicht drauf, wieso das nicht 
funktioniert:

Und zwar will ich aus einem String eine Zahl herausfiltern.

Der String sieht z.B. so aus:

> char string[]="PARAM#123";

nun will ich die Zahl 123 herausfiltern. Ich habe es bisher so probiert:

> volatile int stringPosition=0;

> while(string[stringPosition]!='#')
> {
>   stringPosition++;
> }
> for(i=stringPosition, j=0; i<(stringPosition+3); i++, j++)
> {
>   zeitString[j]=string[i+1];
> }
> zeit1=atoi(zeitString);

wenn der String jetzt z.B. "PARAM#001" ist, ist zeit1=1, aber wenn im 
String jetzt "PARAM#010" steht, dann ist zeit1=0

Wieso liest er das nicht alle drei Stellen ein???

Bitte um Hilfe!

lg Peter

von Peter D. (peda)


Lesenswert?

1
zeit1 = atoi( strchr(string, '#') + 1);


Peter

von Peter H. (Gast)


Lesenswert?

@ peter

kannst du mir erklären, was das genau macht?

von Bartholomäus S. (sam_vdp)


Lesenswert?

Hast du deinen zeitString richtig initialisiert (z.B. char 
zeitString[4]) und terminiert (mit einem 0-Byte, z.B. so: 
zeitString[4]=0).
 Könnte sein, dass atoi da drüber stolpert.

von Peter H. (Gast)


Lesenswert?

@Bartholomäus Steinmayr

jep,

> xdata volatile char zeitString[4];

dürfte normal passen, oder muss ich

> xdata volatile char zeitString[4]=0; schreiben?

von Peter D. (peda)


Lesenswert?

Peter H. wrote:
> @ peter
>
> kannst du mir erklären, was das genau macht?

strchr sucht ein Zeichen im String und gibt den Zeiger darauf zurück.

Deine Zahl beginnt dahinter, also "+1".

Und dann noch den Zeiger an atoi übergeben.


Peter

von Peter H. (Gast)


Lesenswert?

@ peter

danke, d.h ich brauch die ganzen schleifen gar nicht und brauch nur

> zeit1 = atoi( strchr(string, '#') + 1);

zu schreiben?

Wenn ja, was ist, wenn der String so aussieht: "PARAM#123#456"

werden in zeit1 dann nur die zeichen bis zum nächsten # gespeichert, 
oder muss ich das dann anders machen?

von Peter D. (peda)


Lesenswert?

Das '#' ist keine gültige Ziffer und daher bricht atoi dort ab.

Der korrekte Weg ist allerdings, erstmal nachzusehen, ob überhaupt ein 
'#' im String ist, z.B.:
1
if( strchr(string, '#') ){
2
// ...  # gefunden
3
}else{
4
// ... # nicht gefunden
5
}


Peter

von Peter H. (Gast)


Lesenswert?

@peter

Ok, danke. Ich bin mir sicher, dass ein '#' im String ist, von dem her 
ist das dann kein Problem. Danke nochmal!

von yalu (Gast)


Lesenswert?

> Wenn ja, was ist, wenn der String so aussieht: "PARAM#123#456"

Peters Ansatz für eine beliebige Anzahl (auch 0) von Nummern:
1
#include <stdio.h>
2
#include <string.h>
3
4
char str[] = "PARAM#1#22#333#4444 blabla #55555 ende";
5
6
int main() {
7
  char *p;
8
  p = str;
9
  while(p=strchr(p, '#'))
10
    printf("%d\n", atoi(++p));
11
  return 0;
12
}

Die Zeile mit dem printf kannst du natürlich durch etwas anderes 
ersetzen, bspw.
1
array[n++] = atoi(++p);

wenn du die gefundenen Zahlen in ein Array schreiben möchtest.

von Peter H. (Gast)


Lesenswert?

Hallo noch einmal an alle!

Hab jetzt mein Programm mit folgender Variante die letzte Zeit laufen 
gehabt:

Also der String sieht so aus:

>"PARAM#123*456+789:"

Und so lese ich das ein:

>zahl1=atoi(strchr(string,'#')+1);
>zahl2=atoi(strchr(string,'*')+1);
>zahl3=(atoi(strchr(string,'+')+1));

Nach längerem Testen stellte sich nun heraus, dass diese Art nicht immer 
zuverlässig ist. D.h. manchmal steht in den Variablen eine andere Zahl 
als im String und manchmal gar nichts.

Vielleicht sollte ich noch erwähnen, dass ich den String über die 
serielle Schnittstelle einlese, aber das Einlesen funktioniert.

Hat vielleicht einer eine Idee oder eine andere sichere Variante?

Bin für jeden Tip dankbar!

lg Peter

von Uhu U. (uhu)


Lesenswert?

Das ist ja alles ziemlich vage. Ich würde drauf tippen, daß da 
irgendwelcher Schrott eingelesen wird, der Deinen Parser aus dem Gleis 
haut.

Nur ohne gesichertes Wissen über die Eingangsdaten kommst Du nicht 
weiter... interessant ist nicht, was die Gegenseite der seriellen 
Leitung abgeschickt hat, sondern was tatsächlich angekommen ist.

von Karl H. (kbuchegg)


Lesenswert?

Peter H. wrote:
> Hallo noch einmal an alle!
>
> Hab jetzt mein Programm mit folgender Variante die letzte Zeit laufen
> gehabt:
>
> Also der String sieht so aus:
>
>>"PARAM#123*456+789:"
>
> Und so lese ich das ein:
>
>>zahl1=atoi(strchr(string,'#')+1);
>>zahl2=atoi(strchr(string,'*')+1);
>>zahl3=(atoi(strchr(string,'+')+1));
>
> Nach längerem Testen stellte sich nun heraus, dass diese Art nicht immer
> zuverlässig ist. D.h. manchmal steht in den Variablen eine andere Zahl
> als im String

Beispiel?

> und manchmal gar nichts.
Gar nichts kann nicht sein. Ein int hat immer einen Wert

>
> Hat vielleicht einer eine Idee

Übernimm nie das Ergebnis eines strchr ungeprüft.
wenn der NULL zurückliefert weiss niemand was der
atoi für ein Ergebnis liefern wird.

Dann bleieben noch die üblichen Verdächtigen:
Fehler sonstwo, Array Überlauf, String zu klein dimensioniert, ...
Dinge in der Art

> oder eine andere sichere Variante?

Das grundsätzliche Vorgehen ist ok.

von Peter H. (Gast)


Lesenswert?

@Karl heinz Buchegger

Hallo! Danke erstmal für die schnelle Antwort.

Also wie schon gesagt schicke ich den String über die serielle 
Schnittstelle und der passt so, dass ist sicher.

Woran ich merke, dass da was ab und zu nicht stimmt?

Wenn ich bestimmte Werte per serieller Schnittstelle schicke, dann setze 
ich Leds um zu überprüfen, ob sie richtig eingelesen wurden. Es 
funktioniert ja auch an und ab, aber wie gesagt nicht immer. Und dass 
ist das, was ich überhaupt nicht verstehe, wieso das manchmal geht und 
wieso nicht.

Der Einlese-String ist auch groß genug, von da her dürfte auch nichts 
sein. Wo könnte dann der Fehler sein?

Wo ist ein Fehler, wenn es manchmal geht und dann wieder nicht?

Hoffe auf weitere Antworten wie auch auf etwaige andere 
Lösungsvorschläge.

lg Peter

von Karl H. (kbuchegg)


Lesenswert?

Peter H. wrote:
> @Karl heinz Buchegger
>
> Hallo! Danke erstmal für die schnelle Antwort.
>
> Also wie schon gesagt schicke ich den String über die serielle
> Schnittstelle und der passt so, dass ist sicher.
>
> Woran ich merke, dass da was ab und zu nicht stimmt?
>
> Wenn ich bestimmte Werte per serieller Schnittstelle schicke, dann setze
> ich Leds um zu überprüfen, ob sie richtig eingelesen wurden. Es
> funktioniert ja auch an und ab, aber wie gesagt nicht immer. Und dass
> ist das, was ich überhaupt nicht verstehe, wieso das manchmal geht und
> wieso nicht.
>
> Der Einlese-String ist auch groß genug, von da her dürfte auch nichts
> sein. Wo könnte dann der Fehler sein?
>
> Wo ist ein Fehler, wenn es manchmal geht und dann wieder nicht?

Das ist sehr, sehr schwer zu sagen ohne Source Code.
Selbst mit Source Code ist es schwer :-)

Normalerweise sind solch sporadische Dinge auf
Array Overflows, Stack Overflows oder sonstige Schweinereien
zurückzuführen.

Was ich tun würde:
Ich würde auf jeden Fall mal die Return Werte der strchr
anschauen. Wahrscheinlich würde ich mir auch an dieser
Stelle eine Debug-Strecke über die Serielle zurück aufbauen
um zu sehen:
* Welcher String kommt den da (du bist nicht der erste der
  schwört, dass die Eingangswerte in Ordnung sind und wenn man
  dann genauer hinschaut, stellt man fest, dass dem nicht so ist :-)
* Welche Teilstrings wurden mit dem strchr identifiziert
* Was ist das Ergebnis vom atoi()
Ohne solche Debug-Mittel ist das ziemlich schwer zu finden.

Ich weiss schon, du willst wahrscheinlich hören, dass strchr oder
atoi manchmal Fehler machen. Schmink dir das gleich wieder ab.
Der Fehler liegt mit 99.9% Sicherheit in deinem Code.

von Peter H. (Gast)


Lesenswert?

@Karl heinz Buchegger

>Ich weiss schon, du willst wahrscheinlich hören, dass strchr oder
>atoi manchmal Fehler machen. Schmink dir das gleich wieder ab.
>Der Fehler liegt mit 99.9% Sicherheit in deinem Code.

Du kennst mich ja gut. ;-)

Ja, du hast wahrscheinlich recht, also dann werde ich mal überprüfen, 
was strch() genau findet und was atoi() liefert.

Eins wäre vielleicht noch zu sagen:

Die Daten von der seriellen Schnittstelle kommen von einem Java 
Programm.
Wenn ich aber nun das Java-Programm mittels Hyperterminal simuliere. 
Also per Hand eintippe was kommen soll dann funktioniert es immer.

Vielleicht fällt dir dazu noch was ein?

lg Peter



von Unbekannter (Gast)


Lesenswert?

> Wenn ich aber nun das Java-Programm mittels Hyperterminal simuliere.
> Also per Hand eintippe was kommen soll dann funktioniert es immer.

Na, wo wird dann wohl der Fehler liegen????

von Karl H. (kbuchegg)


Lesenswert?

Peter H. wrote:
> @Karl heinz Buchegger
>
> Eins wäre vielleicht noch zu sagen:
>
> Die Daten von der seriellen Schnittstelle kommen von einem Java
> Programm.
> Wenn ich aber nun das Java-Programm mittels Hyperterminal simuliere.
> Also per Hand eintippe was kommen soll dann funktioniert es immer.

Da klingeln bei mir alle Alarmglocken, dass du dir
auf jeden Fall das was von der Schnittstelle kommt in
irgendeiner Form anschauen sollst.

>
> Vielleicht fällt dir dazu noch was ein?

Da fällt mir zum Beispiel ein, dass das Java Programm
die Daten wesentlich schneller senden kann als du tippen
kannst -> hast du ein Handshake implementiert?

von Peter H. (Gast)


Lesenswert?

So, hab jetzt mal ausgiegig getestet.

Ich hab mir den ganzen String gespeichert und dann wieder ausgeben.

Bei den werten Zahlen 2, 50 und 100 sollen leds leuchten.
Jetzt hat z.B. nur die led für 2 geleuchtet, aber der String sah 
folgendermaßen aus:

>PARAM#002*050+0100:

D.h. es müsste funktionieren. Also weiter Fehlersuche.


von Uhu U. (uhu)


Lesenswert?

>PARAM#002*050+0100:

Woher weiß Du, daß der Sting so ausgesehen hat? Hast Du ihn im µC 
gespeichert und dann im Debugger angesehen?

von Peter D. (peda)


Lesenswert?

Führende 0: atoi interpretiert Zahl als oktal

Peter

von Peter H. (Gast)


Lesenswert?

@Uhu Uhuhu

Ich hab ihn wieder zum hyperterminal geschickt!

@Peter Dannegger

Heißt das, ich muss schauen, dass vor der Zahl keine Nullen kommen? Aber 
im Hyperterminal hat es auch mit Nullen davor geklappt.

von Peter H. (Gast)


Lesenswert?

Ach ja, noch was:

Also im String steht:

>PARAM#002*050+0100:

Die leds für zahl1 und zahl2 leuchten, für die zahl3 nicht, obwohl es im 
String steht.
Dann hab ich mir die zahlen noch einmal geschickt
zahl1=2
zahle2=50
zahl3=0

???

also kann es doch am Einlesen liegen, oder?

von Peter D. (peda)


Lesenswert?

Peter H. wrote:

> im Hyperterminal hat es auch mit Nullen davor geklappt.

Dann macht atoi wohl doch kein oktal draus.


Peter

von Uhu U. (uhu)


Lesenswert?

> Führende 0: atoi interpretiert Zahl als oktal

Nein, habe gerade die Definition für atoi bei M$ nachgelesen - hätte 
mich auch schwer verblüfft, wenn Du recht hättest...

von Uhu U. (uhu)


Lesenswert?

Wenn Du einen Debugger an Deinen µC hast, dann schreib doch einfach 
hinter den Befehl, der die letzte Zahl einliest, sowas:

   if (zahl3 == 0)
      zahl3 = zahl3;

Auf die bedingt ausgeführte Anweisung - die nichts bewirkt - setzt Du 
einen Debugger-Haltepunkt.

Damit Du die Strings ansehen kannst, machst Du was in der Art:

   char *S1, *S2, S3;

   S1 = strchr(string,'#') + 1;
   zahl1=atoi(S1);
   ...

Dann kannst Du Dir die Strings im Debugger ansehen und mußt nicht 
rätselraten... Achte auch darauf, daß die S*-Pointer auch wirklich in 
Deinen Puffer zeigen!

von Peter H. (Gast)


Lesenswert?

@Uhu Uhuhu

Ich muss auch nicht rätselraten, ich hab es zwar nicht mit dem Debugger 
gemacht, aber ich weiß, dass im String das Richtige steht.

Das hab ich jetzt ausgiebig getestet.

Und ich weiß jetzt auch immer, was in den Zahlen steht.

Wenn die entsprechende Led nicht leuchtet, dann steht in der Zahl auch 
nicht das Richtige.

Ich habe die Zahlen öfter überprüft, nicht nur mit den Leds. Ich hab sie 
auch so anggesehen.

Somit muss wohl der Fehler beim Einlesen sein, oder?

Also bei:

>zahl1=atoi(strchr(string,'#')+1);
>zahl2=atoi(strchr(string,'*')+1);
>zahl3=(atoi(strchr(string,'+')+1));

von Uhu U. (uhu)


Lesenswert?

Glaubst Du wirklich, daß Du auf Anhieb in den Routinen, die vor Dir 
tausende von Programmierern erfolgreich benutzt haben und deren korrekte 
Implementierung seit 30 Jahren bekannt ist, einen Fehler findest?

Eher fällt der erste Mai auf einen Freitag den 13...

Checks nochmal so nach, wie ich es vorhin beschrieben habe.

von Unbekannter (Gast)


Lesenswert?

> Somit muss wohl der Fehler beim Einlesen sein, oder?

Stimmt.

Du machst keine Fehler. Nur die anderen.

von Lukas D. (ltd)


Lesenswert?

hab mir den thread gerade durchgelesen und da stellt sich mir doch eine 
frage:

@ Peter H.: Wieso bist du dir so sicher das der string, den du von der 
seriellen schnittstelle bekommst tatsächlich dem string entspricht, den 
du erwartest?

von Peter H. (Gast)


Lesenswert?

@Lukas D.

Hallo!

Ich habe das Programm sozusagen angehalten, den String abgespeichtert 
und dann wieder über die serielle Schnittstelle zum Hyperterminal 
gesendet. D.h. ich habe das Java-Programm geschlossen und dann den 
String zum Hyperterminal gesendet. Und der String passt, nur in den 
Zahlen steht manchmal das Richtige drinnen und manchmal nicht.

Ich bin immer noch nicht dahinter gekommen wieso.

@all

Mir ist schon klar, dass ich da wo einen Fehler habe. Is ja klar, wer 
sonst? Und dass die Funktionen funktionieren will ich auch nicht 
anzweifeln, sondern ich denke mir nur, dass ich sie eventuell falsch 
verwende.

lg Peter

von Uhu U. (uhu)


Lesenswert?

Nochmal: Machs, wie ich am 04.05.2007 20:07 geschrieben habe. Du mußt 
wirklich in die Variablen im µC gucken, alles andere ist 
Kaffeesatzleserei.

Es ist z.B. denkbar, daß es sich um ein dynamisches Problem handelt, das 
erst dann entsteht, wenn Du den empfangenen String schon zurückgeschickt 
hast - z.B. daß während der Verarbeitung des Pufferinhaltes von der 
Gegenstelle schon wieder was neues in den Puffer geschrieben wird - 
Fachausdruck Racecondition.

Solche Dinger kriegt man am besten mit der Haltepunktfalle, die ich oben 
skizziert habe.

von Peter H. (Gast)


Lesenswert?

@Uhu Uhuhu

Hallo!

Es könnte tatsächlich sein, dass sich da auch noch andere Zeichen in den 
String schmuggeln. Weil es werden kurz danach, auch noch andere Zeichen 
vom Java aus gesendet (vl ja zeitgleich???). Ich verstehe nur nicht, 
wieso dann der String im Hyperterminal passt. Aber ich glaube schon, 
dass du recht hast, dass ich nur im µC schauen kann, was wirklich 
drinnen steht.

Das Problem ist leider nur, dass ich vom debuggen nicht viel Ahnung habe 
und es deswegen damit noch nicht probiert habe.

Also kann es sein, dass obwohl der String im Hyperterminal richtig 
steht, er im µC anders gespeichert ist?


von Uhu U. (uhu)


Lesenswert?

> Also kann es sein, dass obwohl der String im Hyperterminal richtig
>steht, er im µC anders gespeichert ist?

Ja: Wenn er kurz nach dem Absenden an das HT im µC zerdroschen wurde - 
z.B. von der Interrupt-Routine, die für das Datenempfangen auf der 
Leitung verantwortlich ist.

Benutzt Du nur einen einzigen Empfangspuffer?

> Das Problem ist leider nur, dass ich vom debuggen nicht viel Ahnung habe
> und es deswegen damit noch nicht probiert habe.

Dann ist das die Gelegenheit, es zu lernen...

von Peter H. (Gast)


Lesenswert?

Ja, ich habe nur einen Empfangsbuffer.

Aber den String schicke ich erst, nachdem ich die Zahlen eingelesen 
habe. Und siehe da, in den Zahlen steht nicht das Richtige, aber dann im 
Hyperterminal steht der String richtig.

von Uhu U. (uhu)


Lesenswert?

Poste mal Deinen Code.

von Peter H. (Gast)


Lesenswert?

So, das sind jetzt nur ein paar Auszüge:

die Variablen sind global und volatile
1
void main (void)
2
{
3
  init();
4
  led1=0;
5
    
6
  while(1)
7
  {
8
    getParam();
9
10
    //Hier arbeite ich mit den Zahlen dann weiter
11
12
  }    
13
    
14
}
15
16
void serISR (void) interrupt 4
17
{
18
  if(RI)
19
  {
20
    RI=0;
21
    rec=SBUF;
22
23
    if((rec=='\r')||(rec=='\n'))
24
    {  
25
      serflag=1;
26
    }
27
28
    else
29
    {
30
      receive[cnt]=rec;
31
      cnt++;
32
    }
33
  }
34
}
35
36
void getParam (void)  
37
{  
38
  if(serflag==1)
39
  { 
40
    serflag=0;
41
          
42
    if(strstr(receive, "PARAM"))
43
    {                
44
      zahl1=0;
45
      zahl2=0;
46
      zahl3=0;
47
      zahl1=atoi(strchr(receive,'#')+1);
48
      zahl2=atoi(strchr(receive,'*')+1);
49
      zahl3=(atoi(strchr(receive,'+')+1))*10;
50
51
      //Leds zum Testen
52
      if(zeit==2)
53
        led2=0;
54
        
55
      if(kP==50)
56
        led3=0;
57
        
58
      if(maxPegelstand==1000)
59
        led4=0;  
60
    }
61
    clearString();
62
    cnt=0;
63
  }
64
}
65
66
void clearString (void)
67
{
68
  int i;
69
70
  for(i=0; i<200; i++)
71
  {
72
    receive[i]=0;
73
  }
74
}

  

von Uhu U. (uhu)


Lesenswert?

Überleg Dir mal, was passiert, wenn in receive gerade "PAR" steht, wenn 
getParam aufgerufen wird...

Ich sehe gerade, daß das nicht vorkommen sollte...

Aber was passiert, wenn Zeichen kommen, bevor getParam cnt = 0 
ausgeführt hat?

Ich würde sagen, dann zerklopft die ISR Dir den Speicher...

Wenn das nicht zum Absturz führt, können natürlich trotzdem Daten 
überschrieben werden. Das Mindeste ist jedoch, daß der betreffende 
Datensatz verloren geht.

von Peter H. (Gast)


Lesenswert?

Wie gesagt, es handelt sich um Codeauszüge.

Hätte ich aber dazuposten können, mein Fehler:

Also, main noch einmal:
1
void main (void)
2
{
3
  init();
4
  led1=0;
5
    
6
  while(1)
7
  {
8
9
    if((serflag==1))  
10
    {
11
      serflag=0;
12
      if(strstr(receive,"ready"))
13
      {
14
        getParam();
15
      }
16
    }
17
18
    //Hier arbeite ich mit den Zahlen dann weiter
19
20
  }    
21
    
22
}

Aber außerdem wird serflag=1 erst gesetzt, wenn '\n' oder '\r' kommt und 
'\n' oder '\r' kommen erst am Ende des Strings, also muss der String 
schon komplett sein.

von Uhu U. (uhu)


Lesenswert?

Sieh nochmal meinen vorigen Beitrag an - ich hatte daran noch 
rumgebastelt...

von Peter H. (Gast)


Lesenswert?

Es ist sogar der Fall, dass bevor cnt=0 gesetzt wird, noch Zeichen 
kommen.
Werden die dann nicht einfach hinten drangehängt und somit kann ich den 
String ja trotzdem auslesen, oder?

von Uhu U. (uhu)


Lesenswert?

Du nullst den Puffer aus und dann finden die str*-Routinen den hinten 
angepappten Datensatz nicht, weil sie vorher auf ein NUL-Zeigen gestoßen 
sind.

Wahrscheinlich bekommst Du es folgendermaßen hin:

Wenn die ISR einen vollständigen Satz empfangen hat, kopiert sie ihn in 
einen separaten Puffer, der von getParam gelesen wird, setzt cnt selbst 
zurück und ist dann sofort wieder Empfangsbereit.

GetParam nullt nur seinen eigenen Puffer aus, wenn sie fertig ist.

Die ISR kopiert keine Daten in den Ausgabepuffer, wenn dessen erstes 
Byte != 0 ist und setzt stattdessen ein Overrun-Flag. Dabei geht ein 
Satz verloren.

Übrigens: Keiner der beiden Puffer muß volatile sein - überleg Dir 
warum...

von Peter H. (Gast)


Lesenswert?

Also, hab ich das richtig verstanden?
1
void main (void)
2
{
3
  init();
4
  led1=0;
5
    
6
  while(1)
7
  {
8
9
    if((serflag==1))  
10
    {
11
      serflag=0;
12
      if(strstr(receive2,"ready"))
13
      {
14
        getParam();
15
      }
16
    }
17
18
    //Hier arbeite ich mit den Zahlen dann weiter
19
20
  }    
21
    
22
}
23
24
void serISR (void) interrupt 4
25
{
26
  if(RI)
27
  {
28
    RI=0;
29
    rec=SBUF;
30
31
    if((rec=='\r')||(rec=='\n'))
32
    {  
33
      serflag=1;
34
      strcpy(receive2, receive);
35
      cnt=0;
36
      clearString();
37
    }
38
39
    else
40
    {
41
      receive[cnt]=rec;
42
      cnt++;
43
    }
44
  }
45
}
46
47
void getParam (void)  
48
{  
49
  if(serflag==1)
50
  { 
51
    serflag=0;
52
          
53
    if(strstr(receive2, "PARAM"))
54
    {                
55
      zahl1=0;
56
      zahl2=0;
57
      zahl3=0;
58
      zahl1=atoi(strchr(receive2,'#')+1);
59
      zahl2=atoi(strchr(receive2,'*')+1);
60
      zahl3=(atoi(strchr(receive2,'+')+1))*10;
61
62
      //Leds zum Testen
63
      if(zahl1==2)
64
        led2=0;
65
        
66
      if(zahl2==50)
67
        led3=0;
68
        
69
      if(zahl3==1000)
70
        led4=0;  
71
    }
72
    clearString2();
73
  }
74
}
75
76
void clearString (void)
77
{
78
  int i;
79
80
  for(i=0; i<200; i++)
81
  {
82
    receive[i]=0;
83
  }
84
}
85
86
void clearString2 (void)
87
{
88
  int i;
89
90
  for(i=0; i<200; i++)
91
  {
92
    receive2[i]=0;
93
  }
94
}

Meiner Meinung nach müssen receive und receive2 schon volatile sein, 
sonst steht ja nicht immer der aktuelle Wert drinnen, oder? Und 
übergeben tu ich die Strings ja nie.

von Uhu U. (uhu)


Lesenswert?

Ja, das kommt dem sehr nahe...

Ein paar kleine Optimierungen:

Sieh mal nach, ob Dein Compiler eine Funktion memset, oder setmem kennt 
- dann brauchst Du das Rad nicht nochmal zu erfinden.

Aber generell brauchst Du den zweiten Puffer garnicht auszunullen, denn 
die ISR benutzt strcpy und die kopiert die abschließende 0 mit.

Das clearString() in der ISR kannst Du Dir auch sparen, wenn Du im Block

    if((rec=='\r')||(rec=='\n')) {
       receive[cnt]= 0;
       ...
    }

den ersten Puffer ordentlich terminierst.

Zum Thema 'volatile':
Der Puffer, der nur von der ISR zugegriffen wird, muß nicht volatile 
sein - es gibt keine konkurrierenden Zugriffe.

Statt den zweiten Puffer volatile zu machen, reicht es aus, serflag 
volatile zu definieren; wenn die von der ISR gesetzt ist, greift die ja 
nicht mehr darauf zu.

Ein weiteres mögliches Problem: 'if((rec=='\r')||(rec=='\n'))'.

Was wenn die Gegenstelle - wie das unter Windows üblich ist - eine Zeile 
mit \r\n abzuschließt?

von Peter H. (Gast)


Lesenswert?

Ja, stimmt, danke!

Ich werde dann das mal alles programmieren und testen und schauen, ob es 
funktioniert.

Vielen Dank für deine Hilfe.

lg Peter

von Peter H. (Gast)


Lesenswert?

Mit '\n' und '\r' hast du wahrscheinlich recht.

Ich hab mir nun folgendes überlegt:

In meinem Programm kommen öfter solche Abfragen vor und es funktioniert 
immer, bis auf das eine mal, also könnte ich es doch einfach so machen:
1
void getParam (void)  
2
{  
3
  if(serflag==1)
4
  { 
5
    serflag=0;
6
          
7
    if(strstr(receive2, "PARAM"))
8
    {  
9
      strcpy(receive2,receive);              
10
      zahl1=0;
11
      zahl2=0;
12
      zahl3=0;
13
      zahl1=atoi(strchr(receive2,'#')+1);
14
      zahl2=atoi(strchr(receive2,'*')+1);
15
      zahl3=(atoi(strchr(receive2,'+')+1))*10;
16
17
      //Leds zum Testen
18
      if(zeit==2)
19
        led2=0;
20
        
21
      if(kP==50)
22
        led3=0;
23
        
24
      if(maxPegelstand==1000)
25
        led4=0;  
26
    }
27
  }
28
}

Also nur bei dieser Abfrage mit receive2 arbeiten, dann kann mir ja auch 
nichts mehr reinpfuschen, oder?

von Uhu U. (uhu)


Lesenswert?

Das ist keine gute Idee, denn die Synchronisation zwischen ISR und 
Vordergrund wird dadurch gelockert. Das Umkopieren sollte die ISR 
machen.

Wenn sich Deine ISR merkt, daß sie gerade den Puffer umkopiert hat, 
reicht es, alle Zeichen kleiner ' ' einfach wegzuschmeißen, bis
was >= ' ' kommt und dann wieder in den ersten Puffer kopieren.

Der Vorteil ist, daß Du unabhängig von Betriebssystemgebräuchen 
bezüglich Zeilenende wirst - solange \r und/oder \n benutzt werden.

von Peter H. (Gast)


Lesenswert?

Da hast du wieder Recht, ich werd das dann mal so probieren.

Danke noch einmal für die vielen Tips und Hilfestellungen!

von Uhu U. (uhu)


Lesenswert?

Na wenigstens ist der erste Mai gerettet...

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.