#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <pthread.h>
#include <string.h>
#define BAUDRATE B9600 //gps波特率
#define COM "/dev/ttySAC3" //串口节点
#define FALSE 0
#define TRUE 1
pthread_t pthread_receive,pthread_show_gps_info;
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 STOP=FALSE;
int gpsfd;
int GET_GPS_OK=FALSE;
int gps_location_pass=FALSE;
char GPS_BUF[1024];
int baud=BAUDRATE;
GPS_INFO gps_info;
//得到指定序号的逗号位置
// 从1开始算 return num后出现的第一个字符的位置x(0--x)
static int GetComma(int num,char *str)
{
int i,j=0;
int len=strlen(str);
for(i=0;i<len;i++)
{
if(str[i]==',')j++;
if(j==num)return i+1;
}
return 0;
}
//获取",,""之间的字符串并转换成doule类型
static double get_double_number(char *s)
{
char buf[128];
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;
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){
GPS->day=1;
GPS->month++;
}
}
else{
if(GPS->day>31){
GPS->day=1;
GPS->month++;
}
}
if(GPS->year % 4 == 0 ){
if(GPS->day > 29 && GPS->month ==2){
GPS->day=1;
GPS->month++;
}
}
else{
if(GPS->day>28 &&GPS->month ==2){
GPS->day=1;
GPS->month++;
}
}
if(GPS->month>12){
GPS->month-=12;
GPS->year++;
}
}
}
//show someting gps information
static void show_gps(GPS_INFO *GPS)
{
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 : %10.4f %c\n",GPS->latitude,GPS->NS);
printf("Longitude: %10.4f %c\n",GPS->longitude,GPS->EW);
printf("high : %10.4f \n",GPS->high);
printf("STATUS : %c\n",GPS->status);
}
//解析gps发出的数据
static void gps_parse(char *line,GPS_INFO *GPS)
{
int i,tmp,start,end;
char c;
char* buf=line;
c=buf[5];//first ',' appear location
if(c=='C')//"GPRMC"
{
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)];
if(GPS->status=='A')//vaild data
gps_location_pass=TRUE;
if(GPS->status=='V')//invalid data
gps_location_pass=FALSE;
GPS->latitude =get_double_number(&buf[GetComma(3,buf)]); //纬度
GPS->NS =buf[GetComma(4,buf)]; //南北
GPS->longitude=get_double_number(&buf[GetComma(5,buf)]); //经度
GPS->EW =buf[GetComma(6,buf)]; //东西
UTC2BTC(&GPS->D);//transform world time to beijing time
}
if(c=='A')//"$GPGGA" //高度
{
GPS->high = get_double_number(&buf[GetComma(9,buf)]);
}
}
static void* receive(void * data)
{
int i=0;
char c;
char buf[1024];
GPS_INFO GPS;
printf("read modem\n");
while (STOP==FALSE)
{
read(gpsfd,&c,1);
buf[i++] = c;
if(c == '\n'){
strncpy(GPS_BUF,buf,i);
i=0;
GET_GPS_OK=TRUE;
}
if(STOP)
break;
}
printf("exit from reading modem\n");
return NULL;
}
static void* show_gps_info(void * data)
{
while(1){
if(GET_GPS_OK){
GET_GPS_OK=FALSE;
printf("%s",GPS_BUF);
gps_parse(GPS_BUF,&gps_info);
if(gps_location_pass==TRUE){
show_gps(&gps_info);
}
else
printf("-----------------\n");
}
usleep(100);
if(STOP)break;
}
}
static int uart_init(void)
{
struct termios newstdtio,newtio;
gpsfd = open(COM, O_RDWR );
if (gpsfd <0)
{
perror(COM);
exit(-1);
}
if(tcgetattr(gpsfd,&newstdtio)!= 0)/* get working stdtio */
{
perror("SetupSerial 3");
return(FALSE);
}
newtio.c_cflag = baud | CRTSCTS | CS8 | CLOCAL | CREAD;/*ctrol flag*/
newtio.c_iflag = IGNPAR; /*input flag*/
newtio.c_oflag = 0; /*output flag*/
newtio.c_lflag = 0;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(gpsfd, TCIFLUSH);/* now clean the modem line and activate the settings for modem */
if(tcsetattr(gpsfd,TCSANOW,&newtio)!= 0)/*set attrib */
{
perror("COM");
return (FALSE);
}
return 0;
}
int main(int argc,char** argv)
{
uart_init();
pthread_create(&pthread_receive, NULL, receive, 0);
pthread_create(&pthread_show_gps_info, NULL, show_gps_info,0);
while(!STOP)
{
usleep(100000); //0.1ms
}
close(gpsfd);
exit(0);
}
编译的时候使用
arm-linux-gcc gpc.o -o gps -static -lpthread
关于gps数据的解析,可参考或芯片手册
http://www.cnblogs.com/csMapx/archive/2011/11/02/2232663.html
如果需要将该程序运行在Android上,可运用JNI,最终的效果图如下