GPS模塊屬於字符設備,只須要和FL2440開發板的第二個串口鏈接既能夠,而後將GPS測試模塊放在室外即可以每隔一段時間向開發板的串口發一個數據包。html
~ >: microcom /dev/ttyS1 -s 4800linux
$GPGGA,024907.000,3029.6642,N,11423.6203,E,1,10,1.0,35.7,M,-13.7,M,,0000*41
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPRMC,024907.000,A,3029.6642,N,11423.6203,E,0.07,244.07,210914,,,A*67
$GPGGA,024908.000,3029.6643,N,11423.6202,E,1,10,1.0,35.3,M,-13.7,M,,0000*4A
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPGSV,3,1,11,04,78,178,38,01,74,066,31,30,56,242,44,11,54,043,31*75
$GPGSV,3,2,11,28,47,328,27,07,40,194,40,08,31,177,47,17,29,277,27*74
$GPGSV,3,3,11,20,23,145,36,32,21,098,33,19,15,059,*4C
$GPRMC,024908.000,A,3029.6643,N,11423.6202,E,0.09,238.16,210914,,,A*6D
$GPGGA,024909.000,3029.6643,N,11423.6202,E,1,10,1.0,35.0,M,-13.7,M,,0000*48
$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1.0,1.7*3B
$GPRMC,024909.000,A,3029.6643,N,11423.6202,E,0.07,251.95,210914,,,A*66ios
。。。git
GPS數據如何理解呢?這一大串的數據到底表明了什麼意思呢?要想編寫GPS數據解析程序,確定要知道這些數據表明什麼,還要知道如何轉換這些數據。如下給出一個博客連接詳細地說明了GPS數據,這裏不在作贅述:編程
http://www.cnblogs.com/csMapx/archive/2011/11/02/2232663.html函數
其實編寫GPS數據解析程序就是ARM+linux串口編程,串口編程是嵌入式應用程序開發中最基礎也是最重要的部分,如何從一個串口設備獲取數據並將這些數據作必定的解析呢?OK,串口編程大體能夠分爲如下幾個步驟:測試
至於串口編程的詳細介紹,如何設置波特率,如何設置中止位等等,如下給出兩個linux串口編程的博客連接,講的很詳細,再也不贅述:ui
http://www.cnblogs.com/wblyuyang/archive/2011/11/21/2257544.htmlspa
http://blog.csdn.net/mtv0312/article/details/6599162.net
這個程序比較簡單,只是一個測試GPS數據的程序,GPS數據當中的GPRMC數據就能夠用來作導航信息用了,包含了經度、緯度、日期時間等等!若是大家想作一個比較完善的GPS數據解析程序,能夠在個人基礎上進行修改,好比加上GPS數據出錯處理、GPS數據超時處理等等!
OK,我先說一下個人代碼包含如下這幾個文件:gps_test.c gps_analysis.c set_com.c gpsd.h主函數在gps_test.c文件中,gps_analysis.c主要是GPS數據解析函數設計,set_com.c主要是設置GPS串口設備函數設計,gpsd.h是頭文件!
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include "gpsd.h"
#define GPS_LEN 512 /* GPS數據長度宏定義 */
int main (int argc, char **argv)
{
int fd = 0;
int nread = 0;
GPRMC gprmc;
//GPRMC *gprmc;
char gps_buff[GPS_LEN];
char *dev_name = "/dev/ttyS1";
fd = open_com(dev_name);
set_opt(fd,4800,8,'N',1);
while(1)
{
sleep(2); //注意這個時間的設置,設置不剛好的話,會致使GPS數據讀取不完成,數據解析出錯誤
nread = read(fd,gps_buff,sizeof(gps_buff));
//printf("gps_buff: %s", gps_buff);
memset(&gprmc, 0 , sizeof(gprmc));
gprmc_analysis(gps_buff, &gprmc);
if(nread > 0)
{
printf("=========== GPS全球定位模塊 ==============\n");
printf("== 開發者:韋書勝 ==\n");
printf("== 版本: 1.0.0 ==\n");
printf("===========================================\n");
printf("===========================================\n");
printf("= GPS狀態位 : %c [A:有效狀態 V:無效狀態]=\n" ,gprmc.pos_state);
printf("= GPS模式位 : %c [A:自主定位 D:差分定位]=\n" , gprmc.mode);
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)%24,(gprmc.time%10000)/100,
gprmc.time%100);
printf("=緯度 : 北緯:%.3f=\n",(gprmc.latitude/100));
printf("=經度 : 東經:%.3f=\n",(gprmc.longitude/100));
printf("=速度 : %.3f =\n",gprmc.speed);
printf("===========================================\n");
}
}
close(fd);
return 0;
} /* ----- End of main() ----- */
/*********************************************************************************
* Copyright: (C) 2014 lingyun
* All rights reserved.
*
* Filename: gps_analysis.c
* Description: This file
*
* Version: 1.0.0(2014年09月09日)
* Author: skyyang <790549341@qq.com>
* ChangeLog: 1, Release initial version on "2014年09月09日 04時21分53秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gpsd.h"
int gprmc_analysis (char *buff,GPRMC *gprmc)
{
char *ptr = NULL;
if(gprmc == NULL)
return -1;
if(strlen(buff) < 10)
return -1;
if(NULL == (ptr = strstr(buff,"$GPRMC")))
return -1;
sscanf(ptr,"$GPRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",\
&(gprmc->time),&(gprmc->pos_state),&(gprmc->latitude),&(gprmc->longitude),&(gprmc->speed),&(gprmc->direction),&(gprmc->date),&(gprmc->mode));
return 0;
} /* ----- End of gprmc_analysis() ----- */
//strstr(str1,str2) 函數用於判斷字符串str2是不是str1的子串。若是是,則該函數返回str2在str1中首次出現的地址;不然,返回NULL。
//sscanf() 從一個字符串中讀進與指定格式相符的數據。
/*
例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
int ret;
char *string;
int digit;
char buf1[255];
char buf2[255];
string = "china beijing 123";
ret = sscanf(string, "%s %s %d", buf1, buf2, &digit);
printf("1.string=%s\n", string);
printf("1.ret=%d, buf1=%s, buf2=%s, digit=%d\n\n", ret, buf1, buf2, digit);
return 0;
}
執行結果:
1.ret=3, buf1=china, buf2=beijing, digit=123
能夠看出,sscanf的返回值是讀取的參數個數
*/
/*********************************************************************************
* Copyright: (C) 2014
* All rights reserved.
*
* Filename: set_com.c
* Description: This file
*
* Version: 1.0.0(2014年09月09日)
* Author:
* ChangeLog: 1, Release initial version on "2014年09月09日 04時15分06秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <stdlib.h>
#include "gpsd.h"
int set_opt(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() ----- */
#ifndef __GPSD_H__
#define __GPSD_H__
typedef unsigned int UINT; //add by wei
typedef int BYTE; //add by wei
typedef long int WORD; //add by wei
typedef struct __gprmc__
{
UINT time; //時間
char pos_state; //定位狀態
float latitude; //緯度
float longitude; //經度
float speed; //移動速度
float direction; //方向
UINT date; //日期
float declination; //磁偏角
char dd; //磁偏角方向
char mode;
} GPRMC;
extern int open_com(char *device_name);
extern int gprmc_analysis(char *buff,GPRMC *gprmc);
extern int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);
#endif
1.交叉編譯器編譯GPS數據解析程序,這裏最好本身寫一個makefile
[weishusheng@localhost gps_yang]$ ls
gps_analysis.c gpsd.h gps_test gps_test.c makefile set_com.c version.h
[weishusheng@localhost gps_yang]$ /opt/buildroot-2011.11/arm920t/usr/bin/arm-linux-gcc set_com.c gps_test.c gps_analysis.c -o gps_wei_test
[weishusheng@localhost gps_yang]$ ls
gps_analysis.c gpsd.h gps_test.c gps_wei_test set_com.c
生成gps_wei_test
2.在開發板上直接運行gps_test可執行程序,即可以獲取解析後的GPS數據了:
/fl2440/gps >: ./gps_wei_test
gps infomation :8,53,332,24,30,52,231,43*77
$GPGSV,3,2,12,11,47,043,15,07,33,192,48,17,32,284,34,20,28,140,14*7C
$GPGSV,3,3,12,08,24,176,47,32,23,091,13,19,11,064,22,06,03,218,24*7F
$GPRMC,030323.000,A,3029.6405,N,11423.6222,E,0.34,332.13,210914,,,A*69
$GPGGA,030324.000,3029.6408,N,11423.6220,E,1,09,1.0,106.1,M,-13.7,M,,0000*7D
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030324.000,A,3029.6408,N,11423.6220,E,0.29,346.94,210914,,,A*61
$GPGGA,030325.000,3029.6410,N,11423.6218,E,1,09,1.0,105.2,M,-13.7,M,,0000*7E
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030325.000,A,3029.6410,N,11423.6218,E,0.28,315.50,210914,,,A*6D
$GPGGA,030326.000,3029.6412,N,11423.6216,E,1,09,1.0,104.5,M,-13.7,M,,0000*77
$GPGSA,A,3,04,08,28,30,07,17,01,11,19,,,,1.8,1.0,1.5*33
$GPRMC,030326.000,A,3029.6412,N,11423.621=========== GPS全球定位模塊 ==============
== 開發者:weishusheng ==
== 版本: 1.0.0 ==
============================================
============================================
= GPS狀態位 : A [A:有效狀態 V:無效狀態]=
日期 : 2014-09-21
時間 : 11:03:23
緯度 : 北緯:30.296
經度 : 東經:114.236
速度 : 0.340
到此,咱們的GPS定位成功!