前面写了一系列关于Linux的文章,从这一篇开始换个题目,叫做GPS项目实战系列,后面的很多篇内容都会围绕着这个项目展开。这个项目要完成的任务,可以参考之前的文章:https://topsemic.com/2186.html

今天这篇文章的主题是GPS数据解析,关于GPS的基础知识,我在很早之前的一篇文章(https://topsemic.com/573.html)里有过介绍过,网上也有大量的内容可以参考,不在这里解释了。

关于硬件,之前一直使用的是NUC972板子,今天换一个I.MX 8M的板子,原因是之前那个板子上没有GPS模块,我这正好有个带GPS模块的I.MX板子。其实,对应用程序来说,硬件用什么都无所谓。

因为我的编程水平真的很菜,所以我一般写代码的套路是先从网上搜索,就是典型的拿来主义,先找一个能用的工程跑通,再根据需要去修改。经过简单搜索,我找到了下面的这篇文章,https://blog.csdn.net/zouleideboke/article/details/73521122

由于作者没有给完整工程的下载地址,所以我只能手动去复制代码,经过简单一通Ctrl+C和Ctrl+V操作,在GPSProj文件夹里整了下面五个文件

整完之后,咱们还得简单修改下,一是Makefile中交叉工具链的设置,

把Make的里第一句改成你实际使用的即可,

另外一处是main函数里,修改下你板上GPS模块对应的串口

char *dev_name="/dev/ttyUSB0";

我这里改成了我用的/dev/ttymxc1串口。

然后先去编译一把,看看有没有报错,因为很多时候网上的东西都无法正常编译。

之前我一直是在我的虚拟机上编译的,由于我电脑性能较差,经常把我电脑干卡机。今天想起自己有一个阿里云账号,装的是Ubuntu系统,所以就把它利用了一下,在它上面放了交叉工具链。访问它只需要通过SecureCRT工具登录即可,非常方便。

在编译时,一上来就报了一个错误,提示没有libstdc++.so.6文件

libstdc++.so.6: cannot open shared object file: No such file or directory

咋整,不会就问度娘或者谷哥呗,强烈建议技术相关的问题用谷哥,经过我多次对比后发现,在度娘那查了好久解决不了的问题,用谷哥很快就能搞定。至于怎么用谷哥,你自己开动脑筋去解决吧。上述问题解决方法如下:
         apt-get install lib32stdc++6

然后再次编译,又报错了。。。

经过再一次网上搜索,我尝试把Makefile中命令行前面的空白(如下图红框部分所示)删掉,用Tab键代替,就可以了

这一次编译成功,生成gps_test文件。

在执行程序前,建议先用microcom指令看一下板子的串口是否确实收到了GPS串口的数据。如果GPS接收正常的话,会显示类似如下的信息,

OK,我们把gps_test放到板子里跑一把,先看看情况如何?

如果你发现上述中文对应的是一堆乱码(这个问题折腾了我大半天,我起初以为是编译的问题),后来才发现是SecureCRT里配置的问题,改成下面配置就行了,

从上述执行结果来看,程序是跑起来了,也正确读取到了串口数据,但是没有解析成功。这是啥原因呢?这时就得看一下代码了,首先比较容易发现的是,程序里判断的是$GPRMC,但是我这里读取到的是$GNRMC,所以在下面这段代码就直接返回了:

      if(NULL==(ptr=strstr(buff,"$GPRMC"))){return -1;}

怎么改呢,你是不是会想直接把$GPRMC改成$GNRMC,可以是可以,但是不够好,万一你遇到的是$GPRMC开头的呢?可以改成如下判断条件,含义是既找不到$GPRMC同时也找不到$GNRMC的情况下才返回-1

      if( NULL==(ptr=strstr(buff,"$GPRMC")) && NULL==(ptr=strstr(buff,"$GNRMC")) ){return -1;}

改完了之后下面这句话也得改:

sscanf(ptr,"$GNRMC,%d.00,%c,%f,N,%f,E,%f,,%d,6.91,W,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->date),&(gps_data->mode));

我一开始做了如下修改,我的逻辑是如果查询到有$GPRMC就执行if条件下的语句,否则执行else下面的语句,

if(NULL != (ptr=strstr(buff,"$GPRMC")))sscanf(ptr,"$GPRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->direction),&(gps_data->date),&(gps_data->mode));
elsesscanf(ptr,"$GNRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->direction),&(gps_data->date),&(gps_data->mode));

放进去一跑,结果提示Segmentation fault,在做应用开发的过程中,会经常遇到这个问题。这个问题又调试了半天才发现问题,你们能很快发现问题在哪里吗?

问题出在,当你$GNRMC语句时,在if判断时会给ptr指针赋一个null指针,然后在else语句里用到了ptr,自然会出问题,于是我又做了一次改动

 if(NULL != (ptr=strstr(buff,"$GPRMC")))sscanf(ptr,"$GPRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->direction),&(gps_data->date),&(gps_data->mode));
else if(NULL != (ptr=strstr(buff,"$GNRMC")))sscanf(ptr,"$GNRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->direction),&(gps_data->date),&(gps_data->mode));

兴致勃勃放进去运行了一把,结果如下:

没有解析出正确的字段,我们很容易定位是sscanf那条语句出了问题,由于我之前没用过这个函数,为此我上网查了好久这个函数的用法,后来把思路转向对比作者的GPRMC语句和我收到的GNRMC语句,除了开头不同,其他地方的差异,

$GPRMC,131913.000,A,3029.64972,N,11423.62352,E,0.00,0.00,200617,,,A*67

$GNRMC,085959.00,A,4000.73433,N,11628.03429,E,0.461,,280220,6.91,W,D*29

发现以下有以下几处不同,

  1. 字段1:UTC时间这里,他的小数点后面是3个0,但是我的是2个0
  2. 字段8:方位角这里,他的值是0.00,我的是空白
  3. 字段11和12,磁偏角及磁偏角方向,他的是空白,我的有值

正是这3处不同,导致的上述运行错误问题。原作者完全是按照它的格式来先写的代码,只要有任何一处不同,就极大概率会解析错误。为了先匹配我的这个格式,将第二个sscanf做了如下修改:

sscanf(ptr,"$GNRMC,%d.00,%c,%f,N,%f,E,%f,,%d,6.91,W,%c*",&(gps_data->time),&(gps_data->pos_state),&(gps_data->latitude),&(gps_data->longitude),&(gps_data->speed),&(gps_data->date),&(gps_data->mode));

之后运行,各个字段倒是解析出来了

我们来看一看它解析的对不对

$GNRMC,085959.00,A,4000.73433,N,11628.03429,E,0.461,,280220,6.91,W,D*29

字段9:UTC日期,DDMMYY格式,280220对应2020年02月28日,没错

字段1:UTC时间,hhmmss.sss格式,转换后也是对的,代码里加了一个8,表示的是北京时间。

纬度:dddmm.mmmm度分格式,4000.73433对应,40度,0分,0.73433分,转换秒,0.73433*60=44.0598秒

经度:dddmm.mmmm度分格式,11628.03429对应,116度,28分,0.03429分,转换秒,0.03429*60=2.0574秒

速度:单位是节,1节=1.852 km/h=0.5144 m/s

综上速度单位错了,其他计算是正确的。

但是这个程序真的能这么写吗?

答案是否!

因为你只考虑了这一种情况,上述方向角字段空是因为GPS模块处于静止状态,如果运动起来这个字段就会有值,上述代码就会出问题。

另外比如在GPS信号不好的时候,整个字段的内容也会发生变化,中间会有很多空的情况,比如刚启动的时候,格式就会类似如下,

$GNRMC,064016.00,V,,,,,,,280220,6.91,W,N*2B

所以使用sscanf去处理这种协议类型的数据(数据字段之间以逗号分隔,但是字段可能会为空),显然是不合适的。针对这种类型格式,该如何用去解析呢?希望读者们也想一想,查一查,最好是动手去实现一下,没有板子没关系,直接在电脑上就可以运行。时间不早了,今天就到这里了,敬请期待下一篇文章。

欢迎关注:

GPS项目实战系列1:GPS数据解析1相关推荐

  1. 【PBL项目实战】户外智慧农场项目实战系列——7.Mind+Mixly双平台工业级多合一空气质量传感器数据上云及云端可视化展示

    [PBL项目实战]户外智慧农场项目实战系列--7.Mind+Mixly双平台工业级多合一空气质量传感器数据上云及云端可视化展示 原文链接  https://mp.weixin.qq.com/s/ZEU ...

  2. 【PBL项目实战】户外智慧农场项目实战系列之4——Mind+Mixly双平台ESP32数据上云及云端可视化实时展示

    [PBL项目实战]户外智慧农场项目实战系列之4--Mind+Mixly双平台ESP32数据上云及云端可视化实时展示 原文链接  https://mp.weixin.qq.com/s/r_NeJdPoi ...

  3. 【PBL项目实战】户外智慧农场项目实战系列——5.天气预报API接口对接

    [PBL项目实战]户外智慧农场项目实战系列--5.天气预报API接口对接 原文链接  https://mp.weixin.qq.com/s/jditkIEd-UK6cSQyCC_-Eg 本系列以户外智 ...

  4. 【PBL项目实战】户外智慧农场项目实战系列——1.阿里云物联网平台的开通与云端可视化应用的新建

    岭师人工智能素养教育共同体PBL项目教程系列之1:户外智慧农场项目实战系列 原文链接  https://mp.weixin.qq.com/s/avKWJHNvnPeFsdEXUBByjw 本系列以户外 ...

  5. 【PBL项目实战】户外智慧农场项目实战系列——2.产品与设备的新建及与云端可视化应用的关联

    [PBL项目实战]户外智慧农场项目实战系列--2.产品与设备的新建及与云端可视化应用的关联 原文链接  https://mp.weixin.qq.com/s/mH4bRSf93QC4Jhhd5ci2m ...

  6. Android项目实战系列—基于博学谷(六)习题模块

    由于这个模块内容较多,篇幅较长,请耐心阅读. 习题模块分为两个部分 习题列表界面 习题详情界面 一.习题列表界面 1.习题界面 (1).创建习题界面 在res/layout文件夹中,新建一个布局文件, ...

  7. 【PBL项目实战】户外智慧农场项目实战系列——3.云端可视化页面开发及设备数据源的配置与调试

    [PBL项目实战]户外智慧农场项目实战系列--3.云端可视化页面开发及设备数据源的配置与调试 原文链接  https://mp.weixin.qq.com/s/5OT57-_QlN7lwRMWvey4 ...

  8. Linux运维企业架构项目实战系列

    Linux运维企业架构项目实战系列 目录 一.全网备份 (一)部署Rsync守护进程 1)服务端(backup) 2)客户端(web01/02/03 nfs01) (二)编写脚本文件 1)客户端脚本编 ...

  9. Android项目实战系列—基于博学谷(七)课程模块(上)

    由于这个模块内容较多,分为上.中.下 三篇博客分别来讲述,请耐心阅读. 课程模块分为四个部分 课程列表 课程详情 视频播放 播放记录 课程模块(上)主要讲述课程列表部分 一.水平滑动广告栏界面 1.创 ...

最新文章

  1. 环境DNA高通量测序问题及解决SOP (Part 1: From sample to data)
  2. Linux内核的namespace机制分析
  3. python面试-Python面试题(整理)
  4. Android中的音乐播放
  5. 作者招募 | 听我的,各路炼丹师都来加入我们吧!
  6. 中石油训练赛 - 小A进学校(唯一分解定理)
  7. 忽如一夜冬风来,团队忽然就解散了
  8. wien2k 2009 编译方法
  9. 【论文分享】ACL 2020 信息抽取任务中的新动向
  10. Linux程序设计-1-Linux基础
  11. 转载收集的云计算网络技术
  12. 云原生分布式数据库和数据仓库崛起背后的原因
  13. 程序员常用英语单词汇总
  14. 一文搞明白DNS与域名解析
  15. 北美票房:《玻璃先生》无悬念夺魁
  16. 蓝桥杯试题 入门训练 圆的面积
  17. python 检查是否为数字(包括正负数、浮点数)
  18. 一款拥有漂亮外表的Typecho简洁主题-Scarfskin
  19. 电脑上怎样下载喜马拉雅里的 Mp3
  20. 如何理解类与对象、继承

热门文章

  1. ionic 创建 ionic1、ionic3、ionic4项目
  2. 整理了18家大厂Java面试题共350道(分布式+微服务+高并发)
  3. 获取小程序模板库标题列表 报错: {errcode:-1,errmsg:system error hint: [zttteq44664}
  4. Visio卷积神经网络模型(三)-网络卷积层示意图
  5. 什么是长尾理论-长尾效应
  6. android 人脸道具,Faceunity 面部跟踪和虚拟道具 SDK 在 Android 平台中的集成 Demo
  7. 英文描述疫情的生活状态
  8. 【算法入门】平分七筐鱼
  9. html获取访客ip,jQuery获取访问者IP地址的方法(基于新浪API与QQ查询接口)
  10. C语言俄罗斯方块统计消行,求助 关于俄罗斯方块如何消行(附上消行部分代码)...