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
