书接上回,上次咱们介绍的如何利用I2C接口接入传感器,这篇文章介绍是如何通过UART连接北斗/GPS模块获取地理位置信息,智慧物流嘛北斗/GPS是传统位置追踪的手段,也可以利用GPS模块给出的时间数据进行校时。
一、北斗/GPS模块介绍GPS购于某宝,类似的厂商有很多知名的有Ublox,,移远等,我这里买的是中科微的,别问为什么选它,问就是便宜... 而且这个模块尺寸小、支持全GNSS系统(北斗、GPS、GLONASS、伽利略、日本的QZSS以及卫星增强系统SBAS)。
1.接MCU的UART
GPS模块
模块引脚说明如下
GPS模块引脚说明
实际与LPC55S69-IOT kit连接的时候,可以按照如下接法,模块的RX可以不接,看要不要配置模块了。如果不配置可以不接的。
LPC55S69-IOT KIT的FlexComm接口接GPS模块示意图
2.GPS模块的数据格式- NEMA码我们可以先用USB转UART的dongle来看看NEMA长什么样子,本狮这里用的是CP2102的模块,用sscom串口助手来接受GPS模块发出来的数据。数据有点多,但是别怕,之后我们先认真分析下后用“拥抱(CTRL+C) +开源(CTRL+V)”的方式给大家节约点时间,毕竟工作后键盘磨秃的不再是AWSD了~
GPS输出的数据
这里本狮说的NEMA码指的是NMEA-0183协议的报文,大多数常见的GNSS接收机、GNSS数据处理软件、导航软件都遵守或者兼容这个协议。
数据里面我们看到三种数据类型 GN、GP、BD 分别代表双模模式、GPS 模式、北斗模式。比如下面这条报文:
根据NMEA-0183协议的规定,$XXGGA报文是关于时间、经纬度位置、解算状态、卫星颗数等相关信息。XX的不同代表模式的不同,比如$GPGGA表示单GPS模式,$BDGGA表示单北斗模式,$GNGGA表示多星联合定位。具体的含义我们对应查表就行了(NEMA-0193协议),微信小文章就不放了,论坛的帖子里我会放具体的表格,定位不一样。 二、MCU如何获取NEMA码并且解析一般来说GPS模块都是和MCU的串口连接的,串口接收数据的方式无非三种,轮询Polling/中断Interrupt/DMA。轮询基本上是不可能选择的模式,所以大多数用户还是用的中断,高阶点的则用DMA的方式。
1.中断的方式中断的方式虽说占用些MCU的资源,但是胜在串口是低速率的并且简单易移植,如果系统设备始终中断资源较少的话影响还好。
2.DMA的方式DMA的方式比较推荐,占用MCU的资源少,一般来说要配置UART的接收完成(Received Idle)信号来完成一次数据的接收并且启动下一次DMA从串口到RAM的搬运工作。但是LPC55系列除了LPC55S3x系列的UART带有Received Idle的功能,其他的比如LPC55S0x,LPC55S1x,LPC55S2x,LPC55S6x都不具备,所以针对这种没有Received Idle的MCU,我们只能启动一个定时器来做Timeout管理了。
3.代码中如何识别咱们可以用strstr的方式去获取GPS的数据头帧的信息,比如:
4.借助开源github上关于GPS的NEMA解码有现成的code,比如GPS_NMEA_parser,现在作者改名叫lwgps了,license比较友好MIT的,基于ANSI C99l垒的码移植起来也很简单,具体见论坛的帖子。 API使用介绍
第一步,声明全局句柄lwgps_t hgps;
第二步,初始化lwgps_init(&hgps);
第三步,在while(1)或者任务中调用lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data));
剩下的就可以通过,hgps.is_valid来判断GPS模块是否定位成功,如果定位成功则hgps.latitude和hgps.longitude就是经纬度数据,hgps.altitude就是高度数据。当然也可以通过hgps的date,month,year等获取时间数据,hpgs.speed获取速度数据等等。具体参考hgps的定义即可。
三、附加知识如果你GPS的实际数据上传到百度或者高德地图的话,多半会和你实际的地理位置差了几公里...那是因为你的GPS模块吐出来的一般是WGS84坐标系,百度地图用的是BD-09坐标系,高德地图用的是GCJ-02坐标系,国外的地图服务商可能会用WGS84坐标系... 数据偏移的算法也不难,网上可查,但是作为一个CTRL+C/V的程序员还是推荐一个开源的代码库ChinaMapShift,license依旧是友好的MIT。 API使用介绍
第一步,声明 WGS84和 GCJ02句柄
Location WGS84;
Location GCJ02;
第二步,将GPS输出的合法的WGS84坐标系的数据赋值给WGS84
WGS84.lat = hgps.latitude;
WGS84.lng = hgps.longitude;
第三步,调用transformFromWGSToGCJ()
GCJ02 = transformFromWGSToGCJ(WGS84);
剩下的,GCJ02.lat以及GCJ02.lng就是GCJ02坐标系下的经纬度数据了。
四、结尾本人水平有限,非常欢迎大家分享如何使用GPS的技巧。