前面主要是在PC上操作串口,接受GPS天线传来的原始数字,下面是编程在用户层对接受到的信息进行处理和解析,有了前面的编写GPRS收发短信的经历,这次编写C程序接受和显示程序接容易多了。当然也参考和学习了网上别人的程序;
以下是实现的具体代码:
/*********************************************************************************
* Copyright: (C) 2014 liucehngdeng<[email protected]>
* All rights reserved.
*
* Filename: gps_test.c
* Description: This file
*
* Version: 0.0.0(09/04/2014~)
* Author: liu chengdeng <[email protected]>
* ChangeLog: 1, Release initial version on "09/04/2014 11:05:23 AM"
*
********************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 1024
typedef struct{
int year;
int month;
int day;
int hour;
int minute;
int second;
}date_time;
typedef struct{
date_time D;
char status;
double latitude;
double longitude;
char NS;
char EW;
double speed;
double high;
}GPS_INFO;
int open_dev(char *dev)
{
int fd = open( dev, O_RDWR| O_NDELAY ); //| O_NOCTTY | O_NDELAY
if (-1 == fd)
{
perror("Can't Open Serial Port !");
return -1;
}
else
return fd;
}
int init_serial(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;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
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] = 100;//杩斿洖鐨勬渶灏忓€? 閲嶈
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
return 0;
}
char * get_gprmc (char * buf)
{
char *buff=buf;
char *target="$GPRMC";
char *p=NULL;
if((p=strstr(buff,target))==NULL)
{
printf("No fonud the string GPRMC\n");
return 0;
}
return p;
}
char * get_gpgga (char * buf)
{
char *buff=buf;
char *target="$GPGGA";
char *p=NULL;
if((p=strstr(buff,target))==NULL)
{
printf("No fonud the string GPGGA\n");
return 0;
}
return p;
}
static int getcomma(int num,char *str)
{
int i,j=0;
int len=strlen(str);
for(i=0;i
if(str[i]==',')j++;
if(j==num)return i+1;
}
return 0;
}
static double get_double_number(char *s)
{
char buf[BUF_SIZE];
int i;
double rev;
i=getcomma(1,s);
strncpy(buf,s,i);
buf[i]=0;
rev=atof(buf);
return rev;
}
static void UTC2BTC(date_time *GPS)
{
//濡傛灉绉掑彿鍏堝嚭,鍐嶅嚭鏃堕棿鏁版嵁,鍒欏皢鏃堕棿鏁版嵁+1绉?
GPS->second++; //鍔犱竴绉?
if(GPS->second>59){
GPS->second=0;
GPS->minute++;
if(GPS->minute>59){
GPS->minute=0;
GPS->hour++;
}
}
GPS->hour+=8; //鍖椾含鏃堕棿璺烾TC鏃堕棿鐩搁殧8灏忔椂
if(GPS->hour>23)
{
GPS->hour-=24;
GPS->day+=1;
if(GPS->month==2 ||GPS->month==4 ||GPS->month==6 ||GPS->month==9 ||GPS->month==11 ){
if(GPS->day>30){ //涓婅堪鍑犱釜鏈堜唤鏄?0澶╂瘡鏈堬紝2鏈堜唤杩樹笉瓒?0
GPS->day=1;
GPS->month++;
}
}
else{
if(GPS->day>31){ //鍓╀笅鐨勫嚑涓湀浠介兘鏄?1澶╂瘡鏈?
GPS->day=1;
GPS->month++;
}
}
if(GPS->year % 4 == 0 ){
if(GPS->day > 29 && GPS->month ==2){ //闂板勾鐨勪簩鏈堟槸29澶?
GPS->day=1;
GPS->month++;
}
}
else{
if(GPS->day>28 &&GPS->month ==2){ //鍏朵粬鐨勪簩鏈堟槸28澶╂瘡鏈?
GPS->day=1;
GPS->month++;
}
}
if(GPS->month>12){
GPS->month-=12;
GPS->year++;
}
}
}
/*姝ゅ嚱鏁颁紶鍏ヤ袱涓瓧绗︿覆$GPRMC 锛?GPGGA鐨勯鍦板潃*/
void gps_parse(char *line1,char *line2,GPS_INFO *GPS)
{
int i,tmp,start,end;
char* buf=line1;
char* buff=line2;
GPS->D.hour =(buf[ 7]-'0')*10+(buf[ 8]-'0');
GPS->D.minute =(buf[ 9]-'0')*10+(buf[10]-'0');
GPS->D.second =(buf[11]-'0')*10+(buf[12]-'0');
tmp = getcomma(9,buf); //寰楀埌绗?涓€楀彿鐨勪笅涓€瀛楃搴忓彿
GPS->D.day =(buf[tmp+0]-'0')*10+(buf[tmp+1]-'0');
GPS->D.month =(buf[tmp+2]-'0')*10+(buf[tmp+3]-'0');
GPS->D.year =(buf[tmp+4]-'0')*10+(buf[tmp+5]-'0')+2000;
GPS->status =buf[getcomma(2,buf)]; //鐘舵€?
GPS->latitude =get_double_number(&buf[getcomma(3,buf)])/100; //绾害
GPS->NS =buf[getcomma(4,buf)]; //鍗楀寳绾?
GPS->longitude=get_double_number(&buf[getcomma(5,buf)])/100; //缁忓害
GPS->EW =buf[getcomma(6,buf)]; //涓滆タ缁?
UTC2BTC(&GPS->D); //杞寳浜椂闂?
GPS->high = get_double_number(&buff[getcomma(9,buff)]);
}
void show_gps(GPS_INFO *GPS)
{
printf("\n");
printf("DATE : %ld-%02d-%02d \n",GPS->D.year,GPS->D.month,GPS->D.day);
printf("TIME : %02d:%02d:%02d \n",GPS->D.hour,GPS->D.minute,GPS->D.second);
printf("Latitude : %4.4f %c\n",GPS->latitude,GPS->NS);
printf("Longitude: %4.4f %c\n",GPS->longitude,GPS->EW);
printf("high : %4.4f \n",GPS->high);
printf("STATUS : %c\n",GPS->status);
}
int main(void)
{
int fd,nset1,nread;
char buf[BUF_SIZE];
char *buff_gprmc,*buff_gpgga;
GPS_INFO GPS;
fd = open_dev("/dev/ttyS1");//鎵撳紑涓插彛
nset1 = init_serial(fd,4800, 8, 'N', 1);//璁剧疆涓插彛灞炴€?
if (nset1 == -1)
exit(1);
while(1)
{
sleep(2);
memset(buf,0,BUF_SIZE);
nread = read(fd, buf, BUF_SIZE);//璇讳覆鍙?
if (nread > 0)
{
printf("\nGPS DATALen=%d\n",nread);
buf[nread] = '\0';
printf( "GPS information as follow:\n\n%s\n", buf); //杈撳嚭鎵€璇绘暟鎹?
}
buff_gprmc=get_gprmc(buf);
buff_gpgga=get_gpgga(buf);
gps_parse(buff_gprmc,buff_gpgga,&GPS);
show_gps(&GPS) ;
}
close(fd);
return 0;
}
下面是在开发板上运行的结果:
[root@root /]# ./gps_info_test
GPS DATALen=598
GPS information as follow:
$GPGGA,043402.000,3029.6468,N,11423.6176,E,1,09,1.2,88.9,M,-13.7,M,,0000*41
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPRMC,043402.000,A,3029.6468,N,11423.6176,E,0.08,134.87,060914,,,A*63
$GPGGA,043403.000,3029.6468,N,11423.6176,E,1,09,1.2,89.0,M,-13.7,M,,0000*48
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPGSV,3,1,12,04,87,286,29,28,66,339,23,01,55,039,26,30,41,216,46*78
$GPGSV,3,2,12,17,39,298,22,20,38,126,29,11,34,046,30,32,25,076,16*75
$GPGSV,3,3,12,07,20,187,37,08,18,180,40,06,14,224,38,19,03,074,*7D
$GPRMC,043403.000,A,3029.6468,N,11423.6176,E,0.15,
DATE : 2014-09-06
TIME : 12:34:03
Latitude : 30.2965 N
Longitude: 114.2362 E
high : 88.9000
STATUS : A
GPS DATALen=434
GPS information as follow:
135.18,060914,,,A*69
$GPGGA,043404.000,3029.6468,N,11423.6176,E,1,09,1.2,89.1,M,-13.7,M,,0000*4E
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPRMC,043404.000,A,3029.6468,N,11423.6176,E,0.16,149.00,060914,,,A*6F
$GPGGA,043405.000,3029.6468,N,11423.6175,E,1,09,1.2,89.3,M,-13.7,M,,0000*4E
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPRMC,043405.000,A,3029.6468,N,11423.6175,E,0.05,113.40,060914,,,A*64
DATE : 2014-09-06
TIME : 12:34:05
Latitude : 30.2965 N
Longitude: 114.2362 E
high : 89.1000
STATUS : A
GPS DATALen=412
GPS information as follow:
$GPGGA,043406.000,3029.6468,N,11423.6175,E,1,09,1.2,89.3,M,-13.7,M,,0000*4D
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPRMC,043406.000,A,3029.6468,N,11423.6175,E,0.06,154.67,060914,,,A*62
$GPGGA,043407.000,3029.6467,N,11423.6175,E,1,09,1.2,89.5,M,-13.7,M,,0000*45
$GPGSA,A,3,30,07,08,04,01,06,17,11,28,,,,2.2,1.2,1.8*3B
$GPRMC,043407.000,A,3029.6467,N,11423.6175,E,0.12,137.48,060914,,,A*61
DATE : 2014-09-06
TIME : 12:34:07
Latitude : 30.2965 N
Longitude: 114.2362 E
high : 89.3000
STATUS : A