曲终人散空愁暮,招屈亭前水车注。——刘禹锡《竞渡曲》
前面两篇文章已经描述了串口编程以及在串口调试助手下对GPS信息的解析。这篇文章主要讲怎么样在板子上通过编程来获取GPS信息。
前两篇文章地址:
串口编程:http://blog.youkuaiyun.com/peter_tang6/article/details/72790169
GPS信息解析:http://blog.youkuaiyun.com/peter_tang6/article/details/72146764
我们这个程序分三步走:
1、设置串口
2、获取GPS信息
3、提取出来
设置串口
我的串口用的是/dev/ttyUSB0,具体的串口设置程序在上一篇文章已经详细介绍过,本篇不再赘述。
这里我们使用命令先来监听我们的串口,当然,前提是我们的串口已经能使用,并且我们已经连接好模块,模块的连接方式前面已经说过http://blog.youkuaiyun.com/peter_tang6/article/details/72146764。
使用microcom命令监听GPS(GPS的波特率为9600)
获取GPS数据信息
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: test.c
* Description: This file
*
* Version: 1.0.0(05/28/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "05/28/2017 11:58:17 AM"
*
********************************************************************************/
#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 gps_analysis(char *buff,GPRMC *gps_date);
int print_gps(GPRMC *gps_date);
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);
/********************************************************************************
* Description: main():程序执行的入口
* 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 ttyS1 error!!\n");
return -1;
}
set_opt( 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_analysis(gps_buff, &gprmc);
print_gps(&gprmc);
}
close(fd);
return 0;
} /* ----- End of main() ----- */
附上头文件:
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: gps.h
* Description: This file
*
* Version: 1.0.0(05/28/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "05/28/2017 12:29:30 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
提取GPS数据信息
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: analyze.c
* Description: This file
*
* Version: 1.0.0(05/28/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "05/28/2017 12:33:11 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"
/**************************************************************************************
* Description:从GPS数据包中抽取出GPRMC最小定位信息
* Input Args:buff:GPS返回的数据包 gps_date:GPRMC信息存储结构体
* Output Args:
* Return Value:
*************************************************************************************/
int gps_analysis(char *buff,GPRMC *gps_date)
{
char *ptr=NULL;
if(gps_date==NULL)
return -1;
if(strlen(buff)<10)
return -1;
if(NULL==(ptr=strstr(buff,"$GPRMC")))
return -1;
sscanf(ptr,"$GPRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",&(gps_date->time),&(gps_date->pos_state),&(gps_date->latitude),&(gps_date->longitude),&(gps_date->speed),&(gps_date->direction),&(gps_date->date),&(gps_date->mode));
return 0;
} /* ----- End of if() ----- */
/********************************************************************************************
strstr(str1,str2) 函数用于在字符串str1中搜寻str2,并返回str2在str1中首次出现的地址;否则,返回NULL
sscanf()格式化字符串输入,从一个字符串中读进与指定格式相符的数据并在存入到另一个字符串中
**********************************************************************************************/
/**************************************************************************************
* Description:解析GPRMC最小定位信息,并打印到屏幕上
* Input Args:gps_date:gps_analysis函数抽取的GPRMC信息
* Output Args:
* Return Value:
*************************************************************************************/
int print_gps(GPRMC *gps_date)
{
printf(" \n");
printf(" \n");
printf("===========================================================\n");
printf("== 全球GPS定位导航模块 ==\n");
printf("== 开发人员:唐延军 ==\n");
printf("== 邮箱:519656780@qq.com ==\n");
printf("== 平台:fl2440 ==\n");
printf("== GPS型号:FIT-GPS_SF2820(代替ET-312) ==\n");
printf("===========================================================\n");
printf(" \n");
printf(" \n");
printf("===========================================================\n");
printf("== \n");
printf("== GPS状态位 : %c [A:有效状态 V:无效状态] \n",gps_date->pos_state);
printf("== GPS模式位 : %c [A:自主定位 D:差分定位] \n", gps_date->mode);
printf("== 日期 : 20%02d-%02d-%02d \n",gps_date->date%100,(gps_date->date%10000)/100,gps_date->date/10000);
printf("== 时间 : %02d:%02d:%02d \n",(gps_date->time/10000+8)%24,(gps_date->time%10000)/100,gps_date->time%100);
printf("== 纬度 : 北纬:%d度%d分%d秒 \n", ((int)gps_date->latitude) / 100, (int)(gps_date->latitude - ((int)gps_date->latitude / 100 * 100)), (int)(((gps_date->latitude - ((int)gps_date->latitude / 100 * 100)) - ((int)gps_date->latitude - ((int)gps_date->latitude / 100 * 100))) * 60.0));
printf("== 经度 : 东经:%d度%d分%d秒 \n", ((int)gps_date->longitude) / 100, (int)(gps_date->longitude - ((int)gps_date->longitude / 100 * 100)), (int)(((gps_date->longitude - ((int)gps_date->longitude / 100 * 100)) - ((int)gps_date->longitude - ((int)gps_date->longitude / 100 * 100))) * 60.0));
printf("== 速度 : %.3f \n",gps_date->speed);
printf("== \n");
printf("===========================================================\n");
return 0;
} /* ----- End of print_gps() ----- */
1、我们的时间是格林威治时间,即世界时间(UTC),我们需要把它转换成北京时间,加上8个小时即可。
2、定位状态为V的时候才是有效的数据。
3、经纬度的转换:我们把它转化成度分秒格式
我们收到的是4546.40891
然后4546.40891 / 100 = 45.4640891 则读出45度
然后4546.40891 - 45 * 100 = 46.40891 则读出46分
最后46.40891 - 46 = 0.40891 * 60 = 24.5346 读出24秒
因此最后结果是:45度46分24秒。
然后我通过强制类型转换将这个计算过程用一个表达式表示出来,即上面程序中的经度和纬度的结果。
最后将前面的串口程序和这三个程序放在同一文件夹下,再附上Makefile文件:
CC =/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
objs = serial.o analyze.o test.o
srcs = serial.c analyze.c test.c
gps: $(objs)
$(CC) -o gps $(objs)
@make clean
test.o: $(srcs) gps.h
$(CC) -c $(srcs)
serial.o: serial.c
$(CC) -c serial.c
analyze.o: analyze.c gps.h
$(CC) -c analyze.c
clear:
@rm gps
.PHONY: clean
clean:
@rm *.o
make之后生成gps文件,传到开发板中,给其可执行权限,运行:
程序代码就不一一分析了,这里理清一下代码实现的基本流程:
首先打开我们的设备,即串口
设置我们的串口
将串口输出的内容放到一个buf中
利用strstr和sscanf函数将我们buf中的$GPRMC这一行内容提取出来,并用sscanf函数将其内容与头文件中定义的结构体信息(即这一行信息的内容)一一配对。
sscanf()格式化字符串输入,从一个字符串中读进与指定格式相符的数据并在存入到另一个字符串中;strstr(str1,str2) 函数用于在字符串str1中搜寻str2,并返回str2在str1中首次出现的地址;否则,返回NULL。
最后打印我们的信息。
这段程序主要是针对我们对数据的提取以及对数据的处理能力。