串行协议的状态机

时间:2017-04-20 10:41:27

标签: c serial-port uart state-machine

我正在用c编写一个串行协议的状态机。我的数据包格式如下所示。

delim0 interface command_H command_L length_H length_l payload checksum 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;
}

1 个答案:

答案 0 :(得分:0)

  1. 继续将收到的字符c保存到缓冲区并增加索引 buffer[index++] = c;
  2. 到达case UART_INT_STATE_CHECKSUM:后 如果你有一个简单的sum-of-sums校验和,那么在缓冲区中添加所有字节(校验和字节除外)。然后将其与收到的校验和字节进行比较。这实际上取决于你的协议有哪种校验和。
  3. 注意:您有时使用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;