通過自己這幾天的努力終於把GPS數據全部進行了解碼,相信看了我的日志的人也期待了好久,資源在於分享,才能獲得進步;相對於網上直接調用接口不同的是從C的方向解決問題能讓問題更加的清晰,本設計芯片采用的是聯星的CC550-BG模塊,滿足大多數芯片性能,系統是在LINUX系統下面實現,選用ttyS0節點,根據不同借口,串口線選擇的是RS-232,相信大家也有所了解,詳細的請看我代碼,都有詳細的解釋,希望幫到大家,這裡我只解析了GPRMC格式的編碼,大家也可以把其他幾種格式的編碼解析同樣解析出來,只要在read_data()函數裡面strncmp()的array數組改變名稱就可以,可以把他寫成Switch格式的解碼選擇器,好了廢話不多說,貼上我的代碼!
- #include <stdio.h> /*標准輸入輸出定義*/
- #include <stdlib.h> /*標准函數庫定義*/
- #include <unistd.h> /*Unix 標准函數定義*/
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <string.h>
- #include <fcntl.h>
- #include <termios.h>
-
- //#define dev "/dev/ttyS0"
- #define BUFF_SIZE 512
- #define MAX_COM_NUM 3
-
- int SectionID=0,i=0;
-
- struct data
- {
- char GPS_time[20]; //UTC時間
- char GPS_sv; //使用衛星
- char GPS_wd[12]; //緯度
- char GPS_jd[12]; //經度
- //char GPS_warn; //定位警告
- char GPS_speed[5]; //速度
- char GPS_date[8]; //UTC日期
-
- }GPS_DATA;
-
-
-
- int set_com_config(int fd,int baud_rate,int data_bits,char parity,int stop_bits)
- {
- struct termios new_cfg,old_cfg;
- int speed;
- //保存並測試現有串口參數設置,在這裡如果串口號出錯,會有相關的出錯信息
-
- if(tcgetattr(fd,&old_cfg)!=0)
- {
- perror("tcgetattr");
- return -1;
- }
- tcflush(fd, TCIOFLUSH);
- new_cfg=old_cfg;
- cfmakeraw(&new_cfg);//配置為原始模式
- new_cfg.c_cflag&=~CSIZE;
-
- //設置波特率
- switch(baud_rate)
- {
- case 2400:
- {
- speed = B2400;
- break;
- }
- case 4800:
- {
- speed = B4800;
- break;
- }
- case 9600:
- {
- speed = B9600;
- break;
- }
- case 19200:
- {
- speed = B19200;
- break;
- }
- case 38400:
- {
- speed = B38400;
- break;
- }
- case 115200:
- {
- speed = B115200;
- break;
- }
-
-
- }
- cfsetispeed(&new_cfg,speed);
- cfsetospeed(&new_cfg,speed);
- //設置數據位
-
- switch(data_bits)
- {
- case 7:
- {
- new_cfg.c_cflag|=CS7;
- break;
- }
-
- case 8:
- {
- new_cfg.c_cflag|=CS8;
- break;
- }
-
- }
-
- //設置停止位
- switch(stop_bits)
- {
- case 1:
- {
- new_cfg.c_cflag &=~CSTOPB;
- break;
- }
-
- case 2:
- {
- new_cfg.c_cflag |=CSTOPB;
- break;
- }
-
-
- }
-
- //設置奇偶校驗位
- switch(parity)
- {
- case 'o':
- case 'O':
- {
- new_cfg.c_cflag|=(PARODD|PARENB);
- new_cfg.c_iflag|=(INPCK |ISTRIP);
- break;
- }
- case 'e':
- case 'E':
- {
- new_cfg.c_cflag |=PARENB;
- new_cfg.c_cflag &=~PARODD;
- new_cfg.c_iflag |=(INPCK | ISTRIP);
- break;
- }
- case 's':
- case 'S':
- {
- new_cfg.c_cflag &=~PARENB;
- new_cfg.c_cflag &=~CSTOPB;
- break;
- }
-
- case 'n':
- case 'N':
- {
- new_cfg.c_cflag &=~PARENB;
- new_cfg.c_iflag &=~INPCK;
- break;
- }
-
- }
-
- new_cfg.c_cc[VTIME] =10;
- new_cfg.c_cc[VMIN] =5;
- //處理未接收字符
- tcflush(fd,TCIFLUSH);
-
- if((tcsetattr(fd,TCSANOW,&new_cfg))!=0)
- {
- perror("tcsetattr");
- return -1;
- }
-
- return 0;
- }
-
-
- //打開串口函數
- int open_port(int com_port)
- {
- int fd;
- #if (COM_TYPE == GNR_COM) //使用普通串口
- char* dev[] = {"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};
- #else//使用USB轉串口
- char* dev[] = {"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2"};
- #endif
- if((com_port<0)||(com_port > MAX_COM_NUM))
- {
- return -1;
- }
- //打開串口
- if((fd=open(dev[com_port-1],O_RDWR|O_NOCTTY|O_NDELAY))<0)
- {
- perror("open serial port");
- return -1;
- }
- //恢復串口為堵塞狀態
- if(fcntl(fd,F_SETFL,0) <0 )
- {
- perror("fcntl F_SETFL\n");
- return -1;
-
- }
- //測試是否為終端設備
- if(isatty(STDIN_FILENO)==0)
- {
- perror("standard input is not a terminal device");
- }
- return fd;
- }
-
- void print_info(void)
- {
- //打印選擇界面,即引導的字符號
- printf("Now the receive time is %s\n",GPS_DATA.GPS_time);
- printf("The star is %c 3\n",GPS_DATA.GPS_sv);
- printf("The earth latitude is :%s\n",GPS_DATA.GPS_wd);
- printf("The earth longitude is :%s\n",GPS_DATA.GPS_jd);
- printf("The train speed is:%s km/h\n",GPS_DATA.GPS_speed);
- printf("The date is:%s\n",GPS_DATA.GPS_date);
-
- }
-
-
- void GPS_resolve_GPRMC(char data)
- {
- //$GPRMC,092427.604,V,4002.1531,N,11618.3097,E,0.000,0.00,280812,,E,N*08
-
-
- if(data==',')
- {
- ++SectionID;
- i=0;
- }
- else
- {
- switch(SectionID)
- {
- case 1://02:48:13
- GPS_DATA.GPS_time[i++]=data;
- if(i==2 || i==5)
- {
- GPS_DATA.GPS_time[i++]=':';
- }
- GPS_DATA.GPS_time[8]='\0';
- break;
- case 2:
- if(data=='A')
- GPS_DATA.GPS_sv='>';
- else
- GPS_DATA.GPS_sv='<';
- break;
- case 3://3158.4608
- GPS_DATA.GPS_wd[++i]=data;
- GPS_DATA.GPS_wd[12]='\0';
- break;
-
- case 4:
- if(data=='N')
- GPS_DATA.GPS_wd[0]='N';
- else if(data=='S')
- GPS_DATA.GPS_wd[0]='S';
-
- break;
- case 5://11848.3737,E
-
- GPS_DATA.GPS_jd[++i]=data;
- GPS_DATA.GPS_jd[12]='\0';
- break;
-
- case 6:
- if(data=='E')
- GPS_DATA.GPS_jd[0]='E';
- else if(data=='W')
- GPS_DATA.GPS_jd[0]='W';
-
- break;
- case 7://10.05
- GPS_DATA.GPS_speed[i++]=data;
- GPS_DATA.GPS_speed[4]='\0';
- break;
- case 9://15-07-06 -> 06-07-15
- GPS_DATA.GPS_date[i++]=data;
- if(i==2 || i==5)
- {
- GPS_DATA.GPS_date[i++]='-';
- }
- GPS_DATA.GPS_date[8]='\0';
- break;
- }
- }
-
- }
-
- void read_data(int fd)
- {
- char buffer[BUFF_SIZE],dest[1024];
- char array[10]="$GPRMC";
- int res,i=0,j=0,k;
- int data=1,len=0;
- memset(dest,0,sizeof(dest));
-
- do
- {
- memset(buffer,0,sizeof(buffer));
- //$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
- if(res=read(fd,buffer,1)>0)
- {
- //此處源源不斷傳入參數,一次讀到數據可能為($GPRMC,024),res為讀到長度,現在把每一位傳入函數處理;
- strcat(dest,buffer);
- if(buffer[0]=='\n')
- {
- i=0;
- if(strncmp(dest,array,6)==0)
- {
- printf("%s",dest);
- len=strlen(dest);
- for(k=0;k<len;k++)
- {
- GPS_resolve_GPRMC(dest[k]);
- }
- SectionID=0;
-
- print_info();
- }
- bzero(dest,sizeof(dest));
- }
-
- }
- }while(1);
- close(fd);
-
- }
-
- int main(int argc,char*argv[])
- {
- int fd=0;
- int HOST_COM_PORT=1;
- fd=open_port(HOST_COM_PORT);
- if(fd<0)
- {
- perror("open fail!");
- }
- printf("open sucess!\n");
- if((set_com_config(fd,9600,8,'N',1))<0)
- {
- perror("set_com_config fail!\n");
- }
- printf("The received worlds are:\n");
- read_data(fd);
- return 0;
- }