2017-04-20 77 views
0

我写一个状态机在c为一个串行协议。我的数据包格式看起来像这样。状态机的串行协议

delim0接口command_H command_L length_H长度_1有效载荷校验delim1

编辑:我的问题是如何编写C代码用于计算负载和使用这种状态机校验。

我是这个主题的新手,如果我犯了任何简单的错误,请原谅。

switch (dev_int_state) { 
      case UART_INT_STATE_IDLE: 
       if (c == '<') {   // Delim0 = 0x3C 

       dev_int_state = UART_INT_STATE_INTERFACE; 
    } 
    break; 
      case UART_INT_STATE_INTERFACE: 
       if (c == 0x00) {   //Generic Commands = 0x00 

       dev_int_state = UART_INT_STATE_REQ_INTERFACE_SUPPORTED; 
    } 
    break; 
      case UART_INT_STATE_REQ_INTERFACE_SUPPORTED: 
       if (c == 0x00) {  // REQ_INTERFACE_SUPPORTED = 0x00 

       dev_int_state = UART_INT_STATE_GET_PROTOCOLHH; 
    } 
    break; 
      case UART_INT_STATE_GET_PROTOCOLHH: 
       if (c == 0x00) {   // GET_PROTOCOL = 0x00 

       dev_int_state = UART_INT_STATE_GET_PROTOCOLHL; 
    } 
break; 
      case UART_INT_STATE_GET_PROTOCOLHL: 
       if (c == 0x0B) {   // GET_PROTOCOL_RESPONSE = 0x000B 

       dev_int_state = UART_INT_STATE_LENGTHH; 
    } 
break; 
      case UART_INT_STATE_LENGTHH: 
       if (c ==0x04) { 

      dev_int_state = UART_INT_STATE_LENGTHL;   // LENGHT = 4 bytes 
    } 
break; 
      case UART_INT_STATE_LENGTHL: 
      if (c == 0x00) { 



      dev_int_state = UART_INT_STATE_PAYLOAD; 
    } 
break; 
      case UART_INT_STATE_PAYLOAD: 


         {  //--- i want to store the payload in this state 

             } 

      case UART_INT_STATE_CHECKSUM: 

{ 
       size = 0; 
       for (unsigned i = 0; i< headerLength-1; i++) { /* i have computed checksum but not sure about it */ 
        size += headerBuffer[i]; 
       } 

       dev_int_state = UART_INT_STATE_DELIM1; 
} 
break; 

       dev_int_state = UART_INT_STATE_DELIM1; 
} 
break; 
     case UART_INT_STATE_DELIM1: 
       if (c == '>') { 





     } 
     break; 
    default: 
     break; 
} 
+0

*“我的问题是如何计算的有效载荷和校验和使用这种状态机。” *你是什么意思呢?问题必须是确切的,否则将不会负责。请[编辑],并且只有一个*清除*问题。 – user694733

+2

您将按给定协议的规定计算有效负载和校验和。您如何期望互联网上的一些随机人员能够告诉_you_您的特定定制UART协议是如何构建的? – Lundin

+1

注意:您的状态都只有一个*传出*状态。我认为你需要回到初始状态,然后(错误)重新同步。 – joop

回答

0
  1. 请保存接收到的字符c到缓冲区,并增加索引 buffer[index++] = c;
  2. 一旦你到达case UART_INT_STATE_CHECKSUM: 如果你有一个简单的sum-of-sums校验,再加入所有字节的缓冲区(除校验和字节外)。然后将其与接收到的校验和字节进行比较。这真的取决于你的协议有什么样的校验和。

注意:您有时使用c作为1字节,有时使用2字节。如果c是一个字符,那么它总是1个字节。如果先捕获整个数据包,然后将其转换为协议类型的结构并检查相应的值,可能会更容易。

例如:

typedef struct uart_protocol_t 
{ 
    uint8_t delim0; 
    uint8_t interface; 
    union { 
     struct { 
      uint8_t command_H; 
      uint8_t command_L; 
     }cmd_bytes; 
     uint16_t command; 
    }cmd_union; 
    union { 
     struct { 
      uint8_t length_H; 
      uint8_t length_L; 
     }len_bytes; 
     uint16_t length; 
    }len_union; 
    uint8_t payload; 
    uint8_t checksum; 
    uint8_t delim1; 
}uart_protocol_t; 

然后将其丢

uart_protocol_t *p_proto = (uart_protocol_t *)buffer; 
+1

这样的工会通常不是一个好主意,因为它们取决于CPU的永久性而不是数据协议的永恒性。另请注意,这个结构可能会在结构中的任何一点引入填充。 – Lundin

+0

'uart_protocol_t * p_proto =(uart_protocol_t *)buffer;'由于提到的填充/对齐问题,此代码可能根本不适用于许多真实世界的处理器。很有可能你必须编写序列化/反序列化例程。 – Lundin