1

我有以下问题:我正在用 C 语言编写微控制器(ATmega 8bit、8051 等),并通过UART接口接收自定义总线协议。我将接收到的字节放入缓冲区并稍后处理它们。

现在的问题是:是否有任何设计模式或策略来解码接收到的帧?最好的方法是如何做到这一点?有书籍/教程吗?

这是我在这里的第一个问题,所以如果问题格式不正确,请不要打我:)

4

2 回答 2

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;
}
于 2013-04-12T08:05:12.080 回答
0

我发现设计协议以使其易于解码很重要。我当前的有特定的开始和结束字节。因此,当 UART 接收到东西时,它知道数据包从哪里开始(将缓冲区索引设置为零)和在哪里结束(以便可以处理它)。

如果这样做,则需要“转义”数据中的开始/结束字节,在其中添加另一个字节。即 0x7F -> 0x7D,0x5F 其中 0x7D 表示“下一个字节被转义”,0x5F 表示转义的 0x7F。

这让我的事情变得更容易了。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
于 2013-04-16T03:12:40.593 回答