《手把手教学:单片机+GPS模块实战 - 解析经纬度、海拔、时间全攻略(附代码)》
本文介绍了SR1513M10型号GPS模块的使用方法、数据解析及程序设计。该模块通过4线连接(电源正负极、串口收发),默认波特率9600,每秒自动发送定位数据。重点解析了$GNRMC/$GPRMC和$GNGGA/$GPGGA格式数据,获取UTC时间(需+8小时转换为北京时间)、经纬度(需进行度分转换)和海拔高度等信息。文中提供了完整的C语言代码实现,包括串口数据接收、RMC/GGA数据解析、经纬度
·
一、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
更多推荐



所有评论(0)