串行数据流:如何确保完成

时间:2014-08-20 03:19:16

标签: usbserial

我有一个设备通过USB将串行数据以不同的速度和长度发送到我的程序的COM端口。

在数据中有一个数千字节的块,以特殊的不同代码开始和结束('FDDD'用于开始,'FEEE'用于结束)。

由于流的长度,有时并非所有数据都是一次性收到的。

在解析之前,将所有字节组合成一条消息的推荐方法是什么?

(我负责缓冲区大小,但无法控制串行线路质量,也无法使用USB进行硬件控制)

谢谢

2 个答案:

答案 0 :(得分:0)

实现这一目标的一种可能方法是遵循这些方针:

# variables
#   buffer: byte buffer
#   buffer_length: maximum number of bytes in the buffer
#   new_char: char last read from the UART
#   prev_char: second last char read from the UART
#   n: index to the buffer

new_char := 0
loop forever:
    prev_char := new_char
    new_char := receive_from_uart()

    # start marker
    if prev_char = 0xfd and new_char = 0xdd
        # set the index to the beginning of the buffer
        n := 0
    # end marker
    else if prev_char = 0xfe and new_char = 0xee
        # the frame is ready, do whatever you need to do with a complete message
        # the length of the payload is n-1 bytes
        handle_complete_message(buffer, n-1)
    # otherwise
    else
       if n < buffer_length - 1
           n := n + 1
           buffer[n] := new_char

一些提示/评论:

  • 您不一定需要单独的开始和结束标记(两种用途都可以相同)
  • 如果你想要两个字节的标记,那么使用相同的第一个字节
  • 会更容易
  • 您需要确保数据流中没有标记组合
  • 如果您使用转义码来避免有效负载中的标记,则可以方便地使用相同的代码处理它们
  • 参见HDLC异步成帧(简单编码,解码简单,处理转义)
  • handle_complete_message通常会将buffer的内容复制到其他位置或交换另一个缓冲区,而不是buffer如果匆匆
  • 如果您的数据框没有完整性检查,则应检查有效负载长度是否等于buffer_length - 1,因为那样您可能会溢出

答案 1 :(得分:0)

经过多次测试,我想出了以下关于我自己问题的简单解决方案(对于c#)。 显示的是最小化的简化解决方案。可以添加长度检查等。 “开始”和“结束”是任意长度的字符串标记。

    public void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)

    SerialPort port = (SerialPort)sender;

    inData = port.ReadExisting();
    {
    if (inData.Contains("start"))
           {
          //Loop to collect all message parts   
          while (!inData.Contains("end"))
             inData += port.ReadExisting();  
          //Complete by adding the last data chunk
           inData += port.ReadExisting();
           }                    
          //Use your collected message  
          diaplaydata(inData);