Forum: Mikrocontroller und Digitale Elektronik STM32Cubeide strstr


von Sascha F. (sascha_focus) Benutzerseite


Lesenswert?

Hi,

versuche mich gerade , ein ESP8266 per UART anzubinden. Der Uart läuft 
im Interrupt und füllt auch das Array. Nun will ich im Arry auf Strings 
vergleichen:
1
char RxBuffer[32768]={0,};
2
uint16_t RxBufferIndex=0;
3
4
bool Wifi_WaitForString(uint32_t TimeOut_ms,uint8_t *result,uint8_t CountOfParameter,...)
5
{
6
  /*
7
   * It uses the CountOfParameter and the Parameters after that to compare with the
8
   * information that it was received in the UART RX. If the parameter is in the
9
   * received string the functions return a true value and the position of the
10
   * parameter (according to the position in the function)
11
   *
12
   * Ex:
13
   * Wifi_WaitForString(_WIFI_WAIT_TIME_LOW,&result,2,"OK","ERROR")
14
   *
15
   * If the ESP8266 return a AT+OK after the last command, the function is going to
16
   * return a true value and the result number would be 1.
17
   */
18
19
  if(result == NULL)
20
    return false;
21
  if(CountOfParameter == 0)
22
    return false;
23
24
  *result=0;
25
26
  va_list tag;
27
    va_start (tag,CountOfParameter);
28
    char *arg[CountOfParameter];
29
    for(uint8_t i=0; i<CountOfParameter ; i++)
30
      arg[i] = va_arg (tag, char *);
31
  va_end (tag);
32
33
  for(uint32_t t=0 ; t<TimeOut_ms ; t++)
34
  {
35
    delay_ms(1);
36
    for(uint8_t  mx=0 ; mx<CountOfParameter ; mx++)
37
    {
38
      if(strstr((char*)RxBuffer,arg[mx])!=NULL)
39
      {
40
        *result = mx+1;
41
        return true;
42
      }
43
    }
44
  }
45
  // timeout
46
  return false;
47
48
}

Jedoch läuft die Funktion immer in den Timeout, obwohl der gesuchte 
String im Array liegt.

Hat jemand eine Idee, woran es scheitert?

Gruß Sascha

Beitrag #7380650 wurde vom Autor gelöscht.
von K. H. (hegy)


Lesenswert?

Was mir dazu bisher als Fehlerquellen einfällt:

(1) strstr() checkt auch auf Groß-/Kleinschreibung, ok != OK

(2) das durchchecken des Strings dauert länger als man denkt (Timeout)

(3) delay_ms() ist aktives warten nehme ich mal an, wird in der Zeit 
tatsächlich was in den RxBuffer[] geschrieben (DMA, Interrupt)?

(4) wenn das Programm in der Schleife
1
for(uint32_t t=0 ; t<TimeOut_ms ; t++)
 steckt, wird CountOfParameter nicht geändert.

Ich kenne den ESP nicht aber ich gehe mal davon aus, dass die CPU den 
Wert von CountOfParameter bzw. den Inhalt von RxBuffer[] nur dann 
ändert, wenn die CPU das auch darf, also die for-Schleife auch mal 
verlässt und andere Dinge macht. Entweder ist da eine 2. CPU noch aktiv 
(Shared Memory u. dgl.) oder aber durch Interrupts werden die Inhalte 
geändert.

Zu Punkt (1): Aus der man-Page von strstr()
1
strstr(const char *haystack, const char *needle);

The strcasestr() function is like strstr(), but ignores the case of both 
arguments.
1
char *strcasestr(const char *haystack, const char *needle);

: Bearbeitet durch User
von Rahul D. (rahul)


Lesenswert?

Sascha F. schrieb:
> Hat jemand eine Idee, woran es scheitert?

Poste mal bitte mehr Code, so dass man den Kram auch selber compilieren 
könnte.
Hast du deine Funktion mal mit konstanten Werten ausprobiert?
z.B. strstr("ABC", "ABCDEF")

Lass dir doch mal deine args ausgeben.
Groß- und Kleinschreibung hatte Hegy ja schon angesprochen.

von Εrnst B. (ernst)


Lesenswert?

Sascha F. schrieb:
> obwohl der gesuchte
> String im Array liegt.

Vorsicht, demnächst hast du evtl. das umgekehrte Problem, die Funktion 
wird immer Strings finden, die garnicht mehr im buffer vorhanden sind.

Problem: strstr (und andere str*-Funktionen) erwarten Null-Terminierte 
Strings.
Wenn deine UART-Receive-ISR das nicht sicherstellt, solltest du nach 
deinem delay_ms(1) ein
RxBuffer[RxBufferIndex]='\0'; einfügen, und für den Rest der Schleife 
die Interrupts sperren...
Very ugly, I know.

Ansonsten schaut das ganze Konzept schon sehr verkorkst aus

: Bearbeitet durch User
von K. H. (hegy)


Lesenswert?

Rahul D. schrieb:
> Poste mal bitte mehr Code, so dass man den Kram auch selber compilieren
> könnte.

Ist zwar für "auf'm PC" aber geht, damit habe ich gestern mal 
rumgespielt:
str.c:
1
#include <stdio.h>
2
#include <string.h> 
3
#include <stdint.h>
4
#include <stdbool.h>
5
#include <stdarg.h>
6
7
char RxBuffer[32768]={0,};
8
uint16_t RxBufferIndex=0;
9
10
void init(void)
11
{
12
  sprintf(RxBuffer, "_WIFI_WAIT_TIME_LOW,&result,2,PK,ERRORItusestheCountOfParameterandtheParametersafterthatcomparewiththeinformationthatitwasreceivedintheUARTRX.IftheparameterisinthereceivedstringthefunctionsreturnatruevalueandthepositionOKftheparameter(accordingtothepositioninthefunction");
13
}
14
15
void delay_ms(uint32_t cnt)
16
{
17
  for(uint32_t i = 0; i < cnt; i++)
18
    asm ( "NOP" );
19
}
20
21
bool Wifi_WaitForString(uint32_t TimeOut_ms,uint8_t *result,uint8_t CountOfParameter,...)
22
{
23
  /*
24
   * It uses the CountOfParameter and the Parameters after that to compare with the
25
   * information that it was received in the UART RX. If the parameter is in the
26
   * received string the functions return a true value and the position of the
27
   * parameter (according to the position in the function)
28
   *
29
   * Ex:
30
   * Wifi_WaitForString(_WIFI_WAIT_TIME_LOW,&result,2,"OK","ERROR")
31
   *
32
   * If the ESP8266 return a AT+OK after the last command, the function is going to
33
   * return a true value and the result number would be 1.
34
   */
35
36
  uint32_t cnt = 0;
37
38
  if(result == NULL)
39
    return false;
40
41
  if(CountOfParameter == 0)
42
    return false;
43
44
  *result=0;
45
46
  va_list tag;
47
    va_start (tag,CountOfParameter);
48
    char *arg[CountOfParameter];
49
50
    for(uint8_t i=0; i<CountOfParameter ; i++)
51
    {
52
      arg[i] = va_arg (tag, char *);
53
      cnt = i;
54
    }
55
    printf("va_arg: i = %i\n", cnt);
56
  va_end (tag);
57
58
  for(uint32_t j = 0; j < cnt; j++)
59
  { 
60
    printf("arg[%i] = %s\n", j, arg[j]);
61
  }
62
63
  for(uint32_t t=0 ; t<TimeOut_ms ; t++)
64
  {
65
    delay_ms(1);
66
    for(uint8_t  mx=0 ; mx<CountOfParameter ; mx++)
67
    {
68
      printf("arg[mx] = %s, mx = %i\n", arg[mx], mx);
69
      if(strstr((char*)RxBuffer, arg[mx]) != NULL)
70
      {
71
        *result = mx+1;
72
        printf("result (%s) = %s @%i\n", RxBuffer, arg[mx], mx);
73
        // return true;
74
      }
75
    }
76
  }
77
78
  // timeout
79
  return false;
80
}
81
82
int main(void)
83
{
84
  uint8_t result = 0;
85
86
  init();
87
  Wifi_WaitForString(1, &result, 5, "OK", "ERROR", "Fail", "Stop", "Halt");
88
89
  printf("result: %i\n", result);
90
}
Mit
gcc -Wall -O2 -s str.c -o str
compilieren, geht ohne Fehler und Warnungen.
Ich habe ein paar printf()'s eingebaut, wie man sieht und ein paar 
kleine Änderungen.

Vergessen, der Output:
1
$ ./str
2
va_arg: i = 4
3
arg[0] = OK
4
arg[1] = ERROR
5
arg[2] = Fail
6
arg[3] = Stop
7
arg[mx] = OK, mx = 0
8
result (_WIFI_WAIT_TIME_LOW,&result,2,PK,ERRORItusestheCountOfParameterandtheParametersafterthatcomparewiththeinformationthatitwasreceivedintheUARTRX.IftheparameterisinthereceivedstringthefunctionsreturnatruevalueandthepositionOKftheparameter(accordingtothepositioninthefunction) = OK @0
9
arg[mx] = ERROR, mx = 1
10
result (_WIFI_WAIT_TIME_LOW,&result,2,PK,ERRORItusestheCountOfParameterandtheParametersafterthatcomparewiththeinformationthatitwasreceivedintheUARTRX.IftheparameterisinthereceivedstringthefunctionsreturnatruevalueandthepositionOKftheparameter(accordingtothepositioninthefunction) = ERROR @1
11
arg[mx] = Fail, mx = 2
12
arg[mx] = Stop, mx = 3
13
arg[mx] = Halt, mx = 4
14
result: 2

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

K. H. schrieb:
> void delay_ms(uint32_t cnt)
> {
>   for(uint32_t i = 0; i < cnt; i++)
>     asm ( "NOP" );
> }

Kein Wunder dass man damit in ein Timeout fällt.

von K. H. (hegy)


Lesenswert?

Wastl schrieb:
> Kein Wunder dass man damit in ein Timeout fällt.

Ich bin davon ausgegangen, dass die delay_ms() Funktion sowas in der Art 
ist und deswegen habe ich mir mal eben schnell so eine 
aktives-Warten-Funktion gebaut.

Bei mir sieht z. B. die HAL-Delay() Funktion so aus:
1
void HAL_Delay(uint32_t Delay) // Delay = ms
2
{
3
    if(Delay == 0)
4
        return;
5
6
    if(Delay > HAL_MAX_DELAY)
7
        return;
8
9
    uint32_t tickstart = HAL_GetTick();
10
11
    while((HAL_GetTick() - tickstart) < Delay);
12
}

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.