STM32 UART Library for NEO-M9N GNSS module

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