--------------------------------------------------------------------------------------------------------------------------------
系統環境:Centos 6.5
板子芯片:s3c2440
內核版本:linux 3.0
編譯器:arm-linux-gcc 4.5.4
作者:Lu Zengmeng <[email protected]>
--------------------------------------------------------------------------------------------------------------------------------
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): [email protected]
* 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): [email protected]
* 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): [email protected]
* 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): [email protected]
* 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>
交叉編譯後下載到開發板上改權限運行即可