【问题标题】:c# Serial Port Binary stream processingc# 串口二进制流处理
【发布时间】:2011-10-24 20:19:25
【问题描述】:

我有一个具有二进制输出的串行设备,我使用以下方法捕获数据。

        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int count = sp.BytesToRead;
            byte[] data = new byte[count];
            sp.Read(data, 0, data.Length);
            file.WriteLine(BitConverter.ToString(data));
        }

数据通过,看起来像这样......

06-14-F2-A1-64-2D-62-00-1A-31-00-06-14-F3-84-62-59-01-00-1A-31-00-06-14-F3-85-56-52-55-31
1A-31-00-06-14-F4-18-04-2E-62-00-1A-31-00-06-14-F4-E3-27-5B-01-00-1A-31-00-06-14-F4-E4-1C-51-55-31
1A-31-00-06-14-F5-71-4C-59-71-20-1A-31-00-06-14-F5-8E-A5-2E-62-00-1A-31-00-06-14-F5-F4-47-56-55-31-1A-31-00-06-14-F6-10-1A-1A-31-52-24-1A-31-00-06-14-F6-3D-40-19-70-00-1A-31-00-06-14-F6-3E-9C-4C-55-31-1A-33-00-06-14-F6-F6-11-3D-A0-00-17-B0-C8-4E-42-70-AA-00-00-59-51-1E-1A-31-00-06-14-F7-05-4A-2E-62-00-1A-31-00-06-14-F7-83-5C-56-55-31-1A-31-00-06-14-F7-99-04-5A-01-00-1A-31-00-06-14-F7-99-F8-51-55-31-1A-31-00-06-14-F8-7B-EA-2E-62-00-1A-31-00-06-14-F9-00-CE-56-01-00-1A-31-00-06-14-F9-0E-DF-51-55-31-1A-31-00-06-14-F9-F2-8B-2B-62-00-1A-31-00-06-14-FA-15-1F-1D-05-30-1A-31-00-06-14-FA-62-4D-59-01-00-1A-31-00-06-14-FA-63-41-55-55-31-1A-31-00-06-14-FA-6F-6E-1D-67-67-1A-31-00-06-14-FA-EC-50-2E-72-00-1A-31-00-06-14-FB-22-96-38-62-00-1A-31-00-06-14-FB-3B-7A-40-20-43-1A-31-00-06-14-FB-69-2E-2B-62-00-1A-31-00-06-14-FC-62-F1-2D-72-00-1A-31-00-06-14-FC-DF-D1-2E-62-00-1A-31-00-06

十六进制在这里不是问题,因为我可以对其进行解码,但我正在寻找的语句以 1A-31 开头,然后是一组字节长。正如您所看到的,在这种情况下,串行流从中间流开始,因此不是完整的语句。

如何查找此标记,丢弃开头,然后开始处理。还要记住,这会发生多次,因为 readBuffer 在某些时候会截断流,我需要将它重新拼凑起来?

【问题讨论】:

  • 是的,你回答了你的问题。

标签: c# serial-port


【解决方案1】:

你快到了。您的问题是您正在流式传输的数据以块的形式出现,这与语句的开始和结束位置不一致。我将假设语句的 end 由标识下一条语句的开始的 1A-31 找到。如果这不是真的,请相应地重新解释此答案。

现在,您将无法对示例中的第一条数据执行任何操作,其中包含半条语句。所以,让我们首先假设您获得的第一块数据确实以 1A-31 开头。

现在有两种选择:

  • 您可以在块中找到整个语句(即您在其中遇到另一个 1A-31)。在这种情况下,把它吃掉,然后做任何你想做的事情(我会添加一个StatementReceived 事件并将其发送到那里,或类似的东西)。重复这个练习,直到块被完全处理完。
  • 语句未完全包含在块中。将您已经获得的数据复制到临时缓冲区并等待下一次port_DataReceived 调用。

如果是第二种情况,您知道下一个port_DataReceived 的数据不会以 1A-31 开头(因为临时缓冲区非空)。但是,您可以扫描到它的末尾(直到下一个 1A-31),将临时缓冲区(存储在上一个 port_DataReceived 调用中)添加到它,然后引发 StatementReceived 并擦除临时缓冲区。

使用类似的方法,您也可以处理需要发送超过 2 个数据块的语句;每次没有遇到 1A-31 时,将接收到的数据追加到临时缓冲区,直到语句完成。

最后,如果您在启动时读取的第一个字节不是以 1A-31 开头的,您只需丢弃这些字节。半句语句做不了什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    • 2015-08-16
    • 2010-10-01
    相关资源
    最近更新 更多