walnutcy

基于状态机的NMEA0183与TSIP协议混合解析

0
阅读(2469)

Tremble的授时模块支持两种协议:NMEA0183与TSIP,软件要支持两种协议,

该文讨论如何用状态机同时支持两种协议的分离、解析。

  • NMEA0183,协议简介如下:

[注释]:

◆帧头:1个ASCII字符,‘$’(0x24)

◆信息类别:2个ASCII字符,如‘GP’(0x47 50)

◆信息ID:3个ASCII字符,定义信息内容,‘A’~‘Z’,如‘GGA’。

◆数据:不定长,由‘,’分割。

◆校验和:2个ASCII字符表示的1字节十六进制数,‘$’和‘*’之间全部字符异或运算的结果。通过‘*’与数据段区隔。

◆帧尾:2个ASCII字符,回车换行(0x0D 0x0A)

  • TSIP协议简介如下:

协议解析模块设计如下图中状态所示:

状态机主要分三种状态:等待包头、等待NMEA语句、等待TSIP数据包。

其各个状态的跳转见上图的注释,由数据决定。

由状态机,设计数据结构如下:

structNMEA_PacketST
{
u8 state;
u8 lastCh;// add by walter for TSIP decoder
u16 rxLen;
u16 length;
u8 mDat[120];
};
状态机初始化:

nmea.state = NMEA_STS_HEAD;
nmea.rxLen = 0;

状态机实现:
u8 NMEA_FormatProc(u8 ch)
{
u8 rst =0;

if(nmea.state == NMEA_STS_HEAD)
{
if(('$'== nmea.mDat[1])
&& ('G'== nmea.mDat[2])
&& ('P'== ch))// $GP GGA/GSV/GSA/VTG/RMC/...

{
nmea.state = NMEA_STS_NMEA;
nmea.mDat[0] = nmea.mDat[1];
nmea.mDat[1] = nmea.mDat[2];
nmea.mDat[2] = ch;
nmea.rxLen =3;
}
elseif(ch == TSIP_D_DLE)
{
nmea.state = NMEA_STS_TSIP;
nmea.mDat[0] = ch;
nmea.lastCh = ch;
nmea.rxLen =1;
}
else
{
nmea.mDat[0] = nmea.mDat[1];
nmea.mDat[1] = nmea.mDat[2];
nmea.mDat[2] = ch;

returnrst;
}
}
elseif(nmea.state == NMEA_STS_NMEA)
{
nmea.mDat[nmea.rxLen] = ch;
nmea.rxLen++;
if((nmea.mDat[nmea.rxLen-2] ==0x0D) && (0x0A== ch))
{
nmea.state = NMEA_STS_HEAD;
nmea.length= nmea.rxLen;
nmea.mDat[nmea.rxLen] =0x00;
nmea.rxLen =0;
rst =1;
}
}
elseif(nmea.state == NMEA_STS_TSIP)
{
nmea.mDat[nmea.rxLen] = ch;
nmea.rxLen++;
if((nmea.lastCh == TSIP_D_DLE) && (TSIP_D_DLE == ch))
{
nmea.lastCh =0x00;
}
elseif((nmea.lastCh == TSIP_D_DLE) && (TSIP_D_ETX == ch))
{
nmea.lastCh =0x00;
nmea.length= nmea.rxLen;
nmea.rxLen =0;
rst =2;
}
else
{
nmea.lastCh = ch;
}
}
else
{
nmea.state = NMEA_STS_HEAD;
}

returnrst;
}
这里仅仅讨论了如何分离两种格式的数据,利用了状态机的基本工作原理:状态随条件而跳转,状态决定了软件的工作流程。

欢迎各位讨论,个人联系地址如下:

作者: walnutcy 邮箱: walt_chen#163.com

有两个图像显示有问题,更新下。

Baidu
map