4
\$\begingroup\$

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?

\$\endgroup\$
2
  • \$\begingroup\$ I think this question should be migrated to Stack Overflow as it's only really related to programming, not electronics \$\endgroup\$ Jul 18, 2022 at 9:14
  • 2
    \$\begingroup\$ @ScottishTapWater - Hi, There is overlap between what is on-topic here and at SO. Firmware programming is 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. \$\endgroup\$
    – SamGibson
    Jul 18, 2022 at 9:25

1 Answer 1

18
\$\begingroup\$

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";
\$\endgroup\$
4
  • 1
    \$\begingroup\$ That was it. As soon as I added the '\0' termination character it started working. \$\endgroup\$
    – Nick
    Jul 16, 2022 at 19:13
  • 2
    \$\begingroup\$ @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) or use some nonstandard extension like memmem from GCC. \$\endgroup\$ Jul 17, 2022 at 23:36
  • 1
    \$\begingroup\$ This is somewhat relevant - stackoverflow.com/a/1992271/1730895 memmem() \$\endgroup\$
    – Kingsley
    Jul 18, 2022 at 0:21
  • \$\begingroup\$ @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. \$\endgroup\$ Jul 18, 2022 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.