STM32Cubeide strstr

OP Persönliche Seite #7380589
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 von einem Moderator gelöscht.
#7380753
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);
#7381193
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

#7381204
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
#7381536
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren