Docs

Micro-controllers, wireless transmission and database

Head

STM32 NEO-6M GPS

Prerequisites

This project assumes you have already installed STM32CubeIDE. You need to have previously done a basic blink sketch with blue-pill using STM32CubeIDE. I have made a complete video from installing STM32CubeIDE to LED blink program. You can watch it by clicking this link. https://www.youtube.com/watch?v=kXg467nVd_A

Wiring Diagram

Diagram

Image

STM32CubeIDE Settings

Enable USART1 asynchronous

Parameter Settings --> Basic Parameters --> Baud rate 9600

NVIC Settings --> USART1 global interrupt --> (Tick)

Additional code on top of STM32CubeIDE generated code

/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN 0 */
uint8_t rxBuffer[128] = {0};
uint8_t rxIndex = 0;
uint8_t rxData;
float nmeaLong;
float nmeaLat;
float utcTime;
char northsouth;
char eastwest;
char posStatus;
float decimalLong;
float decimalLat;

float nmeaToDecimal(float coordinate) {
    int degree = (int)(coordinate/100);
    float minutes = coordinate - degree * 100;
    float decimalDegree = minutes / 60;
    float decimal = degree + decimalDegree;
    return decimal;
}

void gpsParse(char *strParse){
  if(!strncmp(strParse, "$GPGGA", 6)){
    sscanf(strParse, "$GPGGA,%f,%f,%c,%f,%c",
      &utcTime, &nmeaLat, &northsouth, &nmeaLong, &eastwest);
    decimalLat = nmeaToDecimal(nmeaLat);
    decimalLong = nmeaToDecimal(nmeaLong);
  }
  else if (!strncmp(strParse, "$GPGLL", 6)){
    sscanf(strParse, "$GPGLL,%f,%c,%f,%c,%f",
      &nmeaLat, &northsouth, &nmeaLong, &eastwest, &utcTime);
    decimalLat = nmeaToDecimal(nmeaLat);
    decimalLong = nmeaToDecimal(nmeaLong);
  }
  else if (!strncmp(strParse, "$GPRMC", 6)){
    sscanf(strParse, "$GPRMC,%f,%c,%f,%c,%f,%c",
      &utcTime, &posStatus, &nmeaLat, &northsouth, &nmeaLong, &eastwest);
    decimalLat = nmeaToDecimal(nmeaLat);
    decimalLong = nmeaToDecimal(nmeaLong);
  }
}

int gpsValidate(char *nmea){
    char check[3];
    char calculatedString[3];
    int index;
    int calculatedCheck;

    index=0;
    calculatedCheck=0;

    // Ensure that the string starts with a "$"
    if(nmea[index] == '$')
        index++;
    else
        return 0;

    //No NULL reached, 75 char largest possible NMEA message, no '*' reached
    while((nmea[index] != 0) && (nmea[index] != '*') && (index < 75)){
        calculatedCheck ^= nmea[index];// calculate the checksum
        index++;
    }

    if(index >= 75){
        return 0;// the string is too long so return an error
    }

    if (nmea[index] == '*'){
        check[0] = nmea[index+1];    //put hex chars in check string
        check[1] = nmea[index+2];
        check[2] = 0;
    }
    else
        return 0;// no checksum separator found therefore invalid data

    sprintf(calculatedString,"%02X",calculatedCheck);
    return((calculatedString[0] == check[0])
        && (calculatedString[1] == check[1])) ? 1 : 0 ;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance==USART1)
  {
    // if the character received is other than 'enter' ascii13, save the data in buffer
    if(rxData!='\n' && rxIndex < sizeof(rxBuffer))
    {
      rxBuffer[rxIndex++]=rxData;
    }
    else
    {
      if(gpsValidate((char*) rxBuffer)) gpsParse((char*) rxBuffer);
      rxIndex=0;
      memset(rxBuffer,0,sizeof(rxBuffer));
    }
    HAL_UART_Receive_IT(&huart1,&rxData,1); // Enabling interrupt receive again
  }
}
/* USER CODE END 0 */

  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart1,&rxData,1);
  /* USER CODE END 2 */