我有以下问题:我在C语言进行编程的微控制器(8位的ATmega,8051等)和接收自定义总线协议在UART
接口。我将接收到的字节放入缓冲区并稍后处理。策略协议帧解码
现在的问题:是否有任何设计模式或策略来解码接收到的帧?如何做到这一点的最佳方式?有没有书籍/教程?
这是我的第一个问题在这里,所以请不要打我,如果这个问题没有很好地形成:)
我有以下问题:我在C语言进行编程的微控制器(8位的ATmega,8051等)和接收自定义总线协议在UART
接口。我将接收到的字节放入缓冲区并稍后处理。策略协议帧解码
现在的问题:是否有任何设计模式或策略来解码接收到的帧?如何做到这一点的最佳方式?有没有书籍/教程?
这是我的第一个问题在这里,所以请不要打我,如果这个问题没有很好地形成:)
由于所有这些协议都是自定义的,有接近他们,因为没有标准的方式这样。类似于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;
}
非常感谢!这就是我做这件事的方式,与FSM混合 - 所以它不可能如此错误:) – oli
我发现设计协议很重要,因此它很容易解码。我目前有一个具体的开始&结束字节。所以当UART接收到数据时,它知道数据包在哪里开始(将缓冲区索引设置为零)以及它在哪里结束(因此可以进行处理)。
如果你这样做,你需要“逃避”你的数据中的开始/结束字节,增加另一个字节,即0x7F - > 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
你在找什么样的策略?就像如何从特定字节的特定位置提取特定位?我不会把这称为一种战略,对于一件微不足道的事情太过荣幸。如果不是这样,那么你在问什么?你可以说得更详细点吗? –
或者您是否遵循了解析和处理协议流的一般方法? – Joe
@Joe是的,这就是我要找的。我不能更具体,因为我不知道,怎么称呼它:) – oli