GPS数据解析程序
GPS是英文Global Positioning System(全球定位系统)的简称
卫星定位的原理:
通过卫星发送数据可以计算出接收机与卫星的距离,只要有三颗以上的卫星距离就可以通过空间圆交汇的方法确定出此时接收机所在的空间点坐标,也就是地球上的经纬度了。
GPS接收机的作用:
接收解析它收到的卫星电报,然后再将这些数据组织成一定协议格式的数据按需求输出。
一,GPS数据包解析:
GPRMC 最小定位信息
数据详解:
数据详解:
$GPRMC,080655.00,A,4546.40891,N,12639.65641,E,1.045,328.42,170809,,,A*60
$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=数据无效)
<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=数据无效)
二,串口编程
串口编程的流程
测试程序如下(gps_main.c gps_main.h initSerialDev.c):
gps_main.c如下:
#include "gps_main.h" int gps_analysize (char *gps_buff, GPRMC *gprmc); #define GPS_LEN 512 /* */ int main (int argc, char **argv) { int fd = 0; char gps_buff [GPS_LEN]; GPRMC gprmc; printf("gps_buff LENGTH:%d,%d\n", sizeof(gps_buff), strlen(gps_buff)); fd = open("/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY); if(fd < 0) { printf("Open /dev/ttyS1 error!"); return 0; } initSerialDev(fd, 4800, 8, 'N', 1); while(1) { int nread = 0; sleep(3); nread = read(fd, gps_buff, sizeof(gps_buff)); printf("gps_buff LENGTH:%d,%d\n", sizeof(gps_buff), strlen(gps_buff)); memset(&gprmc, 0, sizeof(gprmc)); gps_analysize(gps_buff, &gprmc); printf("------------ GPS ANALYSIZE DATA --------------\n"); printf("GPS状态位: %c [A:有效定位 V:无效定位]\n", gprmc.pos_state); printf ("GPS模式位: %c [A:自主定位 D:差分 E:估算 N:数据无效\n", gprmc.mode); printf ("日期: 20%02d-%02d-%02d \n", gprmc.date%100, gprmc.date/100%100, gprmc.date/10000); printf ("时间: %02d:%02d:%02d \n",(int)(gprmc.time)/10000 + 8, (int)(gprmc.time)/100%100, (int)(gprmc.time)%100); printf ("纬度: %c:%.3f \n", gprmc.a, gprmc.latitude/100); printf ("经度: %c:%.3f \n", gprmc.b, gprmc.longitude/100); printf ("速度: %.3f \n", gprmc.speed); } close(fd); return 0; } /* ----- End of main() ----- */ /************************************************************************************** * Description: * Input Args: * Output Args: * Return Value: *************************************************************************************/ int gps_analysize (char *gps_buff, GPRMC *gprmc) { char *ptr = NULL; if(NULL == gprmc) { printf("parament gprmc error"); return -1; } if((strlen(gps_buff)) < 10) { printf ("gps_buff error\n"); } if(NULL == (ptr = strstr(gps_buff, "$GPRMC"))) { printf ("cannot find \"$GPRMC\".\n"); return -1; } sscanf (ptr, "$GPRMC,%f,%c,%f,%c,%f,%c,%f,%f,%d,,,%c", \ &(gprmc->time),&(gprmc->pos_state),&(gprmc->latitude),&(gprmc->a),&(gprmc->longitude),&(gprmc->b),&(gprmc->speed),&(gprmc->direction),&(gprmc->date),&(gprmc->mode)); return 0; } /* ----- End of gps_analysize() ----- */
gps_main.h如下:
#ifndef __GPS_MAIN_H__ #define __GPS_MAIN_H__ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define GPS_LEN 512 /* Length of GPS buffer */ typedef unsigned int UINT; //add by skyyang typedef int BYTE; //add by skyyang typedef long int WORD; //add by skyyang typedef struct __gprmc__ { float time; //时间 char pos_state; //定位状态 float latitude; //纬度 char a; //南北半球 char b; //东经或西经 float longitude; //经度 float speed; //移动速度 float direction; //方向 UINT date; //日期 float declination; //磁偏角 char dd; //磁偏角方向 char mode; }GPRMC; int initSerialDev(int fd,int nSpeed, int nBits, char nEvent, int nStop); #endif /* ----- #ifndef __gps_main_h_INC ----- */
initSerialDev.c如下:
#include "gps_main.h" int initSerialDev(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() ----- */
makefile如下:
CC=/opt/buildroot-2011.11/arm920t/usr/bin/arm-linux-gcc BIN_NAME=gpstest #CFLAGS+=-g CFLAGS+=-Wall CFLAGS+=-Werror all: ${CC} ${CFLAGS} *.c -o ${BIN_NAME} install: cp ${BIN_NAME} /tftp clean: @rm -f *.o @rm -f gpstest gps_test testgps
void bzero(void *s, int n); //置字节字符串s的前n个字节为零且包括‘\0’,推荐使用memset替代bzero,<string.h>
错误:
<1>这里我用的gcc编译的
./gpstest
./gpstest: line 1: syntax error: illegal eof marker for << redirection