GPS数据处理
(Global Positioning System,GPS)全球定位系统是一种以空中卫星为基础的高精度无线电导航的定位系统,它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间信息。GPS自问世以来,就以其高精度、全天候、全球覆盖、方便灵活吸引了众多用户。GPS不仅是汽车的守护神,同时也是物流行业管理的智多星。随着物流业的快速发展,GPS有着举足轻重的作用,成为继汽车市场后的第二大主要消费群体。
目前常用的GPS模块接收到卫星信号后使用串口协议以字符串的形式输出,前面学习过字符串的基本使用,本章节就学习解析GPS卫星数据,提取GPS信息里的有效数据。
GPS返回的数据如下(采用中科微GPS模块):
$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A$GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14$GNZDA,114955.000,06,11,2017,00,00*47$GPTXT,01,01,01,ANTENNA OK*35
其中每个字段的含义如下:
序号 命令 说明 最大帧长1 $GNGGA GPS/北斗定位信息 722 $GNGSA 当前卫星信息 653 $GPGSV 可见 GPS 卫星信息 2104 $BDGSV 可见北斗卫星信息 2105 $GNRMC 推荐定位信息 706 $GNVTG 地面速度信息 347 $GNGLL 大地坐标信息 --8 $GNZDA 当前时间(UTC1)信息 --
1、$GNGGA(GPS 定位信息)
$GNGGA 语句的基本格式如下(其中 M 指单位 M, hh 指校验和, CR 和 LF 代表回车换行,下同):$GNGGA,(1),(2),(3),(4),(5),(6),(7),(8),(9),M,(10),M,(11),(12)*hh(CR)(LF)(1) UTC 时间,格式为 hhmmss.ss;(2) 纬度,格式为 ddmm.mmmmm(度分格式);(3) 纬度半球, N 或 S(北纬或南纬);(4) 经度,格式为 dddmm.mmmmm(度分格式);(5) 经度半球, E 或 W(东经或西经);(6) GPS 状态, 0=未定位, 1=非差分定位, 2=差分定位;(7) 正在使用的用于定位的卫星数量(00~12)(8) HDOP 水平精确度因子(0.5~99.9)(9) 海拔高度(-9999.9 到 9999.9 米)(10) 大地水准面高度(-9999.9 到 9999.9 米)(11) 差分时间(从最近一次接收到差分信号开始的秒数,非差分定位,此项为空)(12) 差分参考基站标号(0000 到 1023, 首位 0 也将传送,非差分定位,此项为空)举例如下:$GNGGA,095528.000,2318.1133,N,11319.7210,E,1,06,3.7,55.1,M,-5.4,M,,0000*69
2、$GNGSA(当前卫星信息)
$GNGSA 语句的基本格式如下:$GNGSA,(1),(2),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(4),(5),(6)*hh(CR)(LF)(1) 模式, M = 手动, A = 自动。(2) 定位类型, 1=未定位, 2=2D 定位, 3=3D 定位。(3) 正在用于定位的卫星号(01~32)(4) PDOP 综合位置精度因子(0.5-99.9)ALIENTEK(5) HDOP 水平精度因子 1(0.5-99.9)(6) VDOP 垂直精度因子(0.5-99.9)举例如下:$GNGSA,A,3,14,22,24,12,,,,,,,,,4.2,3.7,2.1*2D$GNGSA,A,3,209,214,,,,,,,,,,,4.2,3.7,2.1*21注 1:精度因子值越小,则准确度越高。
3、$GPGSV(可见卫星数)
$GPGSV 语句的基本格式如下:$GPGSV, (1),(2),(3),(4),(5),(6),(7),...,(4),(5),(6),(7)*hh(CR)(LF)(1) GSV 语句总数。(2) 本句 GSV 的编号。(3) 可见卫星的总数(00~12,前面的 0 也将被传输)。(4) 卫星编号(01~32,前面的 0 也将被传输)。(5) 卫星仰角(00~90 度,前面的 0 也将被传输)。(6) 卫星方位角(000~359 度,前面的 0 也将被传输)(7) 信噪比(00~99dB,没有跟踪到卫星时为空)。注:每条 GSV 语句最多包括四颗卫星的信息,其他卫星的信息将在下一条$GPGSV 语句中输出。举例如下:$GPGSV,3,1,11,18,73,129,19,10,71,335,40,22,63,323,41,25,49,127,06*78$GPGSV,3,2,11,14,41,325,46,12,36,072,34,31,32,238,22,21,23,194,08*76$GPGSV,3,3,11,24,21,039,40,20,08,139,07,15,08,086,03*45
4、$BDGSV(可见卫星数)
$BDGSV 语句的基本格式如下:$BDGSV, (1),(2),(3),(4),(5),(6),(7),...,(4),(5),(6),(7)*hh(CR)(LF)(1) GSV 语句总数。(2) 本句 GSV 的编号。(3) 可见卫星的总数(00~12,前面的 0 也将被传输)。(4) 卫星编号(01~32,前面的 0 也将被传输)。(5) 卫星仰角(00~90 度,前面的 0 也将被传输)。(6) 卫星方位角(000~359 度,前面的 0 也将被传输)(7) 信噪比(00~99dB,没有跟踪到卫星时为空)。注:每条 GSV 语句最多包括四颗卫星的信息,其他卫星的信息将在下一条$BDGSV 语句中输出。举例如下:$BDGSV,1,1,02,209,64,354,40,214,05,318,40*69
5、$GNRMC(推荐定位信息)
$GNRMC 语句的基本格式如下:$GNRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)(1) UTC 时间, hhmmss(时分秒)(2) 定位状态, A=有效定位, V=无效定位(3) 纬度 ddmm.mmmmm(度分)(4) 纬度半球 N(北半球)或 S(南半球)ALIENTEK(5) 经度 dddmm.mmmmm(度分)(6) 经度半球 E(东经)或 W(西经)(7) 地面速率(000.0~999.9 节)(8) 地面航向(000.0~359.9 度,以真北方为参考基准)(9) UTC 日期, ddmmyy(日月年)(10) 磁偏角(000.0~180.0 度,前导位数不足则补 0)(11) 磁偏角方向, E(东)或 W(西)(12) 模式指示(A=自主定位, D=差分, E=估算, N=数据无效)举例如下:$GNRMC,095554.000,A,2318.1327,N,11319.7252,E,000.0,005.7,081215,,,A*73
6、$GNVTG(地面速度信息)
$GNVTG 语句的基本格式如下:$GNVTG,(1),T,(2),M,(3),N,(4),K,(5)*hh(CR)(LF)(1) 以真北为参考基准的地面航向(000~359 度,前面的 0 也将被传输)(2) 以磁北为参考基准的地面航向(000~359 度,前面的 0 也将被传输)(3) 地面速率(000.0~999.9 节,前面的 0 也将被传输)(4) 地面速率(0000.0~1851.8 公里/小时,前面的 0 也将被传输)(5) 模式指示(A=自主定位, D=差分, E=估算, N=数据无效)举例如下:$GNVTG,005.7,T,,M,000.0,N,000.0,K,A*11
7、$GNGLL(定位地理信息)
$GNGLL 语句的基本格式如下:$GNGLL,(1),(2),(3),(4),(5),(6),(7)*hh(CR)(LF)(1) 纬度 ddmm.mmmmm(度分)(2) 纬度半球 N(北半球)或 S(南半球)(3) 经度 dddmm.mmmmm(度分)(4) 经度半球 E(东经)或 W(西经)(5) UTC 时间:hhmmss(时分秒)(6) 定位状态, A=有效定位, V=无效定位(7) 模式指示(A=自主定位, D=差分, E=估算, N=数据无效)举例如下:$GNGLL,2318.1330,N,11319.7250,E,095556.000,A,A*4F
8、$GNZDA(当前时间信息)
$GNZDA 语句的基本格式如下:$GNZDA,(1),(2),(3),(4), (5), (6)*hh(CR)(LF)(1) UTC 时间:hhmmss(时分秒)(2) 日(3) 月(4) 年(5) 本地区域小时(NEO-6M 未用到,为 00)(6) 本地区域分钟(NEO-6M 未用到,为 00)举例如下:$GNZDA,095555.000,08,12,2015,00,00*4C
C语言代码解析GPS数据示例:
#include <stdio.h>#include <string.h>typedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;const u8 GPS_Info_1[]="\$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F\$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D\$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37\$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A\$GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B\$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C\$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F\$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62\$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D\$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14\$GNZDA,114955.000,06,11,2017,00,00*47\$GPTXT,01,01,01,ANTENNA OK*35";const u8 GPS_Info_2[]="\$GPGSV,3,2,10,20,16,138,,21,27,204,,24,39,040,26,25,35,145,22*7B\$GPGSV,3,3,10,31,13,226,20,32,33,300,23*7F\$BDGSV,2,1,08,03,,,31,04,,,31,06,65,033,24,10,,,31*54\$BDGSV,2,2,08,11,,,30,12,,,30,13,,,29,15,,,31*6C\$GNRMC,144513.000,A,2856.3560,N,11524.5587,E,1.48,292.74,230817,,,A*7B\$GNVTG,292.74,T,,M,1.48,N,2.73,K,A*22\$GNZDA,144513.000,23,08,2017,00,00*43\$GPTXT,01,01,01,ANTENNA OK*35\$GNGGA,144514.000,2856.3563,N,11524.5596,E,1,06,4.0,-13.0,M,0.0,M,,*68\$GNGLL,2856.3563,N,11524.5596,E,144514.000,A,A*40\$GPGSA,A,3,15,24,12,18,25,,,,,,,,6.7,4.0,5.3*3E\$BDGSA,A,3,06,,,,,,,,,,,,6.7,4.0,5.3*26\";#pragma pack(1) /* 必须在结构体定义之前使用,这是为了让结构体中各成员按1字节对齐 *///美国GPS卫星信息typedef struct{ u8 num; //卫星编号 u8 eledeg; //卫星仰角 u16 azideg; //卫星方位角 u8 sn; //信噪比 }nmea_slmsg;//北斗卫星信息typedef struct{ u8 beidou_num; //卫星编号 u8 beidou_eledeg; //卫星仰角 u16 beidou_azideg; //卫星方位角 u8 beidou_sn; //信噪比 }beidou_nmea_slmsg;//UTC时间信息typedef struct{ u16 year; //年份 u8 month; //月份 u8 date; //日期 u8 hour; //小时 u8 min; //分钟 u8 sec; //秒钟}nmea_utc_time;//GPS协议解析后数据存放结构体 typedef struct{ u8 svnum; //可见GPS卫星数 u8 beidou_svnum; //可见GPS卫星数 nmea_slmsg slmsg[12]; //最多12颗GPS卫星 beidou_nmea_slmsg beidou_slmsg[12]; //暂且算最多12颗北斗卫星 nmea_utc_time utc; //UTC时间 u32 latitude; //纬度 分扩大100000倍,实际要除以100000 u8 nshemi; //北纬/南纬,N:北纬;S:南纬 u32 longitude; //经度 分扩大100000倍,实际要除以100000 u8 ewhemi; //东经/西经,E:东经;W:西经 u8 gpssta; //GPS状态:0,未定位;1,非差分定位;2,差分定位;6,正在估算. u8 posslnum; //用于定位的GPS卫星数,0~12. u8 possl[12]; //用于定位的卫星编号 u8 fixmode; //定位类型:1,没有定位;2,2D定位;3,3D定位 u16 pdop; //位置精度因子 0~500,对应实际值0~50.0 u16 hdop; //水平精度因子 0~500,对应实际值0~50.0 u16 vdop; //垂直精度因子 0~500,对应实际值0~50.0 int altitude; //海拔高度,放大了10倍,实际除以10.单位:0.1m u16 speed; //地面速率,放大了1000倍,实际除以10.单位:0.001公里/小时 }GPS_Msg;u8 GPS_GetCommaOffset(u8 *buf,u8 cnt);void GPS_MsgShow(void);u8 GPS_GetCommaOffset(u8 *buf,u8 cnt);void GPS_GPGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);void GPS_GNVTG_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);void GPS_GNRMC_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);void GPS_GNGSA_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);void GPS_BDGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);void GPS_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf);GPS_Msg GPS_DecodeInfo; //存放GPS解码信息int main(){ GPS_InfoGet(&GPS_DecodeInfo,GPS_Info_1); GPS_MsgShow(); return 0;}const u8*fixmode_tbl[4]={"失败","失败"," 2D "," 3D "}; //fix mode字符串u8 dtbuf[50]; //打印缓存器/*函数功能:显示GPS定位信息*/void GPS_MsgShow(void){ float tp; tp=GPS_DecodeInfo.longitude; sprintf((char *)dtbuf,"经度:%.5f %1c",tp/=100000,GPS_DecodeInfo.ewhemi); //得到经度字符串 printf("%s\r\n",dtbuf); tp=GPS_DecodeInfo.latitude; sprintf((char *)dtbuf,"纬度:%.5f %1c",tp/=100000,GPS_DecodeInfo.nshemi); //得到纬度字符串 printf("%s\r\n",dtbuf); tp=GPS_DecodeInfo.altitude; sprintf((char *)dtbuf,"高度:%.1fm",tp/=10); //得到高度字符串 printf("%s\r\n",dtbuf); tp=GPS_DecodeInfo.speed; sprintf((char *)dtbuf,"速度:%.3fkm/h",tp/=1000); //得到速度字符串 printf("%s\r\n",dtbuf); if(GPS_DecodeInfo.fixmode<=3) //定位状态 { sprintf((char *)dtbuf,"定位模式:%s",fixmode_tbl[GPS_DecodeInfo.fixmode]); printf("%s\r\n",dtbuf); } sprintf((char *)dtbuf,"GPS+BD 定位的GPS卫星数:%02d",GPS_DecodeInfo.posslnum); //用于定位的GPS卫星数 printf("%s\r\n",dtbuf); sprintf((char *)dtbuf,"GPS 可见GPS卫星数:%02d",GPS_DecodeInfo.svnum%100); //可见GPS卫星数 printf("%s\r\n",dtbuf); sprintf((char *)dtbuf,"BD 可见北斗卫星数:%02d",GPS_DecodeInfo.beidou_svnum%100); //可见北斗卫星数 printf("%s\r\n",dtbuf); sprintf((char *)dtbuf,"UTC日期:%04d/%02d/%02d ",GPS_DecodeInfo.utc.year,GPS_DecodeInfo.utc.month,GPS_DecodeInfo.utc.date); //显示UTC日期 printf("%s\r\n",dtbuf); sprintf((char *)dtbuf,"显示UTC时间:%02d:%02d:%02d ",GPS_DecodeInfo.utc.hour,GPS_DecodeInfo.utc.min,GPS_DecodeInfo.utc.sec); //显示UTC时间 printf("%s\r\n",dtbuf);}/*函数功能:从buf里面得到第cnt个逗号所在的位置返 回 值:0~254,代表逗号所在位置的偏移.255,代表不存在第cnt个逗号*/u8 GPS_GetCommaOffset(u8 *buf,u8 cnt){ u8 *p=buf; while(cnt) { if(*buf=='*'||*buf<' '||*buf>'z')return 255;//遇到'*'或者非法字符,则不存在第cx个逗号 if(*buf==',')cnt--; buf++; } return buf-p; //计算偏移量}/*函数功能:m^n函数返 回 值:m^n次方.*/u32 GPS_GetPow(u8 m,u8 n){ u32 tmp=1; while(n--)tmp*=m; return tmp;}/*函数功能:str转换为数字,以','或者'*'结束函数参数:buf:数字存储区 dx:小数点位数,返回给调用函数返 回 值:转换后的整数数值*/int GPS_StrtoNum(u8 *buf,u8*dx){ u8 *p=buf; u32 ires=0,fres=0; u8 ilen=0,flen=0,i; u8 mask=0; int res; while(1) //得到整数和小数的长度 { if(*p=='-'){ mask|=0X02; p++; }//是负数 if(*p==','||(*p=='*'))break;//遇到结束了 if(*p=='.'){ mask|=0X01; p++; }//遇到小数点了 else if(*p>'9'||(*p<'0')) //有非法字符 { ilen=0; flen=0; break; } if(mask&0X01)flen++; else ilen++; p++; } if(mask&0X02)buf++; //去掉负号 for(i=0; i<ilen; i++) //得到整数部分数据 { ires+=GPS_GetPow(10,ilen-1-i)*(buf[i]-'0'); } if(flen>5)flen=5; //最多取5位小数 *dx=flen; //小数点位数 for(i=0; i<flen; i++) //得到小数部分数据 { fres+=GPS_GetPow(10,flen-1-i)*(buf[ilen+1+i]-'0'); } res=ires*GPS_GetPow(10,flen)+fres; if(mask&0X02)res=-res; return res;}/*函数功能:分析GPGSV信息函数参数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_GPGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p,*p1,dx; u8 len,i,j,slx=0; u8 posx; p=buf; p1=(u8*)strstr((const char *)p,"$GPGSV"); if(!p1)return; //没有查找成功 len=p1[7]-'0'; //得到GPGSV的条数 posx=GPS_GetCommaOffset(p1,3); //得到可见卫星总数 if(posx!=0XFF)GPS_DecodeInfo->svnum=GPS_StrtoNum(p1+posx,&dx); for(i=0; i<len; i++) { p1=(u8*)strstr((const char *)p,"$GPGSV"); if(!p1)return; //没有查找成功 for(j=0; j<4; j++) { posx=GPS_GetCommaOffset(p1,4+j*4); if(posx!=0XFF)GPS_DecodeInfo->slmsg[slx].num=GPS_StrtoNum(p1+posx,&dx); //得到卫星编号 else break; posx=GPS_GetCommaOffset(p1,5+j*4); if(posx!=0XFF)GPS_DecodeInfo->slmsg[slx].eledeg=GPS_StrtoNum(p1+posx,&dx);//得到卫星仰角 else break; posx=GPS_GetCommaOffset(p1,6+j*4); if(posx!=0XFF)GPS_DecodeInfo->slmsg[slx].azideg=GPS_StrtoNum(p1+posx,&dx);//得到卫星方位角 else break; posx=GPS_GetCommaOffset(p1,7+j*4); if(posx!=0XFF)GPS_DecodeInfo->slmsg[slx].sn=GPS_StrtoNum(p1+posx,&dx); //得到卫星信噪比 else break; slx++; } p=p1+1;//切换到下一个GPGSV信息 }}/*函数功能:分析BDGSV信息函数参数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_BDGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p,*p1,dx; u8 len,i,j,slx=0; u8 posx; p=buf; p1=(u8*)strstr((const char *)p,"$BDGSV"); if(!p1)return; //没有查找成功 len=p1[7]-'0'; //得到BDGSV的条数 posx=GPS_GetCommaOffset(p1,3); //得到可见北斗卫星总数 if(posx!=0XFF)GPS_DecodeInfo->beidou_svnum=GPS_StrtoNum(p1+posx,&dx); for(i=0; i<len; i++) { p1=(u8*)strstr((const char *)p,"$BDGSV"); if(!p1)return; //没有查找成功 for(j=0; j<4; j++) { posx=GPS_GetCommaOffset(p1,4+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_num=GPS_StrtoNum(p1+posx,&dx); //得到卫星编号 else break; posx=GPS_GetCommaOffset(p1,5+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_eledeg=GPS_StrtoNum(p1+posx,&dx);//得到卫星仰角 else break; posx=GPS_GetCommaOffset(p1,6+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_azideg=GPS_StrtoNum(p1+posx,&dx);//得到卫星方位角 else break; posx=GPS_GetCommaOffset(p1,7+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_sn=GPS_StrtoNum(p1+posx,&dx); //得到卫星信噪比 else break; slx++; } p=p1+1;//切换到下一个BDGSV信息 }}/*函数功能:分析GNGGA信息函数参数: GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_GNGGA_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p1,dx; u8 posx; p1=(u8*)strstr((const char *)buf,"$GNGGA"); if(!p1)return; //没有查找成功 posx=GPS_GetCommaOffset(p1,6); //得到GPS状态 if(posx!=0XFF)GPS_DecodeInfo->gpssta=GPS_StrtoNum(p1+posx,&dx); posx=GPS_GetCommaOffset(p1,7); //得到用于定位的卫星数 if(posx!=0XFF)GPS_DecodeInfo->posslnum=GPS_StrtoNum(p1+posx,&dx); posx=GPS_GetCommaOffset(p1,9); //得到海拔高度 (posx!=0XFF)GPS_DecodeInfo->altitude=GPS_StrtoNum(p1+posx,&dx);}/*函数功能:分析GNGSA信息参 数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_GNGSA_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p1,dx; u8 posx; u8 i; p1=(u8*)strstr((const char *)buf,"$GNGSA"); if(!p1)return; //没有查找成功 posx=GPS_GetCommaOffset(p1,2); //得到定位类型 if(posx!=0XFF)GPS_DecodeInfo->fixmode=GPS_StrtoNum(p1+posx,&dx); for(i=0; i<12; i++) //得到定位卫星编号 { posx=GPS_GetCommaOffset(p1,3+i); if(posx!=0XFF)GPS_DecodeInfo->possl[i]=GPS_StrtoNum(p1+posx,&dx); else break; } posx=GPS_GetCommaOffset(p1,15); //得到PDOP位置精度因子 if(posx!=0XFF)GPS_DecodeInfo->pdop=GPS_StrtoNum(p1+posx,&dx); posx=GPS_GetCommaOffset(p1,16); //得到HDOP位置精度因子 if(posx!=0XFF)GPS_DecodeInfo->hdop=GPS_StrtoNum(p1+posx,&dx); posx=GPS_GetCommaOffset(p1,17); //得到VDOP位置精度因子 if(posx!=0XFF)GPS_DecodeInfo->vdop=GPS_StrtoNum(p1+posx,&dx);}/*函数功能:分析GNRMC信息函数参数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_GNRMC_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p1,dx; u8 posx; u32 temp; float rs; p1=(u8*)strstr((const char *)buf,"$GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GPRMC. if(!p1)return; //没有查找成功 posx=GPS_GetCommaOffset(p1,1); //得到UTC时间 if(posx!=0XFF) { temp=GPS_StrtoNum(p1+posx,&dx)/GPS_GetPow(10,dx); //得到UTC时间,去掉ms GPS_DecodeInfo->utc.hour=temp/10000; GPS_DecodeInfo->utc.min=(temp/100)%100; GPS_DecodeInfo->utc.sec=temp%100; } posx=GPS_GetCommaOffset(p1,3); //得到纬度 if(posx!=0XFF) { temp=GPS_StrtoNum(p1+posx,&dx); GPS_DecodeInfo->latitude=temp/GPS_GetPow(10,dx+2); //得到° rs=(float)(temp%GPS_GetPow(10,dx+2)); //得到' GPS_DecodeInfo->latitude=(u32)(GPS_DecodeInfo->latitude*GPS_GetPow(10,5)+(rs*GPS_GetPow(10,5-dx))/60);//转换为° } posx=GPS_GetCommaOffset(p1,4); //南纬还是北纬 if(posx!=0XFF)GPS_DecodeInfo->nshemi=*(p1+posx); posx=GPS_GetCommaOffset(p1,5); //得到经度 if(posx!=0XFF) { temp=GPS_StrtoNum(p1+posx,&dx); GPS_DecodeInfo->longitude=temp/GPS_GetPow(10,dx+2); //得到° rs=(float)(temp%GPS_GetPow(10,dx+2)); //得到' GPS_DecodeInfo->longitude=(u32)(GPS_DecodeInfo->longitude*GPS_GetPow(10,5)+(rs*GPS_GetPow(10,5-dx))/60);//转换为° } posx=GPS_GetCommaOffset(p1,6); //东经还是西经 if(posx!=0XFF)GPS_DecodeInfo->ewhemi=*(p1+posx); posx=GPS_GetCommaOffset(p1,9); //得到UTC日期 if(posx!=0XFF) { temp=GPS_StrtoNum(p1+posx,&dx); //得到UTC日期 GPS_DecodeInfo->utc.date=temp/10000; GPS_DecodeInfo->utc.month=(temp/100)%100; GPS_DecodeInfo->utc.year=2000+temp%100; }}/*函数功能:分析GNVTG信息函数参数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_GNVTG_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ u8 *p1,dx; u8 posx; p1=(u8*)strstr((const char *)buf,"$GNVTG"); if(!p1)return; //没有查找成功 posx=GPS_GetCommaOffset(p1,7); //得到地面速率 if(posx!=0XFF) { GPS_DecodeInfo->speed=GPS_StrtoNum(p1+posx,&dx); if(dx<3)GPS_DecodeInfo->speed*=GPS_GetPow(10,3-dx); //确保扩大1000倍 }}/*函数功能:提取GPS信息函数参数:GPS_DecodeInfo:nmea信息结构体 buf:接收到的GPS数据缓冲区首地址*/void GPS_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf){ GPS_GPGSV_InfoGet(GPS_DecodeInfo,buf); //GPGSV解析-OK GPS_BDGSV_InfoGet(GPS_DecodeInfo,buf); //BDGSV解析-OK GPS_GNGGA_InfoGet(GPS_DecodeInfo,buf); //GNGGA解析-OK GPS_GNGSA_InfoGet(GPS_DecodeInfo,buf); //GPNSA解析-ON GPS_GNRMC_InfoGet(GPS_DecodeInfo,buf); //GPNMC解析-OK GPS_GNVTG_InfoGet(GPS_DecodeInfo,buf); //GPNTG解析-OK}
-----------------------------------
字符串运用案例_GPS数据解析
https://blog.51cto.com/u_15067237/2901989
原链接
字符串运用案例_GPS数据解析https: // blog.51cto.com/u_15067237/2901989
原始数据转度分秒
// 对原始gps数据进行转换为度分秒
// char buff[10] = {0};
// degree_minute_to_degree("2813.55525", buff, 1);
// degree_minute_to_degree("11256.92563", buff, 2);
//
void degree_minute_to_degree(char *data, char *out, int type)
{
char degree_result_char[11] = {0};
char degree_temp_char[4] = {0};
char minute_temp_char[9] = {0};
double degree_result_float = 0.0;
double degree_temp_flaot = 0.0;
double minute_temp_float = 0.0;
int num = 0;
if (1 == type) // 纬度 /
{
num = 2;
}
else if (2 == type)
{
num = 3;
}
else
{
;
}
strncpy(degree_temp_char, data, num);
strcpy(minute_temp_char, data + num);
degree_temp_flaot = atof(degree_temp_char);
printf("degree_temp_flaot %s", degree_temp_flaot);
minute_temp_float = atof(minute_temp_char) / 60;
printf("minute_temp_float %s", minute_temp_float);
degree_result_float = degree_temp_flaot + minute_temp_float;
printf("degree_result_float %s", degree_result_float);
sprintf(degree_result_char, "%.6f", degree_result_float);
strcpy(out, degree_result_char);
}
工具
经纬度换算器
https://www.sioe.cn/xinqing/jingweidu.php
经纬度gps坐标查询
https://adminun.com/gpsjwd
地图坐标系转换
https://tool.lu/coordinate/