目录

1.GPS字段讲解

a.$GNGGA(重点)(时间,位置,定位模式等)(最全)

b.$GNGLL(重点)(时间,位置,定位模式)

c.$GPGSA(定位模式,卫星编号,精度因子)

d.$BDGSA(精度因子,使用卫星PRN号码)

e.$GPGSV(卫星的数量、卫星PRN号码、仰角、方位角以及信噪比)

f.$BDGSV(卫星编号、仰角、方位角和信号强度等信息)

g.$GNRMC(时间,经纬度,日期,定位模式)

h.$GNVTG(航向和地速信息)

i.$GNZDA(UTC时间)

j.$GPTXT(天线状态)

2.GPS准备

3.GPS代码编写

3.1.基础知识:

3.1.1串口驱动


GPS主要是要用起来,一般市面上也就是卖模块,我感觉一般也不会有人会买芯片集成到板子上吧?..所以这篇博客主要是讲解,市面上可以买到的GPS模块串口所打印的数据块的各个数据段什么意思,另外给出解析的方案。

1.GPS字段讲解

本文主要是以市面上能买到的最新款的GPS作为解析的依据,市面上能买的GPS目前最新的串口打印的格式主要是如下:(不太清楚后面会不会改,但应该基本都是这个数据段了)

a.$GNGGA,085126.000,2311.77819,N,11323.44968,E,1,15,1.5,36.7,M,0.0,M,,*4C
b.$GNGLL,2311.77819,N,11323.44968,E,085126.000,A,A*4B
c.$GPGSA,A,3,01,04,08,09,21,199,,,,,,,2.3,1.5,1.8*08
d.$BDGSA,A,3,06,07,09,10,16,29,30,38,39,,,,2.3,1.5,1.8*28
e.$GPGSV,3,1,09,01,21,176,41,04,38,212,41,07,36,324,,08,72,355,29*7C
e.$GPGSV,3,2,09,09,38,259,29,16,,,24,21,42,155,43,32,,,17*73
e.$GPGSV,3,3,09,199,59,148,30*73
f.$BDGSV,3,1,12,02,,,34,03,,,32,06,71,192,35,07,62,315,32*67
f.$BDGSV,3,2,12,09,78,250,36,10,56,298,35,16,68,183,43,29,27,210,33*60
f.$BDGSV,3,3,12,30,80,160,42,38,12,165,33,39,58,178,40,59,,,37*5E
g.$GNRMC,085126.000,A,2311.77819,N,11323.44968,E,0.00,0.00,060123,,,A*7A
h.$GNVTG,0.00,T,,M,0.00,N,0.00,K,A*23
i.$GNZDA,085126.000,06,01,2023,00,00*44
j.$GPTXT,01,01,01,ANTENNA OK*35

以下为各个字段的一些解析,如果实在不想看,直接跳到写代码的部分:

a.$GNGGA(重点)(时间,位置,定位模式等)(最全)

$GNGGA,085126.000,2311.77819,N,11323.44968,E,1,15,1.5,36.7,M,0.0,M,,*4C

这是一个$GNGGA字段,它包含了GPS定位信息。各个字段的含义如下:

  • $GNGGA:定位信息
  • 085126.000:UTC时间,格式为时分秒(hhmmss.sss)
  • 2311.77819,N:纬度,格式为ddmm.mmmmm,表示23度11.77819分北纬
  • 11323.44968,E:经度,格式为dddmm.mmmmm,表示113度23.44968分东经
  • 1:定位质量指示,1代表定位,0代表未定位
  • 15:使用卫星数量,范围为0-12和17-32
  • 1.5:水平精度因子,表示位置精度,值越小精度越高
  • 36.7,M:海拔高度,单位为米
  • 0.0,M:大地水准面高度,单位为米
  • 空字段:时间间隔
  • *4C:校验和,用于验证数据的完整性

这些信息可以用于确定GPS接收器的位置和时间。例如,该数据表示的位置为东经113度23.44968分,北纬23度11.77819分,海拔高度为36.7米,定位精度为1.5米,使用了15颗卫星进行定位。

b.$GNGLL(重点)(时间,位置,定位模式)

GNGLL,2311.77819,N,11323.44968,E,085126.000,A,A*4B

这是一个$GNGLL字段,它包含了GPS定位信息。各个字段的含义如下:

  • $GNGLL:定位信息
  • 2311.77819,N:纬度,格式为ddmm.mmmmm,表示23度11.77819分北纬
  • 11323.44968,E:经度,格式为dddmm.mmmmm,表示113度23.44968分东经
  • 085126.000:UTC时间,格式为时分秒(hhmmss.sss)
  • A:定位质量指示,A代表定位,V代表未定位
  • A:定位模式指示,A代表自主定位,D代表差分定位
  • *4B:校验和,用于验证数据的完整性

这些信息可以用于确定GPS接收器的位置和时间。例如,该数据表示的位置为东经113度23.44968分,北纬23度11.77819分,时间为08:51:26,定位模式为自主定位。

c.$GPGSA(定位模式,卫星编号,精度因子)

GPGSA,A,3,01,04,08,09,21,199,,,,,,,2.3,1.5,1.8*08

这是一个$GPGSA字段,它包含了GPS卫星的信息和定位模式。各个字段的含义如下:

  • $GPGSA:卫星信息和定位模式
  • A:模式选择,A代表自主定位,M代表手动选择差分GPS
  • 3:定位模式,1表示没有定位,2表示2D定位,3表示3D定位
  • 01,04,08,09,21,199:正在使用的卫星编号,最多同时使用12颗卫星,这里使用了6颗
  • ,:后面6个空字段代表还可以使用的卫星编号
  • 2.3:水平精度因子(HDOP),用于评估卫星几何结构对定位的影响
  • 1.5:垂直精度因子(VDOP),用于评估卫星几何结构对高度的影响
  • 1.8:位置精度因子(PDOP),用于评估卫星几何结构对位置的影响
  • *08:校验和,用于验证数据的完整性

这些信息可以用于确定GPS接收器的定位模式(2D还是3D)和使用的卫星编号以及它们的精度因子。例如,该数据表示GPS接收器正在使用6颗卫星进行3D定位,水平精度因子为2.3,垂直精度因子为1.5,位置精度因子为1.8。

d.$BDGSA(精度因子,使用卫星PRN号码

$BDGSA,A,3,06,07,09,10,16,29,30,38,39,,,,2.3,1.5,1.8*28

这是北斗卫星导航系统接收器输出的一条NMEA消息,其中包含了北斗卫星和接收器的一些状态和信息。具体解释如下:

  • $BDGSA: 表示该消息为北斗卫星导航系统接收器的可见卫星状态消息。
  • A: 表示GPS接收器已经定位成功,可以提供3D定位。
  • 3: 表示目前GPS接收器运行在3D定位模式下,即同时使用卫星的位置数据和时间数据进行GPS定位。
  • 06,07,09,10,16,29,30,38,39: 列举了GPS接收器当前正在使用的卫星的PRN号码。
  • 2.3,1.5,1.8: 是精度因子(DOP)值,代表了接收器的定位精度,其中2.3代表水平定位精度,1.5代表垂直定位精度,1.8代表位置误差因子。DOP越小代表定位越精确。
  • *28: 校验和。

因此,综上所述,该条北斗卫星导航系统接收器输出的NMEA消息告诉我们接收器正在使用哪些卫星进行GPS定位,以及定位的精度因子。

e.$GPGSV(卫星的数量、卫星PRN号码、仰角、方位角以及信噪比)

$GPGSV,3,1,09,01,21,176,41,04,38,212,41,07,36,324,,08,72,355,29*7C $GPGSV,3,2,09,09,38,259,29,16,,,24,21,42,155,43,32,,,17*73 $GPGSV,3,3,09,199,59,148,30*73

第一条消息:

  • $GPGSV: 表示该消息为GPS卫星系统的可视卫星数据消息。
  • 3: 表示总共三条消息,这是这三条消息中的第一条消息。
  • 9: 表示当前当前位置下有九颗卫星。
  • 01, 04, 07, 08: 分别表示对应卫星的PRN号码。
  • 21, 38, 36, 72: 分别表示对应卫星的仰角。
  • 176, 212, 324, 355: 分别表示对应卫星的方位角。
  • *7C: 校验和

第二条消息:

  • $GPGSV: 表示该消息为GPS卫星系统的可视卫星数据消息。
  • 3: 表示总共三条消息,这是这三条消息中的第二条消息。
  • 9: 表示当前当前位置下有九颗卫星。
  • 09: PRN号码为09的卫星。
  • 38: 对应卫星的仰角。
  • 259: 对应卫星的方位角。
  • 29: 对应卫星的信噪比。
  • 16, 24, 32:对应卫星的PRN号码,但它们的仰角信息为空。
  • 21: 对应卫星的仰角。
  • 42: 对应卫星的方位角。
  • 155: 对应卫星的信噪比。
  • 43: 对应卫星的仰角。
  • *73: 校验和。

第三条消息:

  • $GPGSV: 表示该消息为GPS卫星系统的可视卫星数据消息。
  • 3: 表示总共三条消息,这是这三条消息中的第三条消息。
  • 9: 表示当前当前位置下有九颗卫星。
  • 199: PRN号码为199的卫星。
  • 59: 对应卫星的仰角。
  • 148: 对应卫星的方位角。
  • 30:对应卫星的信噪比。
  • *73: 校验和。

总体来说,这些NMEA消息提供了有关当前GPS位置下可视卫星的数量、卫星PRN号码、仰角、方位角以及信噪比的信息。在这个例子中,每条消息提供了GPS系统的9颗可视卫星的一部分详细信息。

f.$BDGSV(卫星编号、仰角、方位角和信号强度等信息

$BDGSV,3,1,12,02,,,34,03,,,32,06,71,192,35,07,62,315,32*67
$BDGSV,3,2,12,09,78,250,36,10,56,298,35,16,68,183,43,29,27,210,33*60
$BDGSV,3,3,12,30,80,160,42,38,12,165,33,39,58,178,40,59,,,37*5E

  • $BDGSV: 北斗卫星可视卫星信息(第1个语句)

    • 3:本次信息包括的GSV语句的数目(最多3个)
    • 1:本语句是信息包中的第几个GSV语句(从1开始)
    • 12:可视卫星总数
    • 02,34:第1颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 03,32:第2颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 06,71,192,35:第3颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 07,62,315,32:第4颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
  • $BDGSV: 北斗卫星可视卫星信息(第2个语句)

    • 3:本次信息包括的GSV语句的数目(最多3个)
    • 2:本语句是信息包中的第几个GSV语句(从1开始)
    • 12:可视卫星总数
    • 09,78,250,36:第5颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 10,56,298,35:第6颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 16,68,183,43:第7颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 29,27,210,33:第8颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
  • $BDGSV: 北斗卫星可视卫星信息(第3个语句)

    • 3:本次信息包括的GSV语句的数目(最多3个)
    • 3:本语句是信息包中的第几个GSV语句(从1开始)
    • 12:可视卫星总数
    • 30,80,160,42:第9颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 38,12,165,33:第10颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 39,58,178,40:第11颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)
    • 59,37:第12颗卫星PRN号(0-63),仰角,方位角,信号强度(0-99dB)

此数据提供了北斗卫星系统当前可见的12颗卫星编号、仰角、方位角和信号强度等信息。其中,PRN号是卫星的唯一标识符,而仰角和方位角则可以用于计算卫星的位置。信号强度是指接收机接收到该卫星信号的强度,可以用来评估定位的质量。

g.$GNRMC(时间,经纬度,日期,定位模式)

$GNRMC,085126.000,A,2311.77819,N,11323.44968,E,0.00,0.00,060123,,,A*7A

该数据是GNSS接收器输出的NMEA数据,其中包含了一条RMC语句,其中的各个字段含义如下:

  • $GNRMC:语句类型,这里表示是GNSS推荐的最小定位信息(Recommended Minimum Specific GNSS Sentence)
  • 085126.000:UTC时间,格式为hhmmss.sss
  • A:定位状态,A表示有效定位,V表示无效定位
  • 2311.77819,N:纬度,格式为ddmm.mmmm,表示23度11.77819分北纬
  • 11323.44968,E:经度,格式为dddmm.mmmm,表示113度23.44968分东经
  • 0.00:对地速度,单位为海里/小时,这里为0表示没有速度信息
  • 0.00:方位角,以正北为0度,顺时针方向旋转的度数,这里为0表示没有方位角信息
  • 060123:日期,格式为ddmmyy,这里表示2002年1月6日
  • 空格:磁偏角方向,这里为空格表示磁偏角为0度
  • 空格:磁偏角值,这里为空格表示磁偏角值未知
  • A:定位模式指示,A表示使用卫星定位,D表示使用惯性定位
  • 7A:校验和,表示该语句的校验和,可以用于检测语句是否正确,校验和算法是将$和之间所有字符的ASCII码值进行异或运算得出的一个十六进制数。

综上,此条语句表示当前GNSS接收器定位状态为有效定位,位置在23度11.77819分北纬,113度23.44968分东经,没有速度信息和方位角信息,日期为2002年1月6日,定位模式为卫星定位。

h.$GNVTG(航向和地速信息

$GNVTG,0.00,T,,M,0.00,N,0.00,K,A*23

该数据是GNSS接收器输出的NMEA数据,其中包含了一条VTG语句,其中的各个字段含义如下:

  • $GNVTG:语句类型,这里表示是GNSS推荐的航向和地速信息(Course Over Ground and Ground Speed)
  • 0.00:真北方向的航向角,也就是航迹角(Track Angle),以正北为0度,顺时针方向旋转的度数,这里为0.00度表示无航向信息
  • T:真北方向的航向角单位,这里表示为真北方向的度数
  • 空格:磁北方向的航向角,以正北为0度,顺时针方向旋转的度数,这里为空格表示无航向信息
  • 空格:磁北方向的航向角单位,这里为空格表示为真北方向的度数
  • M:对地速度单位,这里表示为海里/小时
  • 0.00:对地速度,这里为0.00表示无速度信息
  • N:对地速度单位,这里表示为千米/小时
  • 0.00:对地速度,这里为0.00表示无速度信息
  • K:对地速度单位,这里表示为公里/小时
  • A:定位模式指示,A表示使用卫星定位,D表示使用惯性定位
  • 23:校验和,表示该语句的校验和,可以用于检测语句是否正确,校验和算法是将$和之间所有字符的ASCII码值进行异或运算得出的一个十六进制数。

综上,此条语句表示当前GNSS接收器无航向和地速信息,并且使用卫星定位。

i.$GNZDA(UTC时间)

$GNZDA,085126.000,06,01,2023,00,00*44

该数据是GNSS接收器输出的NMEA数据,其中包含了一条ZDA语句,其中的各个字段含义如下:

  • $GNZDA:语句类型,这里表示是当前UTC时间和日期信息(Time and Date)
  • 085126.000:UTC时间,格式为hhmmss.sss
  • 06:日,表示当前日期是6号
  • 01:月,表示当前月份是1月
  • 2023:年,表示当前年份是2023年
  • 00:本地时区的小时偏移值,这里为0表示与UTC时间相同
  • 00:本地时区的分钟偏移值,这里为0表示与UTC时间相同
  • 44:校验和,表示该语句的校验和,可以用于检测语句是否正确,校验和算法是将$和之间所有字符的ASCII码值进行异或运算得出的一个十六进制数。

综上,此条语句表示当前的UTC时间为08:51:26.000,日期为2023年1月6日。

j.$GPTXT(天线状态)

j.$GPTXT,01,01,01,ANTENNA OK*35

该数据是GNSS接收器输出的NMEA数据,其中包含了一条TXT语句,其中的各个字段含义如下:

  • $GPTXT:语句类型,这里表示是GPS文本报告(GPS Text Transmission)
  • 01:当前消息序号,这里为01
  • 01:总消息数,这里为01
  • 01:文本类型,这里为01表示信息或状态报告
  • ANTENNA OK:文本内容,这里表示天线状态为OK
  • 35:校验和,表示该语句的校验和,可以用于检测语句是否正确,校验和算法是将$和之间所有字符的ASCII码值进行异或运算得出的一个十六进制数。

综上,此条语句表示当前GNSS接收器所连接的天线状态正常。

2.GPS准备

怎么说呢,之所以会有这篇博客,主要是因为我找到的GPS代码解析的数据块和我使用的GPS模块串口所发送的GPS数据块不太一致,我用的GPS是这款GPS:所以需要对手头的代码进行修改,在这里也是对修改内容进行记录,以及效果展示等。

 怎么说呢,之前我买的一个50多块的,因为配套的陶瓷天线太短,在房间里面接受不到信号,最后用了这家的,这家天线做的比较长,属于是细节一点了。但也贵一点就是了。

3.GPS代码编写

其实GPS模块,直接接上后就会自动通过串口将数据进行打印:

 而我们要做的就是把其中的有效信息给提取出来,然后再以另一种我们能简单的方式看懂的方式打印出来。

在这里我们选用$GNGGA字段对GPS数据进行解析:

$GNGGA,084843.000,2311.77332,N,11323.44750,E,1,08,2.1,67.3,M,0.0,M,,*4B

$GNGGA:全球导航卫星系统定位数据

  • 这句话提供有关当前 GPS 定位的信息,包括时间、位置和定位质量。
  • 在这种情况下,句子提供了以下信息:
    • 时间 (UTC):08:48:43.000
    • 纬度:北纬23度11.77332分
    • 经度:东经113度23.44750分
    • GPS 质量指示器:1(修复有效)
    • 使用中的卫星数量:8
    • HDOP:2.1
    • 海拔:平均海拔67.3米
    • 大地水准面间距:0.0 米
    • 差分 GPS 数据的年龄(秒):(空)
    • 差分参考站 ID:(空)
    • 校验和:*4B

这一个字段主要的信息如上,加粗的为我打算解析的数据帧。

开始编写代码:

3.1.基础知识:

3.1.1串口驱动

串口驱动的代码怎么说呢...就大家都是互抄的,我不好评价吧?...知道怎么用就行...在这里贴一份写的很好的整合版的串口驱动程序。

Uart.c:

#include "Uart.h"

/*
*函数名:int set_serial_uart(int ser_fd, int nSpeed, int nBits, char nEvent, int nStop)
*参数1:串口设备文件描述符,如打开USB0转串口,传入"/dev/ttyUSB0"
*参数2:波特率,这里主要是设置了常用的9600与115200等波特率选项
*参数3:数据位,这里主要是设置了7位数据位与8位数据位
*参数4:奇偶校验位,有'0'开启奇校验,'E'开启偶校验,'N'无奇偶校验
*参数5:停止位,有1:一位停止位,2:两位停止位
*/

int set_serial_uart(int ser_fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    /*termios 结构体通常被定义在 <termios.h> 头文件中,这是一个系统级的头文件,用于串口通信的参数配置和控制。在使用串口通信相关函数之前,需要先包含该头文件。*/

/*
*结构体内容:
*struct termios {
*    tcflag_t c_iflag;   /* 输入模式标志 */
*    tcflag_t c_oflag;   /* 输出模式标志 */
*    tcflag_t c_cflag;   /* 控制模式标志 */
*    tcflag_t c_lflag;   /* 本地模式标志 */
*    cc_t c_cc[NCCS];    /* 控制字符 */
*};
*/
	struct termios new_cfg,old_cfg;
		
	/*保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/ 
	if	(tcgetattr(ser_fd, &old_cfg) != 0)
	{
		perror("tcgetattr");
		return -1;
	}
	
    /*使用 bzero() 函数将 new_cfg 结构体变量的所有成员都清零,以确保新的配置不会受到旧的配置的影响。*/
	bzero( &new_cfg, sizeof(new_cfg));
    /*将 new_cfg 结构体变量的值设置为 old_cfg 结构体变量的值,以保留旧的配置。*/
	new_cfg = old_cfg; 
	cfmakeraw(&new_cfg); /* 配置为原始模式,cfmakeraw() 函数是一个串口配置函数,用于将 termios 结构体变量的成员设置为原始模式。原始模式是一种简单的串口通信模式,数据以字节流的形式直接传输,不经过任何处理和转换。在原始模式下,串口通信速度最快,但对于数据的处理和解析需要由应用程序自行完成。 */ 

    /* 设置波特率 */
    switch (nSpeed)
    {
    case 2400:
        cfsetispeed(&new_cfg, B2400);
        cfsetospeed(&new_cfg, B2400);
        break;
    case 4800:
        cfsetispeed(&new_cfg, B4800);
        cfsetospeed(&new_cfg, B4800);
        break;
    case 9600:
        cfsetispeed(&new_cfg, B9600);
        cfsetospeed(&new_cfg, B9600);
        break;
    case 115200:
        cfsetispeed(&new_cfg, B115200);
        cfsetospeed(&new_cfg, B115200);
        break;
    default:
        cfsetispeed(&new_cfg, B9600);
        cfsetospeed(&new_cfg, B9600);
        break;
    }
	
	//用于本地连接和接受使能
	new_cfg.c_cflag |= CLOCAL | CREAD;

	/* 数据位选择 */
	new_cfg.c_cflag &= ~CSIZE;    
    switch (nBits)
    {
    case 7:		/*7位数据位*/
        new_cfg.c_cflag |= CS7;
        break;
    case 8:		/*8位数据位*/
        new_cfg.c_cflag |= CS8;
        break;
    }

	/* 设置奇偶校验位 */
	switch (nEvent)
	{
	case '0':								  /* 奇校验 */
		new_cfg.c_cflag |= PARENB; 		  /* 开启奇偶校验 */
		new_cfg.c_iflag |= (INPCK | ISTRIP); /*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
		new_cfg.c_cflag |= PARODD; 		  /*启用奇校验(默认为偶校验)*/
		break;
	case 'E':								  /*偶校验*/
		new_cfg.c_cflag |= PARENB; 		  /*开启奇偶校验	*/
		new_cfg.c_iflag |= (INPCK | ISTRIP); /*打开输入奇偶校验并去除字符第八个比特*/
		new_cfg.c_cflag &= ~PARODD;		  /*启用偶校验*/
		break;
	case 'N': /*无奇偶校验*/
		new_cfg.c_cflag &= ~PARENB;
		break;
	}

    /*设置停止位*/
    if (nStop == 1) /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则**CSTOPB */
    {
        new_cfg.c_cflag &= ~CSTOPB; /*默认为一位停止位; */
    }
    else if (nStop == 2)
    {
        new_cfg.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位 */
    }
	
    /**/
	/*清除串口缓冲区*/
	tcflush( ser_fd,TCIOFLUSH);
	new_cfg.c_cc[VTIME] = 0; //等待时间,适用于需要立即读取数据的情况,比如串口中的数据流实时更新,不能等待一定时间才读取。
	new_cfg.c_cc[VMIN] = 1; //最少接收字节数,如果串口接收字节数小于1,那么读取操作会被阻塞,直到至少有1个字节可供读取为止。
	tcflush ( ser_fd, TCIOFLUSH);

    /*串口设置使能*/
    if ((tcsetattr(ser_fd, TCSANOW, &new_cfg)) != 0)
    {
        perror("com set error");
        exit(1);
    }
}

Uart.h:

#ifndef __UART_H__
#define __UART_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>   /* 文件控制定义*/
#include <termios.h> /* PPSIX 终端控制定义*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int set_serial_uart(int ser_fd, int nSpeed, int nBits, char nEvent, int nStop);

#ifdef __cplusplus
}
#endif

#endif

gps_analyse.c:

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "./gps_analyse.h"

char str[100];

int gps_analyse(char *buff, GNGGA *gps_data)
{
    char *ptr = NULL;
    
    if (gps_data == NULL)
    {
        return -1;
    }
    if (strlen(buff) < 10)
    {
        return -1;
    }
    /* 如果buff字符串中包含字符"$GPRMC"则将$GPRMC的地址赋值给ptr */
    if (NULL == (ptr = strstr(buff, "$GNGGA")))
    {
        return -1;
    }

    /* sscanf函数为从字符串输入,意思是将ptr内存单元的值作为输入分别输入到后面的结构体成员 */
			  // $GNGGA,110823.000,2311.77676,N,11323.44831,E,1,22,0.8,45.6,M,0.0,M,,*4A 
    sscanf(ptr, "$GNGGA,%d.000,%d.%d,N,%d.%d,E,%d,%d,%d.%d,%d.%d,M,%d.%d,M,,*4%c",
           &(gps_data->time),                			/* gps定位时间 */
           &(gps_data->latitude),            			/* 纬度 */
           &(gps_data->latitude_x),            			/* 纬度小数 */
           &(gps_data->longitude),           			/* 经度 */
           &(gps_data->longitude_x),           			/* 经度小数 */
           &(gps_data->GPS_quilty), 		 			/* GPS质量 */
           &(gps_data->Number_of_Satellites_in_Use),    /* 卫星数量 */
           &(gps_data->HDOP),							/* HDOP */
           &(gps_data->HDOP_x),							/* HDOP小数 */
           &(gps_data->Altitude),	 			        /* 海拔 */
           &(gps_data->Altitude_x),	 			        /* 海拔小数 */
           &(gps_data->Geoidal_Separation), 		    /* 大地水准位间距 */
           &(gps_data->Geoidal_Separation_x), 		    /* 大地水准位间距 */
           &(gps_data->str)); 		    				/* 校验 */
    
    sscanf(ptr,"%s",str);
    return 0;
}

int print_gps(GNGGA *gps_data)
{
	printf("============================================================\n");
	printf("===                                                      ===\n");
	printf("==%s\n",str);
	printf("==时间 : %02d:%02d:%02d\n", (gps_data->time / 10000 + 8) % 24, (gps_data->time % 10000) / 100, gps_data->time % 100);
	printf("==维度 : 北纬%02d度%7.5f分\n", ((int)gps_data->latitude)  / 100, (float)((gps_data->latitude)-(gps_data->latitude)/100*100+(float)(gps_data->latitude_x)/100000));
    printf("==经度 : 东经%02d度%7.5f分\n", ((int)gps_data->longitude)  / 100, (float)((gps_data->longitude)-(gps_data->longitude)/100*100+(float)(gps_data->longitude_x)/100000));
	printf("==使用的卫星数量 : %d个\n", gps_data->Number_of_Satellites_in_Use);
	printf("==HDOP : %d.%d\n", gps_data->HDOP,gps_data->HDOP_x);
	printf("==海拔 : %d.%d\n", gps_data->Altitude,gps_data->Altitude_x);
	printf("==大地水准位间距 : %d.%d\n", gps_data->Geoidal_Separation,gps_data->Geoidal_Separation_x);
	printf("===                                                      ===\n");
	printf("============================================================\n");

    	return 0;
}

gps_analyse.h:

#ifndef __GPS_ANALYSE_H__
#define __GPS_ANALYSE_H__

typedef unsigned int UINT;
typedef int BYTE;

typedef struct __gngga__
{
    UINT time;         					/* gps定位时间 */
    UINT latitude;    					/* 纬度整数 */
	UINT latitude_x;    				/* 纬度整数小数 */
    UINT longitude;   					/* 经度整数 */
	UINT longitude_x;   				/* 经度整数小数 */
	UINT GPS_quilty;					/* GPS质量 */
    UINT Number_of_Satellites_in_Use;   /* 卫星数量 */
	UINT HDOP;							/* HDOP */
	UINT HDOP_x;						/* HDOP小数 */
    UINT Altitude; 						/* 海拔 */
	UINT Altitude_x; 					/* 海拔小数 */
    UINT Geoidal_Separation; 		    /* 大地水准位间距 */
	UINT Geoidal_Separation_x; 		    /* 大地水准位间距 */
	char str;
} GNGGA;

extern int set_option(int fd, int nSpeed, int nBits, char nEvent, int nStop);
extern int print_gps(GNGGA *gps_date);
extern int gps_analyse(char *buff, GNGGA *gps_data);
#endif

T113 板子上运行的现象如上,(makefile没贴上来)代码如下:

链接:https://pan.baidu.com/s/1hG1nzQnEwJvPok1sYvd3jw 
提取码:1234 

Logo

更多推荐