2013-04-12 101 views
1

我有以下问题:我在C语言进行编程的微控制器(8位的ATmega,8051等)和接收自定义总线协议在UART接口。我将接收到的字节放入缓冲区并稍后处理。策略协议帧解码

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

这是我的第一个问题在这里,所以请不要打我,如果这个问题没有很好地形成:)

+3

你在找什么样的策略?就像如何从特定字节的特定位置提取特定位?我不会把这称为一种战略,对于一件微不足道的事情太过荣幸。如果不是这样,那么你在问什么?你可以说得更详细点吗? –

+0

或者您是否遵循了解析和处理协议流的一般方法? – Joe

+0

@Joe是的,这就是我要找的。我不能更具体,因为我不知道,怎么称呼它:) – oli

回答

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; 
} 
+0

非常感谢!这就是我做这件事的方式,与FSM混合 - 所以它不可能如此错误:) – oli

0

我发现设计协议很重要,因此它很容易解码。我目前有一个具体的开始&结束字节。所以当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