一、GPS模块介绍

        本文章是基于SR1513M10型号GPS模块进行调试的,下图为该模块的成品图,该模块可以实现GPS定位,返回定位点的UTC时间,经纬度,海拔高度等信息。模块默认波特率9600,无校验。

二、使用方法

        该模块使用时只需连接4根线,G接电源负极,V接电源正极,T接串口发送,R接串口接收。连接好了无需配置,该模块会每隔1s向外发送数据,如下图所示:

三、数据解析以及经纬度转换

        由于项目中只需UTC时间,经纬度,海拔高度信息,所以只需析解$GNRMC/$GPRMC开头和$GNGGA/$GPGGA开头的数据。下图为GGA、RMC数据格式以及经纬度转换方法。

     

                     

四、程序设计

        下面是该模块的代码设计。   Data_Receive函数放在串口接收中断函数中即可,由于获取的UTC时间与北京时间相差8小时,所以获取的时间需要加8。该程序只是对GGA和RMC数据进行解析,同理可解析其他需要的数据。

#include "Module_GPS.h"


_SaveData_RMC Save_DataRMC;
_SaveData_GGA Save_DataGGA;

/*
 *==============================================================================
 *函数名称:Data_Receive
 *函数功能:串口数据接收
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
float GPS_JD=0;
float GPS_WD=0;
void Data_Receive (uint8_t Res)
{
	static uint16_t point1 = 0;
	static char USART_RX_BUF[USART_REC_LEN]; 
	if(Res == '$')
	{
		point1 = 0;	
	}
		

	USART_RX_BUF[point1++] = Res;

	if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C')			//确定是否收到"GPRMC/GNRMC"这一帧数据
	{
		if(Res == '\n')									   
		{
			memset(Save_DataRMC.GPS_Buffer, 0, GPS_Buffer_Length);      	//清空
			memcpy(Save_DataRMC.GPS_Buffer, USART_RX_BUF, point1); 		//保存数据
			Save_DataRMC.isGetData = true;
			point1 = 0;
			memset(USART_RX_BUF, 0, USART_REC_LEN);      			//清空				
		}	
				
	}
	
	if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'G' && USART_RX_BUF[5] == 'A')			//确定是否收到"GNGGA/GPGGA"这一帧数据
	{
		if(Res == '\n')									   
		{
			memset(Save_DataGGA.GPS_Buffer, 0, GPS_Buffer_Length);      	//清空
			memcpy(Save_DataGGA.GPS_Buffer, USART_RX_BUF, point1); 		//保存数据
			Save_DataGGA.isGetData = true;
			point1 = 0;
			memset(USART_RX_BUF, 0, USART_REC_LEN);      			//清空				
		}	
	}
	
	if(point1 >= USART_REC_LEN)
	{
		point1 = USART_REC_LEN;
	}	
}



/*
 *==============================================================================
 *函数名称:parseGpsBuffer_RMC
 *函数功能:GPRMC/GNRMC数据解析
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
void parseGpsBuffer_RMC()
{
	char *subString;
	char *subStringNext;
	char i = 0;
	if (Save_DataRMC.isGetData)
	{
		Save_DataRMC.isGetData = false;

		for (i = 0 ; i <= 9 ; i++)
		{
			if (i == 0)
			{
				if ((subString = strstr(Save_DataRMC.GPS_Buffer, ",")) == NULL)
					Save_DataRMC.isGetData = false;
			}
			else
			{
				subString++;
				if ((subStringNext = strstr(subString, ",")) != NULL)
				{
					char usefullBuffer[2]; 
					switch(i)
					{
						case 1:memcpy(Save_DataRMC.UTCTime, subString, subStringNext - subString);break;	//获取UTC时间
						case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break;		//定位状态
						case 3:memcpy(Save_DataRMC.latitude, subString, subStringNext - subString);break;	//获取纬度信息
						case 4:memcpy(Save_DataRMC.N_S, subString, subStringNext - subString);break;		//获取N/S
						case 5:memcpy(Save_DataRMC.longitude, subString, subStringNext - subString);break;	//获取经度信息
						case 6:memcpy(Save_DataRMC.E_W, subString, subStringNext - subString);break;		//获取E/W
						case 7:break;										//地面速率
						case 8:break;										//地面航向
						case 9:memcpy(Save_DataRMC.UTCDate, subString, subStringNext - subString);break;	//获取UTC日期
						default:break;
					}

					subString = subStringNext;
					Save_DataRMC.isParseData = true;
					if(usefullBuffer[0] == 'A')//有效定位
						Save_DataRMC.isUsefull = true;
					else if(usefullBuffer[0] == 'V')//无效定位
						Save_DataRMC.isUsefull = false;

				}
				else
				{
					Save_DataRMC.isGetData = false;
				}
			}
		}
	}
}

/*
 *==============================================================================
 *函数名称:parseGpsBuffer_GGA
 *函数功能:GNGGA/GPGGA数据解析
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
void parseGpsBuffer_GGA()
{
	char *subString;
	char *subStringNext;
	char i = 0;
	if (Save_DataGGA.isGetData)
	{
		Save_DataGGA.isGetData = false;

		for (i = 0 ; i <= 9 ; i++)
		{
			if (i == 0)
			{
				if ((subString = strstr(Save_DataGGA.GPS_Buffer, ",")) == NULL)
					Save_DataGGA.isGetData = false;
			}
			else
			{
				subString++;
				if ((subStringNext = strstr(subString, ",")) != NULL)
				{
					char usefullBuffer[2]; 
					switch(i)
					{
						case 1:memcpy(Save_DataGGA.UTCTime, subString, subStringNext - subString);break;	//获取UTC时间
						case 2:memcpy(Save_DataGGA.latitude, subString, subStringNext - subString);break;	//获取纬度信息
						case 3:memcpy(Save_DataGGA.N_S, subString, subStringNext - subString);break;		//获取N/S
						case 4:memcpy(Save_DataGGA.longitude, subString, subStringNext - subString);break;	//获取经度信息
						case 5:memcpy(Save_DataGGA.E_W, subString, subStringNext - subString);break;		//获取E/W
						case 6:memcpy(usefullBuffer, subString, subStringNext - subString);break;		//定位状态:1=GPS 定位有效, 0 = 无效									//定位状态
						case 7:break;										//参与定位的卫星数量
						case 8:break;										//水平精度因子
						case 9:memcpy(Save_DataGGA.altitude, subString, subStringNext - subString);break;	//海拔高度
						default:break;
					}

					subString = subStringNext;
					Save_DataGGA.isParseData = true;
					if(usefullBuffer[0] == '1')//有效定位
						Save_DataGGA.isUsefull = true;
					else if(usefullBuffer[0] == '0')//无效定位
						Save_DataGGA.isUsefull = false;

				}
				else
				{
					Save_DataGGA.isGetData = false;
				}
			}
		}
	}
}


/*
 *==============================================================================
 *函数名称:Data_Transfor
 *函数功能:数据转换,将经纬度字符型数据转换成float型数据
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
void Data_Transfor (void)
{
	float latitude = 0;   // 存储纬度信息
	uint16_t temp1 = 0;   // 临时变量1,存储整数
	float longitude = 0;   // 存储经度信息
	uint16_t temp2 = 0;   // 临时变量2,存储整数
	
	latitude = strtod(Save_DataGGA.latitude,NULL);   // 字符串转换成浮点数
	longitude = strtod(Save_DataGGA.longitude,NULL);   // 字符串转换成浮点数
	
	temp1 = latitude/100;
	latitude = latitude - (float)temp1 * 100;
	latitude = (float)temp1 + latitude / 60;
	
	temp2 = longitude/100;
	longitude = longitude - (float)temp2 * 100;
	longitude = (float)temp2 + longitude / 60;
	
	GPS_WD = latitude;
	GPS_JD = longitude;
}

/*
 *==============================================================================
 *函数名称:Data_fill_xgb
 *函数功能:数据赋值,将经纬度字符型数据转换成协议所需数据类型
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
Time_Def GPSTime;
void Data_fill_xgb(void)
{
	if(Save_DataRMC.isUsefull == true)//RMC有效定位
	{
		sscanf(Save_DataRMC.UTCDate, "%2hhu%2hhu%2hhu", &GPSTime.day, &GPSTime.month, &GPSTime.year);
		sscanf(Save_DataRMC.UTCTime, "%2hhu%2hhu%2hhu", &GPSTime.hour, &GPSTime.minute, &GPSTime.second);
		GPSTime.hour = (GPSTime.hour+8)%24;
	}
}


void Pro_GPS(void)
{
	parseGpsBuffer_RMC();
	parseGpsBuffer_GGA();
	Data_Transfor();
	Data_fill_xgb();
}
#ifndef _MODULE_GPS_H
#define _MODULE_GPS_H
#include "main.h"

//定义数组长度
#define GPS_Buffer_Length 80
#define UTCTime_Length 11
#define latitude_Length 11
#define N_S_Length 2
#define longitude_Length 12
#define E_W_Length 2 

typedef struct SaveData 
{
	char GPS_Buffer[GPS_Buffer_Length];
	char isGetData;		//是否获取到GPS数据
	char isParseData;	//是否解析完成
	char UTCTime[UTCTime_Length];		//UTC时间
	char latitude[latitude_Length];		//纬度
	char N_S[N_S_Length];		//N/S
	char longitude[longitude_Length];		//经度
	char E_W[E_W_Length];		//E/W
	char UTCDate[UTCTime_Length];		//UTC日期
	char isUsefull;		//定位信息是否有效
} _SaveData_RMC;

typedef struct SaveData_GGA 
{
	char GPS_Buffer[GPS_Buffer_Length];
	char isGetData;				//是否获取到GPS数据
	char isParseData;			//是否解析完成
	char UTCTime[UTCTime_Length];		//UTC时间
	char latitude[latitude_Length];		//纬度
	char N_S[N_S_Length];			//N/S
	char longitude[longitude_Length];	//经度
	char E_W[E_W_Length];			//E/W
	char isUsefull;				//定位信息是否有效
	char satellites;        		//卫星数量
        char hdop;				//水平精度因子
	char altitude[10];			//海拔高度(米)
	char geoid_height; 			//大地水准面高度 (米)	
} _SaveData_GGA;


void Data_Receive (uint8_t Res);
void Pro_GPS(void);
#endif



Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐