4

I am trying to use an STM32 microcontroller (STM32L010C6T6 to be exact) to parse NMEA sentences from a GPS module over UART. I receive the messages fine, but run into issues when I look for specific strings within the messages.

I read in 700 characters from the GPS module over UART and store them in a buffer. I want to find a "GNGLL" sentence within the buffer. I use the C function strstr() to search my buffer for the string "GNGLL" but the function never finds the string, even when it should be there. I print my buffer contents over a different UART to a serial terminal on my PC, and I've even used the "live expressions" debug feature of the STM32cubeide to verify that the string is there. Here is the relevant code.

#include "main.h"
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <math.h>


uint8_t gps_uartbuf[700] = {0};
char gps_uartbuf_char[700] = {'A'};


void getlatlon(char latlon[]){
    char *mylat = NULL;
    const char gps_gngll[5] = {'G','N','G','L','L'};
    __HAL_UART_CLEAR_IT(&huart2, UART_CLEAR_NEF|UART_CLEAR_OREF);
    HAL_UART_Receive(&huart2, gps_uartbuf, (uint16_t)700, 1000);
    int x = 0;
    for(x=0; x<700; x++){
        gps_uartbuf_char[x] = (char)gps_uartbuf[x];
    }

    gps_uartbuf_char[699] = '\0';

    mylat = strstr(gps_uartbuf_char, gps_gngll);

    if(mylat == NULL){
        //DID NOT FIND GPGLL
        return;
    }else{
        //do stuff
    }
}

Why is the strstr() never finding the string?

Nick
  • 199
  • 7
  • I think this question should be migrated to Stack Overflow as it's only really related to programming, not electronics – ScottishTapWater Jul 18 '22 at 09:14
  • 2
    @ScottishTapWater - Hi, There is overlap between what is on-topic here and at SO. Firmware programming is [on-topic](/help/on-topic) here too. So while this could have been asked originally on SO, it is not off-topic here. As it has been answered here, and migration to SO is often unsuccessful (e.g. someone will find a dup on SO and reject the migration) I'm not going to migrate this one, on this occasion, but thanks for the comment. – SamGibson Jul 18 '22 at 09:25

1 Answers1

18

strstr expects two zero-terminated strings as arguments, which isn't the case for the string containing the sequence of characters to match.

This string starts with a "GNGLL", but is followed by a number of unspecified characters. It's only terminated when a (virtually) random '\0' appears in this sequence.

Change your code as follows:

const char gps_gngll[] = {'G','N','G','L','L','\0'};

Or better yet:

const char gps_gngll[] = "GNGLL";
Velvel
  • 3,591
  • 3
  • 12
  • 30
  • 1
    That was it. As soon as I added the '\0' termination character it started working. – Nick Jul 16 '22 at 19:13
  • 2
    @Nick: Just to restate the obvious, any null bytes in your buffer content can also cause `strstr` to fail (by stopping the search too early). If you may need to deal with those, you'll have to write your own search function (see e.g. [this question on Stack Overflow](https://stackoverflow.com/questions/8584644/strstr-for-a-string-that-is-not-null-terminated)) or use some nonstandard extension like `memmem` from GCC. – Ilmari Karonen Jul 17 '22 at 23:36
  • 1
    This is somewhat relevant - https://stackoverflow.com/a/1992271/1730895 `memmem()` – Kingsley Jul 18 '22 at 00:21
  • @IlmariKaronen you make a very good point, but the specific case of GNSS is a (almost) human readable string, which should not contain any null character except for its own termination. I do see op initializing the buffer with a bunch of 'A' which is a bit confusing in my opinion. – Vladimir Cravero Jul 18 '22 at 09:04