我有以下问题:我在C中编写微控制器(ATmega 8bit,8051等)并通过UART
接口接收自定义总线协议。我将接收到的字节放入缓冲区并稍后处理。
现在的问题是:是否有任何设计模式或策略来解码收到的帧?最好的方法是怎样做的?有没有书籍/教程?
这是我在这里的第一个问题,所以如果问题形成不好,请不要打我。)
答案 0 :(得分:1)
由于所有这些协议都是自定义的,因此没有标准的方法来处理它们。唯一类似于ADT(或“设计模式”)的是数据的实际接收,通常通过ring buffer完成。
您通常用来解析实际协议的内容并不奇怪,但总是以相同的方式完成。你最终会得到这样的东西:
(我在下面的代码中使用前缀XYZ来表示该代码用于解码虚构的“XYZ”协议。将其替换为自定义协议的名称。)
// xyz.h
#ifndef XYZ_H
#define XYZ_H
typedef enum
{
XYZ_OK,
XYZ_ERR_SYNC, // various error codes for things that can go wrong
XYZ_ERR_LENGTH,
XYZ_ERR_CHECKSUM,
...
} xyz_result_t;
xyz_result_t xyz_decode (const uint8_t* buf, size_t n);
#endif /* XYZ_H */
// xyz.c
#include "xyz.h"
xyz_result_t xyz_decode (const uint8_t* buf, size_t n)
{
// various protocol-specific checks:
if(buf[0] != SOME_SYNC_CHARACTER)
{
return XYZ_ERR_SYNC;
}
if(buf[something] < expected_min_length ||
buf[something] > expected_max_length)
{
return XYZ_ERR_LENGTH;
}
...
return XYZ_OK;
}
答案 1 :(得分:0)
我发现设计协议很重要,因此很容易解码。我目前的一个具体的开始&amp;结束字节。因此,当UART接收到内容时,它知道数据包的起始位置(将缓冲区索引设置为零)以及它结束的位置(因此可以处理)。
如果你这样做,你需要“逃避”数据中的开始/结束字节,添加另一个字节。即0x7F - &gt; 0x7D,0x5F其中0x7D表示“下一个字节被转义”,0x5F表示转义的0x7F。
这使我的事情变得更容易。 IRQ很简单,没有/检查数据包很简单,然后很容易从数据包字节中获取数据。
IRQ
If (received byte == start flag)
set receive buffer index to zero
else
if (space left in buffer)
store character in buffer
if (received byte == end flag)
process buffer
处理缓冲区
Unescape the packet data
Check length
Check checksum
Analyse data