嵌入式系统上实现GPS全球定位功能
GPS(Global Positioning System)即全球定位系统,是由美国建立的一个卫星导航定位系统,利用该系统,用户可以在全球范围内实现全天候、连续、实时的三维导航定位和测速;另外,利用该系统,用户还能够进行高精度的时间传递和高精度的精密定位,通过GPS系统可以实现跟踪定位、防盗、里程统计、汽车导航、电子地图等等现实生活不可或缺的功能。本文着眼于在嵌入式linux系统上GPS功能的实现和研究。
1.1 GPS模块与ARM开发板的物理连接
GPS模块属于字符设备,只需要和FL2440开发板的第二个串口连接既可以,然后将GPS测试模块放在室外便可以每隔一段时间向开发板的串口发一个数据包。
~ >: microcom /dev/ttyS1 -s 4800
$GPGGA,024907.000,3029.6642,N,11423.6203,E,1,10,1.0,35.7,M,-13.7,M,,0000*41
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPRMC,024907.000,A,3029.6642,N,11423.6203,E,0.07,244.07,210914,,,A*67
$GPGGA,024908.000,3029.6643,N,11423.6202,E,1,10,1.0,35.3,M,-13.7,M,,0000*4A
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPGSV,3,1,11,04,78,178,38,01,74,066,31,30,56,242,44,11,54,043,31*75
$GPGSV,3,2,11,28,47,328,27,07,40,194,40,08,31,177,47,17,29,277,27*74
$GPGSV,3,3,11,20,23,145,36,32,21,098,33,19,15,059,*4C
$GPRMC,024908.000,A,3029.6643,N,11423.6202,E,0.09,238.16,210914,,,A*6D
$GPGGA,024909.000,3029.6643,N,11423.6202,E,1,10,1.0,35.0,M,-13.7,M,,0000*48
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPRMC,024909.000,A,3029.6643,N,11423.6202,E,0.07,251.95,210914,,,A*66
。。。
1.1 GPS数据解析
GPS数据如何理解呢?这一大串的数据到底代表了什么意思呢?要想编写GPS数据解析程序,肯定要知道这些数据代表什么,还要知道如何转换这些数据。以下给出一个博客链接详细地说明了GPS数据,这里不在做赘述:
http://www.cnblogs.com/csMapx/archive/2011/11/02/2232663.html
1.1 ARM+linux串口编程介绍
其实编写GPS数据解析程序就是ARM+linux串口编程,串口编程是嵌入式应用程序开发中最基础也是最重要的部分,如何从一个串口设备获取数据并将这些数据做一定的解析呢?OK,串口编程大致可以分为以下几个步骤:
至于串口编程的详细介绍,如何设置波特率,如何设置停止位等等,以下给出两个linux串口编程的博客链接,讲的很详细,不再赘述:
http://www.cnblogs.com/wblyuyang/archive/2011/11/21/2257544.html
http://blog.csdn.net/mtv0312/article/details/6599162
1.4 编写一个简单的GPS数据解析程序
这个程序比较简单,只是一个测试GPS数据的程序,GPS数据当中的GPRMC数据就可以用来做导航信息用了,包含了经度、纬度、日期时间等等!如果你们想做一个比较完善的GPS数据解析程序,可以在我的基础上进行修改,比如加上GPS数据出错处理、GPS数据超时处理等等!
OK,我先说一下我的代码包含以下这几个文件:gps_test.c gps_analysis.c set_com.c gpsd.h主函数在gps_test.c文件中,gps_analysis.c主要是GPS数据解析函数设计,set_com.c主要是设置GPS串口设备函数设计,gpsd.h是头文件!
1.4.1 编写gps_test.c测试程序
#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 "gpsd.h"
#define GPS_LEN 512 /* GPS数据长度宏定义 */
int main (int argc, char **argv)
{
int fd = 0;
int nread = 0;
GPRMC gprmc;
//GPRMC *gprmc;
char gps_buff[GPS_LEN];
char *dev_name = "/dev/ttyS1";
fd = open_com(dev_name);
set_opt(fd,4800,8,'N',1);
while(1)
{
sleep(2); //注意这个时间的设置,设置不恰好的话,会导致GPS数据读取不完成,数据解析出错误
nread = read(fd,gps_buff,sizeof(gps_buff));
//printf("gps_buff: %s", gps_buff);
memset(&gprmc, 0 , sizeof(gprmc));
gprmc_analysis(gps_buff, &gprmc);
if(nread > 0)
{
printf("=========== GPS全球定位模块 ==============\n");
printf("== 开发者:韦书胜 ==\n");
printf("== 版本: 1.0.0 ==\n");
printf("===========================================\n");
printf("===========================================\n");
printf("= GPS状态位 : %c [A:有效状态 V:无效状态]=\n" ,gprmc.pos_state);
printf("= GPS模式位 : %c [A:自主定位 D:差分定位]=\n" , gprmc.mode);
printf("=日期 : 20%02d-%02d-%02d=\n", gprmc.date%100, (gprmc.date%10000)/100,
gprmc.date/10000);
printf("=时间 : %02d:%02d:%02d=\n",(gprmc.time/10000+8)%24,(gprmc.time%10000)/100,
gprmc.time%100);
printf("=纬度 : 北纬:%.3f=\n",(gprmc.latitude/100));
printf("=经度 : 东经:%.3f=\n",(gprmc.longitude/100));
printf("=速度 : %.3f =\n",gprmc.speed);
printf("===========================================\n");
}
}
close(fd);
return 0;
} /* ----- End of main() ----- */
1.4.2 编写gps_analysis.c GPS数据解析函数
/*********************************************************************************
* Copyright: (C) 2014 lingyun
* All rights reserved.
*
* Filename: gps_analysis.c
* Description: This file
*
月09日)
* Author: skyyang <790549341@qq.com>
月09日 04时21分53秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gpsd.h"
int gprmc_analysis (char *buff,GPRMC *gprmc)
{
char *ptr = NULL;
if(gprmc == 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*",\
&(gprmc->time),&(gprmc->pos_state),&(gprmc->latitude),&(gprmc->longitude),&(gprmc->speed),&(gprmc->direction),&(gprmc->date),&(gprmc->mode));
return 0;
} /* ----- End of gprmc_analysis() ----- */
//strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
//sscanf() 从一个字符串中读进与指定格式相符的数据。
/*
例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
int ret;
char *string;
int digit;
char buf1[255];
char buf2[255];
string = "china beijing 123";
ret = sscanf(string, "%s %s %d", buf1, buf2, &digit);
printf("1.string=%s\n", string);
printf("1.ret=%d, buf1=%s, buf2=%s, digit=%d\n\n", ret, buf1, buf2, digit);
return 0;
}
执行结果:
1.ret=3, buf1=china, buf2=beijing, digit=123
可以看出,sscanf的返回值是读取的参数个数
*/
1.4.3 编写set_com.c GPS串口设备配置函数
/*********************************************************************************
* Copyright: (C) 2014
* All rights reserved.
*
* Filename: set_com.c
* Description: This file
*
月09日)
* Author:
月09日 04时15分06秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <stdlib.h>
#include "gpsd.h"
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if( tcgetattr( fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O': //奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
{
newtio.c_cflag &= ~CSTOPB;
}
else if ( nStop == 2 )
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
return 0;
}
int open_com(char *device_name)
{
int fd = 0;
if (0 > (fd = open(device_name, O_RDWR|O_NOCTTY|O_NDELAY))) //要设置非阻塞模式打开设备否则会出错!
{
perror("Open Comport Fail:");
return 0;
}
return fd;
}/* ----- End of open_com() ----- */
1.4.4 编写gpsd.h头文件
#ifndef __GPSD_H__
#define __GPSD_H__
typedef unsigned int UINT; //add by wei
typedef int BYTE; //add by wei
typedef long int WORD; //add by wei
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 open_com(char *device_name);
extern int gprmc_analysis(char *buff,GPRMC *gprmc);
extern int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);
#endif
1.5 编译下载GPS数据解析程序到开发板上
1.交叉编译器编译GPS数据解析程序,这里最好自己写一个makefile
[weishusheng@localhost gps_yang]$ ls
gps_analysis.c gpsd.h gps_test gps_test.c makefile set_com.c version.h
[weishusheng@localhost gps_yang]$ /opt/buildroot-2011.11/arm920t/usr/bin/arm-linux-gcc set_com.c gps_test.c gps_analysis.c -o gps_wei_test
[weishusheng@localhost gps_yang]$ ls
gps_analysis.c gpsd.h gps_test.c gps_wei_test set_com.c
生成gps_wei_test
2.在开发板上直接运行gps_test可执行程序,便可以获取解析后的GPS数据了:
/fl2440/gps >: ./gps_wei_test
gps infomation :8,53,332,24,30,52,231,43*77
$GPGSV,3,2,12,11,47,043,15,07,33,192,48,17,32,284,34,20,28,140,14*7C
$GPGSV,3,3,12,08,24,176,47,32,23,091,13,19,11,064,22,06,03,218,24*7F
$GPRMC,030323.000,A,3029.6405,N,11423.6222,E,0.34,332.13,210914,,,A*69
$GPGGA,030324.000,3029.6408,N,11423.6220,E,1,09,1.0,106.1,M,-13.7,M,,0000*7D
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030324.000,A,3029.6408,N,11423.6220,E,0.29,346.94,210914,,,A*61
$GPGGA,030325.000,3029.6410,N,11423.6218,E,1,09,1.0,105.2,M,-13.7,M,,0000*7E
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030325.000,A,3029.6410,N,11423.6218,E,0.28,315.50,210914,,,A*6D
$GPGGA,030326.000,3029.6412,N,11423.6216,E,1,09,1.0,104.5,M,-13.7,M,,0000*77
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030326.000,A,3029.6412,N,11423.621=========== GPS全球定位模块 ==============
== 开发者:weishusheng ==
== 版本: 1.0.0 ==
============================================
============================================
= GPS状态位 : A [A:有效状态 V:无效状态]=
日期 : 2014-09-21
时间 : 11:03:23
纬度 : 北纬:30.296
经度 : 东经:114.236
速度 : 0.340
到此,我们的GPS定位成功!
嵌入式系统上实现GPS全球定位功能的更多相关文章
- 数据终端设备与无线通信模块之间串行通信链路复用协议(TS27.010)在嵌入式系统上的开发【转】
转自:http://blog.csdn.net/hellolwl/article/details/6164449 目录(?)[-] 协议介绍 模块协议介绍 1 命令包格式 2 ...
- Linux嵌入式系统与硬件平台的关系
一. Linux嵌入式系统 操作系统是一种在计算机上运行的软件,它的主要任务是管理计算机上的系统资源,为用户提供使用计算机及其外部设备的接口.它存在的目的是为了管理所有硬件资源,并且提供应用软件一个合 ...
- 【swupdate文档 一】嵌入式系统的软件管理
嵌入式系统的软件管理 嵌入式系统变得越来越复杂, 它们的软件也反映了这种复杂性的增加. 为了支持新的特性和修复,很有必要让嵌入式系统上的软件 能够以绝对可靠的方式更新. 在基于linux的系统上,我们 ...
- 嵌入式设备上的 Linux 系统开发
转载:http://www.ibm.com/developerworks/cn/linux/embed/embdev/index.html 如果您刚接触嵌入式开发,那么大量可用的引导装载程序(bo ...
- 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)
嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...
- 嵌入式系统图形库GUI核心模块介绍
本文转载自:http://blog.csdn.net/xteda/article/details/6575278 (作者 冯青华 信庭嵌入式工作室(www.xteda.com)- CEO Blog:h ...
- 嵌入式系统 Boot Loader 技术内幕
转载:http://www.ibm.com/developerworks/cn/linux/l-btloader/index.html 1. 引言 在专用的嵌入式板子运行 GNU/Linux 系统 ...
- C语言嵌入式系统编程修炼之六:性能优化
使用宏定义 在C语言中,宏是产生内嵌代码的唯一方法.对于嵌入式系统而言,为了能达到性能要求,宏是一种很好的代替函数的方法. 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的 ...
- C语言嵌入式系统编程修炼之四:屏幕操作
汉字处理 现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能.例如,一个微波炉的LCD上没有必要提供显示"电子邮件"的功 ...
随机推荐
- Android AsyncTask异步任务(二)
之前我们讲过了AsyncTask 的生命周期(onPreExecute-->doInBackground-->onProgressUpdate-->onPostExecute),今天 ...
- 第十一&十二&十三周周记
周数 专业学习目标 专业学习时间 新增代码量 博客发表量 人文方面的学习 知识技能总结 第十一周 认真学习网络技术,了解路由器和交换机之间的联通和使用. 一天一小时 300 一篇 每天用一小时看关于经 ...
- (转)Web性能优化方案
第一章 打开网站慢现状分析 在公司访问部署在IDC机房的VIP网站时会感觉很慢.是什么原因造成的?为了缩短页面的响应时间,改进我们的用户体验,我们需要知道用户的时间花在等待什么东西上. 可以跟踪一下我 ...
- javascript获取asp.net服务器端控件的值
代码如下: <%@ Page Language="C#" CodeFile="A.aspx.cs" Inherits="OrderManage_ ...
- httpclient学习
httpclient入门: http://www.ibm.com/developerworks/cn/opensource/os-httpclient/ httpclient证书导入:http: ...
- Silverlight behavior(行为) trigger 大全
behavior是超级有用的东西,一定要学会,因为这个就是面向对象编程中的封装.超级重要! 欢迎大家如果有好的效果,可以给我留言,我打算不断的整理这个behavior,希望不久用behavior可以做 ...
- [原]centos6.5系统可用yum源(32位)以及rpmforge
[10gen] name=10gen Repository baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/i686 gpgche ...
- js版扫雷(可直接运行试玩)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- GGXX的卡通渲染实现 真的好变态......
最近在youtube上看了GDC,学了很多东西,最让我震撼的就是ggxx的卡通渲染了.感慨一下,想要用3D做出二次元的效果,真的不容易.现记录一些要点: 1)不要使用normal map来做cel-s ...
- Java随笔三
1.接口: 1)接口不是类,不能使用new运算符实例化一个接口,而是对类的一组需求描述,这些类要遵循接口描述的统一格式进行定义.个人感觉像C语言中的函数在头文件中的预先声明,但是包含了一些类的特点,比 ...