STM32 UART Library for NEO-M9N GNSS module
Please read Liability Disclaimer and License Agreement CAREFULLY
Before going further please read NEO-M9N datasheet
In NEO_M9N.h add the following code
#ifndef __NEO_M9N_H
#define __NEO_M9N_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define RX_BUFFER_LEN 128
//UBX-NAV-POSLLH (0x01 0x02) 0xb5 0x62 0x01 0x02 = 33645237
//UBX-NAV-STATUS (0x01 0x03) 0xb5 0x62 0x01 0x03 = 50422453
//UBX-NAV-TIMEUTC (0x01 0x21) 0xb5 0x62 0x01 0x21 = 553738933
//UBX-NAV-PVT (0x01 0x07) 0xb5 0x62 0x01 0x07 = 117531317
#define PVT_ID 117531317
#define CHECK_SUM_START_POS 2
#define CHECK_SUM_END_POS 101
#define YER_POS 10
#define MON_POS 12
#define DAY_POS 13
#define HOR_POS 14
#define MIN_POS 15
#define SEC_POS 16
#define FIX_POS 26
#define SAT_POS 29
#define LNG_POS 30
#define LAT_POS 34
#define MSL_POS 42
#define COORD_FACTOR 0.0000001f
#define ALTITUDE_FACTOR 0.001f
typedef enum {
NoFix = 0,
DeadReckoningOnly,
Fix2D,
Fix3D,
Combined,
Time,
Reserved
} GPS_FIX_t;
typedef struct GPS_DATA {
uint8_t newData;
float Latitude;
float Longitude;
float Altitude;
uint8_t UTC_Day;
uint8_t UTC_Month;
uint16_t UTC_Year;
uint8_t UTC_Hour;
uint8_t UTC_Minute;
float UTC_Second;
uint8_t Satellites;
uint8_t Fix_Type;
} GPS_DATA_t;
extern volatile uint8_t gpsRxBuffer[RX_BUFFER_LEN];
extern GPS_DATA_t myGpsData;
void processGPS(void);
void M9N_Reset();
void M9N_Start(void);
#ifdef __cplusplus
}
#endif
#endif /* __NEO_M9N_H */
In NEO_M9N.c add the following code
#include "NEO_M9N.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
volatile uint8_t gpsRxBuffer[RX_BUFFER_LEN];
GPS_DATA_t myGpsData;
static uint8_t gpsSecond;
static uint32_t miliSecond;
static uint8_t checkSum(){
uint8_t ckA = 0;
uint8_t ckB = 0;
// printf("----\n");
// printf("0x%.2X 0x%.2X\n", gpsRxBuffer[CHECK_SUM_END_POS], gpsRxBuffer[CHECK_SUM_END_POS+1]);
for(uint8_t i = gpsRxBuffer[CHECK_SUM_START_POS]; i < gpsRxBuffer[CHECK_SUM_END_POS]; i++){
ckA += gpsRxBuffer[i];
ckB = ckB+ckA;
}
if((ckA == gpsRxBuffer[CHECK_SUM_END_POS]) && (ckB == gpsRxBuffer[CHECK_SUM_END_POS+1])) return 1;
return 0;
}
void processGPS(void){
// First message is the ID
uint32_t ID = *(uint32_t *)gpsRxBuffer;
// If we get the UBX-NAV-STATUS (uint32_t)(0xb5 0x62 0x01 0x03)
if(PVT_ID == *(uint32_t *)gpsRxBuffer){
if(checkSum()){
// Set that flag that this is new data - to be used in Asto calculation
myGpsData.newData = 1;
myGpsData.UTC_Year = *(int16_t *)&gpsRxBuffer[YER_POS];
myGpsData.UTC_Month = gpsRxBuffer[MON_POS];
myGpsData.UTC_Day = gpsRxBuffer[DAY_POS];
myGpsData.UTC_Hour = gpsRxBuffer[HOR_POS];
myGpsData.UTC_Minute = gpsRxBuffer[MIN_POS];
// Add milisecond to seconds - to be used in Asto calculation
if(gpsSecond != gpsRxBuffer[SEC_POS]){
gpsSecond = gpsRxBuffer[SEC_POS];
myGpsData.UTC_Second = (float)gpsSecond;
} else {
myGpsData.UTC_Second += 0.2f;//(HAL_GetTick() - miliSecond) * ALTITUDE_FACTOR; //Can use +=0.2f at 5 Hz to save some CPU cycles
//miliSecond = HAL_GetTick();
}
myGpsData.UTC_Second = gpsRxBuffer[SEC_POS];
myGpsData.Fix_Type = gpsRxBuffer[FIX_POS];
myGpsData.Satellites = gpsRxBuffer[SAT_POS];
myGpsData.Longitude = (float)(*(int32_t *)&gpsRxBuffer[LNG_POS]) * COORD_FACTOR;
myGpsData.Latitude = (float)(*(int32_t *)&gpsRxBuffer[LAT_POS]) * COORD_FACTOR;
myGpsData.Altitude = (float)(*(int32_t *)&gpsRxBuffer[MSL_POS]) * ALTITUDE_FACTOR;
}
}
}
// Reset GPS
void M9N_Reset() {
GPS_RST_Off;
HAL_Delay(100);
GPS_RST_On;
HAL_Delay(100);
}
void M9N_Start(void){
M9N_Reset();
// Start receiveing
HAL_UART_Receive_DMA(&huart3, (uint8_t *)gpsRxBuffer, RX_BUFFER_LEN);
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
}
Comments powered by CComment