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

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

程序员文章站 2022-03-06 18:57:52
...

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

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

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

系列一:读报文

系列二:解析报文

这一段隐藏的问题比较多,修改的原因注释在旁边
(关注细节之前,最好先搞清楚它的流程,这样可以准确发现问题所在)

/******************************************************************************
 *  Function    -  Relative address offset
 *  Purpose     -  计算第cx个逗号的相对地址偏移量
 *  Description -  buf为字段的起始地址
*****************************************************************************/
u8 NMEA_Comma_Pos(u8 *buf,u8 cx)
{
    u8 *p=buf;
    while(cx)
    {
        if(*buf=='*'||*buf<' '||*buf>'z')/*排除*和非法字符*/
        {
            return 0XFF;
        }
        if(*buf==','){cx--;}
        buf++;
    }
    return buf-p;/*相对地址偏移量*/
}
/******************************************************************************
 *  Function    -  Relative address offset
 *  Purpose     -  计算每个语句结束符*的相对地址偏移量
  *  Description -  buf为字段的起始地址
**************************************************************************/
u8 NMEA_End_Pos(u8 *buf)
{
 u8 *p = buf;
 while (*buf != '\n')
 {
  if (*buf<' ' || *buf>'z')/*排除非法字符*/
  {
   return 0XFF;
  }
  buf++;
 }
 return buf-p;/*相对地址偏移量*/
}
/******************************************************************************
 *  Function    -  Numeric character to digit
 *  Purpose     -  数字字符转数字
 *  Description -  buf为数字起始地址
**************************************************************************/
//数字字符转数字,扩大了很多倍,使其成为整数 
int NMEA_Str2num(u8 *buf)
{
    u8 *p=buf;/*buf为数字起始地址*/
    u8 i,j,mask=0;/*mask作为负数号与小数点的验证标志*/
    u8 ilen=0,flen=0;/*整数长和小数长*/
    u32 ires=0,fres=0;/*整数和小数*/
    int res;
    
    while((*p!=',')&&(*p!='*')&&(*p!=' '))
    {
  /*if(*p=='-'){mask|=0x02;p++;}*//*进行按位或,mask=0x02是负数*/
        if(*p=='.'){mask|=0x01;p++;}/*小数点*/
        else if(*p>'9'||(*p<'0'))
        {
            ilen = 0;
            flen = 0;
            break;
        }
        if(mask&0x01){flen++;p++;}/*计数小数的位数*/
        //这样计数小数点位数会把小数点也算进去 ,所以在最后相加的时候我把flen减了1 
        else{ilen++;p++;}/*起始检测存在数字*/
    }

 /*if(mask&0x02){flen++;}*//*负数符号位*/
    for(i=0;i<ilen;i++)
    {
        ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');/*buf为数字起始地址*/
    }
    if(flen>6){flen=6;}/*限定6位小数*/
    for(j=0;j<flen;j++)
    {
        fres+=NMEA_Pow(10,flen-1-j)*(buf[ilen+1+j]-'0');/*加多1位小数点偏移量*/
    }
    //因为前面我把flen减一了,导致原本是整数的数乘以 NMEA_Pow(10,flen)无效,变成了0
 //因此在此处重新加上对原本是整数的数的处理 
    if(flen)
    res = ires*NMEA_Pow(10,flen-1)+fres;
    else
    res = ires*NMEA_Pow(10,flen)+fres;
    /*if(mask&0x02)res=-res;*//*负数的情况*/
    return res;
 /******************************************************************************
 *  Function    -  NMEA Check bit calculation check
 *  Purpose     -  NMEA校验位计算检验 
 *  Description -  按位异或计算'$'至'*'之间的字符
*************************************************************************/
//按位异或计算'$'至'*'之间的字符 
int NMEA_Checkout(char str[256])
{
 int i, result, value, avail;
 char *tail;
 
 tail = strstr(str, "*") + 1;
//若按照原来作者写的会把tail 后面的回车换行也一起转换,导致异或校验失败
//所以我把tail截断 
  
 *(tail+2)='\0';
 
 value = NMEA_Str2hex2num(tail);
 
 for (result = str[1], i = 2; str[i] != '*'; i++)
 { 
  result ^= str[i];
 }
 
 if (result == value)
  avail = 1;
 else
  avail = 0;
 
 return avail;
 }
 
}