c语言解码GPS--实现篇

      通过自己这几天的努力终于把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;
}


你可能感兴趣的:(c语言解码GPS--实现篇)