简体   繁体   English

协议帧解码策略

[英]Strategy for protocol frame decoding

I have the following issue: I'm programming micro controllers (ATmega 8bit, 8051, etc...) in C and receive a custom bus-protocol over the UART interface. 我遇到以下问题:我正在用C对微控制器(ATmega 8bit,8051等)进行编程,并通过UART接口接收了自定义的总线协议。 I put the received bytes into an buffer and process them later. 我将接收到的字节放入缓冲区中,然后再处理。

Now the question: Are there any design patterns or strategies to decode the received frames? 现在的问题是:是否有任何设计模式或策略可以对接收到的帧进行解码? How is the best way to do this? 如何做到这一点的最佳方法? Are there any books/tutorials? 有书籍/教程吗?

this is my first question here, so please don't hit me, if the question is not well formed :) 这是我的第一个问题,如果问题的格式不正确,请不要打我:)

Since all such protocols are custom, there is no standard way to approach them as such. 由于所有此类协议都是自定义的,因此没有标准的方法可以照此处理。 The only thing resembling a ADT (or "design pattern" if you will) is the actual reception of data, which is typically done through a ring buffer . 唯一类似于ADT(如果需要的话,就是“设计模式”)是实际的数据接收,通常是通过环形缓冲区来完成的。

What you typically do to parse the actual protocol is nothing fancy, but it is always done in the same manner. 通常,解析实际协议所做的事情并不花哨,但总是以相同的方式完成。 You will end up with something like this: 您最终将得到如下结果:

(I'm using the prefix XYZ in the below code to indicate that the code is meant to decode the fictional "XYZ" protocol. Replace it with the custom protocol's name.) (我在下面的代码中使用前缀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;
}

I've found it is important to design the protocol so that it is easy to decode. 我发现设计协议以使其易于解码非常重要。 My current one has specific start & end bytes. 我当前的那个有特定的开始和结束字节。 So when the UART receives things it knows where the packet starts (setting the buffer index to zero) and where it ends (so it can be processed). 因此,当UART接收到信息时,它便知道数据包在何处开始(将缓冲区索引设置为零)以及在何处结束(以便可以进行处理)。

If you do this you then need to "escape" the start/end bytes in your data, adding another byte in. ie 0x7F -> 0x7D, 0x5F where 0x7D means "next byte is escaped" and the 0x5F represents an escaped 0x7F. 如果执行此操作,则需要“转义”数据中的开始/结束字节,并添加另一个字节。即0x7F-> 0x7D,0x5F其中0x7D表示“下一个字节已转义”,而0x5F表示转义的0x7F。

This has made things heaps easier for me. 这使事情变得对我来说更容易。 The IRQ is simple, unescaping/checking the packet is simple and then it is easy to get the data from the packet bytes. IRQ很简单,对数据包进行转义/检查很简单,然后很容易从数据包字节中获取数据。

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

Process Buffer 工艺缓冲

Unescape the packet data
Check length
Check checksum
Analyse data

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM