安信可-A7模块——C语言编程实现GPS功能

xiaoxiao2021-02-28  128

上一篇博文整理学习了有关串口通信、串口编程的一些基本知识。本篇将通过编程来获取、解析、转换GPS接收机接收的信息。 我们将在fl2440开发板上实现该功能。

一、A7与开发板连线

我使用的是USB转TTL串口转接线,这里要保证Linux支持了所用的转接芯片。我使用的是cp210的USB转串口芯片,因此要在内核选项中支持它:

make menuconfig Device Drivers-> [*]USB support -> [*]USB Serial Converter supportUSB CP210x family of UART Bridge Controllers

make新内核烧录到开发板,这样开发板就使能了USB驱动。 将串口AT指令控制发送端(U_TXD)和串口AT指令控制接收端(U_RXD)分别与USB转TTL转接头上的RXD和TXD相连,GND与GND相连。另一端接入开发板的USB口即可。

二、打开GPS功能并测试

将A7连上开发板以后,在开发板上使用microcom命令监听相关串口,USB转串口芯片连接则监听串口/dev/ttyUSB0。然后把GPS功能打开:

>: microcom -s 115200 /dev/ttyUSB0 >at //检测模块是否正常 OK >AT+GPS=1 //打开GPS功能 OK

此时将A7模块上的U_TXD连线切换到A7模块上的GPS_TXD引脚,其他连线不变。以波特率为9600重新打开监听串口,将会不断的收到GPS定位的数据。

可以看到GPS已经正常工作。

三、编程实现信息获取、解析

首先便是对串口的设置程序s_uart.c。通过串口把数据发送到终端设备,请参考上一篇博文

gps数据分析,gps_analyse.c :

/********************************************************************************* * Copyright: (C) 2017 TangBin<tangbinmvp@gmail.com> * All rights reserved. * * Filename: gps_analyse.c * Description: This file * * Version: 1.0.0(06/04/2017) * Author: TangBin <tangbinmvp@gmail.com> * ChangeLog: 1, Release initial version on "06/04/2017 07:59:41 PM" * ********************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> #include "gps.h" int gps_analyse (char *buff,GPRMC *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,"$GPRMC"))) { return -1; } 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)); /*sscanf函数为从字符串输入,上面这句话的意思是将ptr内存单元的值作为输入分别输入到后面的结构体成员*/ return 0; } /* ----- End of gps_analyis() ----- */ /************************************************************************************** * Description: * Input Args: * Output Args: * Return Value: *************************************************************************************/ int print_gps (GPRMC *gps_data) { printf(" \n"); printf(" \n"); printf("===========================================================\n"); printf("== 全球GPS定位导航模块 ==\n"); printf("== 开发人员:唐彬 ==\n"); printf("== 邮箱:tangbinmvp@gmail.com ==\n"); printf("== 平台:fl2440 ==\n"); printf("===========================================================\n"); printf(" \n"); printf("===========================================================\n"); printf("== GPS状态位 : %c [A:有效状态 V:无效状态] \n",gps_data->pos_state); printf("== GPS模式位 : %c [A:自主定位 D:差分定位] \n", gps_data->mode); printf("== 日期 : 20d-d-d \n",gps_data->date%100,(gps_data->date%10000)/100,gps_data->date/10000); printf("== 时间 : d:d:d \n",(gps_data->time/10000+8)%24,(gps_data->time%10000)/100,gps_data->time%100); printf("== 纬度 : 北纬:%d度%d分%d秒 \n", ((int)gps_data->latitude) / 100, (int)(gps_data->latitude - ((int)gps_data->latitude / 100 * 100)), (int)(((gps_data->latitude - ((int)gps_data->latitude / 100 * 100)) - ((int)gps_data->latitude - ((int)gps_data->latitude / 100 * 100))) * 60.0)); printf("== 经度 : 东经:%d度%d分%d秒 \n", ((int)gps_data->longitude) / 100, (int)(gps_data->longitude - ((int)gps_data->longitude / 100 * 100)), (int)(((gps_data->longitude - ((int)gps_data->longitude / 100 * 100)) - ((int)gps_data->longitude - ((int)gps_data->longitude / 100 * 100))) * 60.0)); printf("== 速度 : %.3f m/s \n",gps_data->speed); printf("== \n"); printf("============================================================\n"); return 0; } /* ----- End of printf_gps() ----- */

对于字段的分析,在上上篇博文已经解读,不过我们要把数据转化一下,方便我们记录和识别。 1. 时间,这个是格林威治时间即世界时间(UTC),把它转换成我们用的北京时间(BTC),在这个时间基础上加8个小时。 2. 经纬度,GPRMC返回的纬度数据位ddmm.mmmm格式即度分格式,我们把它转换成常见的度分秒的格式,计算方法:如接收到的纬度是:3029.60430 3029.60430/100=30.2960430可以直接读出30度, 3029.60430–30*100=29.60430, 可以直接读出29分 (29.60430–29)*60 =0.60430*60=36.258读出36秒, 所以纬度是:30度29分36秒。 3. 南北纬东西经,N:北纬。S:南纬。E:东经。W:西经。 4. 速率,GPRMC返回的速率值是海里/时,单位是节,把它转换成千米/时,换算为:1海里=1.85公里,把得到的速率乘以1.85。 5. 航向,指的是偏离正北的角度 6. 日期,GPRMC的日期格式为:ddmmyy,如:040617表示2017年06月04日,这个日期是准确的,不需要转换。

主函数gps_main.c,这里便涉及到了串口的打开,读操作,以及调用了串口设置函数:

/********************************************************************************* * Copyright: (C) 2017 TangBin<tangbinmvp@gmail.com> * All rights reserved. * * Filename: gps_main.c * Description: This file * * Version: 1.0.0(06/04/2017) * Author: TangBin <tangbinmvp@gmail.com> * ChangeLog: 1, Release initial version on "06/04/2017 08:07:14 PM" * ********************************************************************************/ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> #include <stdlib.h> #include "gps.h" #define GPS_LEN 512 int set_serial(int fd,int nSpeed, int nBits, char nEvent, int nStop); int gps_analyse(char *buff,GPRMC *gps_date); int print_gps(GPRMC *gps_date); /******************************************************************************** * Description: * Input Args: * Output Args: * Return Value: ********************************************************************************/ int main (int argc, char **argv) { int fd = 0; int nread = 0; GPRMC gprmc; char gps_buff[GPS_LEN]; char *dev_name = "/dev/ttyUSB0"; fd = open(dev_name,O_RDWR|O_NOCTTY|O_NDELAY); if(fd<0) { printf("open ttyUSB0 failed.\n"); return -1; } set_serial( fd,9600,8,'N',1); while(1) { sleep(2); nread = read(fd,gps_buff,sizeof(gps_buff)); if(nread<0) { printf("read GPS date error!!\n"); return -2; } printf("gps_buff: %s\n", gps_buff); memset(&gprmc, 0 , sizeof(gprmc)); gps_analyse(gps_buff,&gprmc); print_gps(&gprmc); } close(fd); return 0; } /* ----- End of main() ----- */

gps.h:

/******************************************************************************** * Copyright: (C) 2017 TangBin<tangbinmvp@gmail.com> * All rights reserved. * * Filename: gps.h * Description: This head file * * Version: 1.0.0(06/04/2017) * Author: TangBin <tangbinmvp@gmail.com> * ChangeLog: 1, Release initial version on "06/04/2017 08:10:52 PM" * ********************************************************************************/ #ifndef __GPS_H__ #define __GPS_H__ typedef unsigned int UINT; typedef int BYTE; typedef long int WORD; typedef struct __gprmc__ { UINT time; char pos_state; float latitude; float longitude; float speed; float direction; UINT date; float declination; char dd; char mode; }GPRMC; extern int gps_analysis(char *buff,GPRMC *gps_date); extern int print_gps(GPRMC *gps_date); extern int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop); #endif

接下来使用Makefile编译, Makefile:

1 CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc 2 3 objs=s_uart.o gps_analyse.o gps_main.o 4 srcs=s_uart.c gps_analyse.c gps_main.c 5 6 gps_test: $(objs) 7 $(CC) -o gps_test $(objs) 8 @make clean 9 10 gps_main.o: $(srcs) gps.h 11 $(CC) -c $(srcs) 12 13 set_uart.o: suart.c 14 $(CC) -c s_uart.c 15 16 analyse_gps.o: gps_analyse.c gps.h 17 $(CC) -c gps_analyse.c 18 19 clean: 20 rm *.o [tangbin@localhost gps]$ ls gps_analyse.c gps.h gps_main.c gps_test Makefile s_uart.c

将编译生成的gps_test下载到开发板,运行测试:

转载请注明原文地址: https://www.6miu.com/read-54442.html

最新回复(0)