--------------------------------------------------------------------------------------------------------------------------------
系统环境:Centos 6.5
板子芯片:s3c2440
内核版本:linux 3.0
编译器:arm-linux-gcc 4.5.4
作者:Lu Zengmeng <1540999272@qq.com>
--------------------------------------------------------------------------------------------------------------------------------
1、GPS简介
全球定位系统(Global Positioning System,通常简称GPS)是一个中距离圆型轨道卫星导航系统。它可以为地球表面绝大部分地区(98%)提供准确的定位、测速和高精度的时间标准。系统由美国国防部研制和维护,可满足位于全球任何地方或近地空间的军事用户连续精确的确定三维位置、三维运动和时间的需要。该系统包括太空中的24颗GPS卫星;地面上的1个主控站、3个数据注入站和5个监测站及作为用户端的GPS接收机。最少只需其中4颗卫星,就能迅速确定用户端在地球上所处的位置及海拔高度;所能收联接到的卫星数越多,解码出来的位置就越精确。
该系统是由美国政府于20世纪70年代开始进行研制于1994年全面建成。使用者只需拥有GPS接收机,无需另外付费。GPS信号分为民用的标准定位服务(sps,standard positioning service)和军规的精密定位服务(pss,precise positioning service)两类。民用讯号中加有误差,其最终定位精确度大概在100米左右;军规的精度在十米以下。2000年以后,克林顿政府决定取消对民用信号所加的误差。因此,现在民用GPS也可以达到十米左右的定位精度。
GPS系统拥有如下多种优点:全天候,不受任何天气的影响;全球覆盖(高达98%);三维定速定时高精度;快速、省时、高效率;应用广泛、多功能;可移动定位;不同于双星定位系统,使用过程中接收机不需要发出任何信号增加了隐蔽性,提高了其军事应用效能。
2、GPS模块与开发板的数据传输
GPS模块上电后,会不断往串口发送定位信息,所以只需一根串口线相连,开发板就可以通过串口收到来自GPS模块发送的定位信息。而我们要做的,就是正确配置串口,从串口获取数据并解析出我们所需要的信息即可。
3、GPS数据格式
GPS上电并与开发板连接后会发来如下格式的定位信息:
$GPGGA,082006.000,3852.9276,N,11527.4283,E,1,08,1.0,20.6,M,,,,0000*35
$GPRMC,082006.000,A,3852.9276,N,11527.4283,E,0.00,0.0,261009,,*38
$GPVTG,0.0,T,,M,0.00,N,0.0,K*50
我们只需要对其中的GPRMC(最小定位信息)解析便可获得基本位置信息
GPRMC数据格式说明如下:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC 时间,hhmmss(时分秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7>地面速率(000.0~999.9节,前面的0也将被传输)
<8>地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
<9> UTC 日期,ddmmyy(日月年)格式
<10>磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
4、串口配置
通过串口获取GPS数据其实就是串口编程,在嵌入式系统中,串口通信是很基础也很重要的通信方式。对串口的配置可参考博客点击打开链接
下面贴上源代码
头文件
<span style="font-size:14px;">/*************************************************************************
* Copyright (C): 1540999272@qq.com
* Filename: serial.h
* Author: Lu Zengmeng
* Description:
* Creat Time: 2016-03-06 12:11
************************************************************************/
#ifndef __GPS_H__
#define __GPS_H__
extern int speed_arr[];
extern int name_arr[];
extern int nread;
extern int ret;
extern int speed_arr[];
//int gprmc_analysis(char *buff,GPRMC *gprmc);
typedef unsigned int UINT;
typedef struct _gprmc_
{
UINT time;
char status;
float latitude;
char latitude_pos;
float longitude;
char longitude_pos;
float speed;
float direction;
UINT date;
char mode;
}GPRMC;
#endif</span>
gps数据解析
<span style="font-size:14px;">/*************************************************************************
* Copyright (C): 1540999272@qq.com
* Filename: gps_analysis.c
* Author: Lu Zengmeng
* Description:
* Creat Time: 2016-03-06 14:18
************************************************************************/
#include<stdio.h>
#include<string.h>
#include"gps.h"
int gprmc_analysis(char *buff,GPRMC *gprmc)
{
char *ptr = NULL;
if(NULL==gprmc)
{
return -1;
}
if(strlen(buff)<2)
{
return -1;
}
if(NULL==(ptr = strstr(buff,"$GPRMC")))
{
return -1;
}
sscanf(ptr,"$GPRMC,%d.000,%c,%f,%c,%f,%c,%f,%f,%d,,,%c*",\
&(gprmc->time),&(gprmc->status),\
&(gprmc->latitude),&(gprmc->latitude_pos),\
&(gprmc->longitude),&(gprmc->longitude_pos),\
&(gprmc->speed),&(gprmc->direction),\
&(gprmc->date),&(gprmc->mode));
printf("--------------------\n");
switch (gprmc->status)
{
case 'A':
printf("有效定位\n");
break;
case 'V':
printf("无效定位\n");
default:
return -1;
}
switch (gprmc->mode)
{
case 'A':
printf("自主定位\n");
break;
case 'D':
printf("差分\n");
break;
case 'E':
printf("估算\n");
break;
case 'N':
printf("数据无效\n");
break;
default:
return -1;
}
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,(gprmc->time%10000)/100,gprmc->time%100);
switch (gprmc->latitude_pos)
{
case 'S':
printf("南纬:%.2f\n",gprmc->latitude/100);
break;
case 'N':
printf("北纬:%.2f\n",gprmc->latitude/100);
break;
default:
return -1;
}
switch (gprmc->longitude_pos)
{
case 'E':
printf("东经:%.2f\n",gprmc->longitude/100);
break;
case 'W':
printf("西经:%.2f\n",gprmc->longitude/100);
break;
default:
return -1;
}
printf("--------------------\n");
return 0;
}
</span>
串口设置
<span style="font-size:14px;">/*************************************************************************
* Copyright (C): 1540999272@qq.com
* Filename: serial_init.c
* Author: Lu Zengmeng
* Description:
* Creat Time: 2015-11-28 14:24
************************************************************************/
#include<stdio.h>
#include<termios.h>
#include<fcntl.h>
#include<string.h>
#include"gps.h"
#define FAIL -1
#define OK 0
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,
38400, 19200, 9600, 4800, 2400, 1200, 300, };
/* set baud rate */
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios options;
tcgetattr(fd, &options);
options.c_iflag &= ~ (INLCR | ICRNL | IGNCR);
options.c_oflag &= ~(ONLCR | OCRNL);
options.c_iflag &= ~(IXON);
for( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if(speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);/*empty input cache*/
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &options);
if(status != 0)
perror("tcsetattr fd");
return;
}
tcflush(fd,TCIOFLUSH);/*empty input cache*/
}
}
/**
* *@brief 设置串口数据位,停止位和效验位
* *@param fd 类型 int 打开的串口文件描述符
* *@param databits 类型 int 数据位 取值 为 7 或者8
* *@param stopbits 类型 int 停止位 取值为 1 或者2
* *@param parity 类型 int 效验类型 取值为N,E,O,S
* */
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return(FAIL);
}
options.c_cflag &= ~CSIZE;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
options.c_oflag &= ~OPOST; /*Output*/
switch (databits) /*set datebits*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FAIL);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FAIL);
}
/*set stopbits */
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FAIL);
}
/* Set input parity options */
if (parity != 'n')
options.c_iflag |= INPCK;
options.c_cc[VTIME] = 0; // 15 seconds
options.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH); /* Update the optionsions and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("tcsetattr");
return FAIL;
}
return (OK);
}
/**
* *@breif open device
* */
int open_dev(char *Dev)
{
int fd = open( Dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (-1 == fd)
{
perror("open");
return FAIL;
}
else
return fd;
}
</span>
主程序
<span style="font-size:14px;">/************************************************************************* * Copyright (C): 1540999272@qq.com
* Filename: serial_test.c
* Author: Lu Zengmeng
* Description:
* Creat Time: 2015-11-28 11:47
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /*file control definition */
#include <termios.h>/*terminal control definition*/
#include <errno.h>
#include "gps.h"
#define DEVICE "/dev/ttyS1"
#define BUFF_LEN 1024
/* start main */
int main(int argc,char **argv)
{
/* open device */
int fd;
char *dev = DEVICE;
fd = open_dev(dev);
printf("打开设备...fd:%d\n",fd);
/* configure device */
set_Parity(fd,8,1,'N');
set_speed(fd,speed_arr[3]);
GPRMC gprmc;
char buff[BUFF_LEN];
int nread;
printf("开始定位...\n");
//while(1)
int i;
for(i=0;i<5;i++)
{
memset(buff,0,sizeof(buff));
fcntl(fd, F_SETFL, FNDELAY);
if((nread=read(fd,buff,sizeof(buff)))<0)
{
perror("read");
}
sleep(2);
//fprintf(stdout,"%s,\n",buff);
memset(&gprmc,0,sizeof(gprmc));
gprmc_analysis(&buff,&gprmc);
}
/*close device*/
close(fd);
printf("定位结束...\n");
printf("关闭设备...\n");
return 0;
}
/* end of main */
</span>
交叉编译后下载到开发板上改权限运行即可