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