欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NMEA报文解析程序(c语言)-读报文

程序员文章站 2022-07-12 21:56:58
...

开发工具:DEV
NMEA协议基础知识可参见:GPS理论知识NMEA 0813协议

为完成课程设计而参照网上例子,按照课程要求修改而来

1、在搜集资料过程中发现网上很多都不完整,而且有的会有很多小错误,无法有效运行,自己调试后做了一些修改,能成功运行。
2、因为是上个学期的作业,有些细节不太记得了,但是代码里有修改的地方我都有注释,大家可以参照这些代码段根据自己的需求构建程序。
3、完整工程可以私信我,留下邮箱,看到就会第一时间发送。
4、有错误的地方也希望大家能够指正。

系列一:读报文

//若要查看读取报文的条数,可以在该函数外部定义一个计数变量,在函数内部做自加
//每读一次计数器就加1,注意:不能在函数内部定义,若定义以为内部局部变量则函数每执行一次都会清零计数器 
  while(fgets(buf,256,fpr) != NULL)/*读取直至文件结束,返回所有命令*/
     {        
        if ((head = strstr(buf, "$"))||(segm == 1))/*NMEA命令起始判定//起始符*/
        {
 	  if (head != NULL)
 	  {
   		 strcpy(buf, head);
    		 strcpy(tep,"\0");/*字符串清空处理*/
  	 }
   
 //字符串超长可以再接着收,但如果是错误报文就要丢弃 
  	 tail = strstr(buf, "*");
          if(!tail)/*断句命令判定//结束符*/
          {
             //若未找到结束符,则判断是否超长了 
    		segm = 1;
   		 len = strlen(buf);
              	  buf[len-1] = '\0';
  		  strcat(tep, buf);
   	 	if(strlen(tep) >= 128)/*命令长度超常越界判定*/
   		 {
      			 segm = 0;
                    	strcpy(tep, "\0");/*字符串清空处理*/
                     
   		 }
            }
            else
            {
                segm = 0;
                *(tail + 3) = '\0'; //*后面还有两字节校验和数字 
    		strcat(tep, buf); //至此,tep里面得到的就是含完整报文代码的字符串(含$,*,校验和 ,\0 
    
    
               //文本输出语句,有天线检测硬件功能的模块会输出此语句$GNTXT
               //天线状态:连接,断路,短路 
      //文本输出语句反映的是天线连接状态,无位置信息,因此可以丢弃 
       if(strnstr(tep, "$GNTXT", 6))
    {
        strcpy(tep, "\0");/*字符串清空处理*/
        
                    continue;
    }
     //校验和字段 
    if(!NMEA_Checkout(tep))/*有效命令校验值判定*/
                {
                    strcpy((char*)dat,"\0");/*字符串清空处理*/
                    strcpy(tmp,"\0");/*字符串清空处理*/
                    strcpy(tep,"\0");/*字符串清空处理*/
                }
                else//校验成功 
                {
                 
                    sign = Package(tep);/*检测封包标志*/
                    
                    if(sign)
                    {
                                if(sign == 1) //同数据包 
                        {
                        //dat的defination: static u8 dat[512]="\0";
      //不清楚dat要把每次同的报文cat在一起的用途
      //个人觉得可以将同数据包报文信息的处理删除 
                            strcat((char*)dat, tep);
                            strcat((char*)dat, "\n");//至此,dat里面得到的就是含完整报文代码的字符串(含$,*,校验和,\0,\n  
                            strcpy(tmp, "\0");/*字符串清空处理*/
                            strcpy(tep, "\0");/*字符串清空处理*/
                        }
                        else/*sign == 2*/
                        {
                         
                            strcpy(tmp,"\0");
                            strcat(tmp, tep);
                            strcat(tmp,"\n"); //至此,tmp里面得到的就是含完整报文代码的字符串(含$,*,校验和,\0,\n
                            
                            
                           // Buf = (u8*)dat;
                           //tmp里才有数据,因此改正为 Buf = (u8*)tmp;
          Buf = (u8*)tmp;
                            if(*Buf != '\0')
                            {
                                while (*Buf != '\0')
                                {
                                 //能够处理的所有报文种类 
                                    Buf = NMEA_GPZDA_Analysis(Res, Buf);
                                 Buf = NMEA_GPGGA_Analysis(Res, Buf);
                                    Buf = NMEA_GPGLL_Analysis(Res, Buf);
                                    Buf = NMEA_GPVTG_Analysis(Res, Buf);
                                    Buf = NMEA_GPGSA_Analysis(Res, Buf);
                                    Buf = NMEA_GPGSV_Analysis(Res, Buf);
                                    Buf = NMEA_GPRMC_Analysis(Res, Buf);
                                }
 
                                if((Res->utc.date != 0)&&(Res->utc.month != 0)&&(Res->utc.year != 0))/*日期信息有效*/
                                {
                                    if(((Res->avhemi) == avhemi_) || (avhemi_ == 'C'))/*输入条件判断*/
                                    {
                                        if(((Res->speed) >= speed_) && ((Res->svnum) >= svnum_))
                                        {
                                        
                                            printout(Res,sn_,fpw); //将符合筛选条件的报文中的信息写进文件中 
                                        
                                        }
                                    }
                                }
                                memset(Res, 0, sizeof(Nmea_msg)); //清空该条报文中的所有信息 
                            }
                            strcpy((char*)dat, "\0");
                            strcat((char*)dat, tmp);//至此,该条新报文就处理完了
                            //至此,dat里面得到的就是含完整报文代码的字符串(含$,*,校验和,\0,\n                           
                           
                        } //若是老报文,重复的数据就不用在比较和写进结果文件里了 
                    }
                    else
                    {
                        strcpy((char*)dat,"\0");
                        strcpy(tmp, "\0");/*字符串清空处理*/
                        strcpy(tep, "\0");/*字符串清空处理*/
                    }
                }//校验成功的数据处理完毕 
            }
        }
        else
            continue;
    }
 

自己画了个大概的流程图
NMEA报文解析程序(c语言)-读报文