在SerialPort vb.net中读取字节值26

在SerialPort vb.net中读取字节值26,vb.net,Vb.net,我有一个vb.net winforms应用程序,可以将串行数据读取/写入连接到USB-RS485设备的多个设备。该应用程序是用visual basic.NET 2008编写的,尽管我也尝试了.NET 2015 除了其中一个设备发送字节值为26的消息外,几乎所有设备都工作正常。然后我不确定到底发生了什么,但在26字节值之后,读取似乎停止了。之后的所有数据将在下一个DataReceived事件中读取 我已经做了一个简短的程序,只测试串行端口。它显示了完全相同的结果。此外,我只有一个设备与测试连接。

我有一个vb.net winforms应用程序,可以将串行数据读取/写入连接到USB-RS485设备的多个设备。该应用程序是用visual basic.NET 2008编写的,尽管我也尝试了.NET 2015

除了其中一个设备发送字节值为26的消息外,几乎所有设备都工作正常。然后我不确定到底发生了什么,但在26字节值之后,读取似乎停止了。之后的所有数据将在下一个DataReceived事件中读取

我已经做了一个简短的程序,只测试串行端口。它显示了完全相同的结果。此外,我只有一个设备与测试连接。 设备发送的数据由10个字节组成。值为251,20(6个数据字节)、校验和lo、校验和hi

前两个字节和后两个字节永远无法达到26的值,只有数据字节才能做到这一点

进口:

Imports System.IO.Ports
Imports System.Text
变量:

Dim WithEvents SP_TestCom As SerialPort
Public DataArray() As Byte
潜艇:

我有一个主窗体,有两个按钮和一个计时器。按钮用于打开和关闭端口。计时器读取数据数组

我试过几种阅读方法

  • 直接读入数组
  • 分别读取每个字节
  • 读入字符串,然后将其转换为字节数组
我还尝试了不同的编码。虽然我不确定这是否会有任何影响

  • ASCII码
  • 统一码
  • UTF
所有的错误都是一样的

我可以忽略任何包含字节值26的消息来绕过错误。在我的应用程序的其余部分,这至少不会给我带来奇怪的结果,但它不是完美的解决方案

有人知道问题可能是什么吗

编辑:

那是一笔相当麻烦的财产。是的,26是一个神奇的数字。它是Ctrl+Z,默认的文件结束字符。可追溯到石器时代,不幸的是它无法改变

这对DataReceived事件处理程序很重要,它将额外触发一次来告诉您Eof。这就搞乱了你的逻辑,BytesToRead的值是不可预测的。你必须迅速离开,就像这样:

Private Sub SP_TestCom_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP_TestCom.DataReceived
    If e.EventType <> SerialData.Chars Then Return
    '' etc...
End Sub
Private Sub SP_TestCom_DataReceived(ByVal sender作为对象,ByVal e作为System.IO.Ports.SerialDataReceivedEventArgs)处理SP_TestCom.DataReceived
如果e.EventType SerialData.Chars,则返回
”“等等。。。
端接头

这不是唯一的问题。您现在可以保证ReceivedBytes至少为10。确保实际将10传递给Read()方法。但你不知道你会得到哪10个。例如,它可以是前一个数据包的4个字节和下一个数据包的6个字节。除非你非常小心地控制启动顺序,否则这不会很好地工作。该设备必须在程序启动后打开,这样您才能硬保证收到的第一个字节是数据包的第一个字节。如果必须向设备发送显式命令才能开始发送,则可能会起作用

或者,您可能需要通过一个特殊的字节值来检测数据包的开头,比如在您的示例中为251。然后,通过读取单个字节进行同步,丢弃一个字节直到得到251。如果ReceivedBytestThreshold>1,则无法执行此操作

使用ErrorReceived事件也是非常非常重要的。溢出错误会发生,特别是在没有握手的情况下,发生时必须重新同步

您还需要注意如何处理数据包。如果无法在DataReceived事件处理程序中执行此操作,则需要一个线程安全队列以确保没有数据丢失

那是一笔相当麻烦的财产。是的,26是一个神奇的数字。它是Ctrl+Z,默认的文件结束字符。可追溯到石器时代,不幸的是它无法改变

这对DataReceived事件处理程序很重要,它将额外触发一次来告诉您Eof。这就搞乱了你的逻辑,BytesToRead的值是不可预测的。你必须迅速离开,就像这样:

Private Sub SP_TestCom_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP_TestCom.DataReceived
    If e.EventType <> SerialData.Chars Then Return
    '' etc...
End Sub
Private Sub SP_TestCom_DataReceived(ByVal sender作为对象,ByVal e作为System.IO.Ports.SerialDataReceivedEventArgs)处理SP_TestCom.DataReceived
如果e.EventType SerialData.Chars,则返回
”“等等。。。
端接头

这不是唯一的问题。您现在可以保证ReceivedBytes至少为10。确保实际将10传递给Read()方法。但你不知道你会得到哪10个。例如,它可以是前一个数据包的4个字节和下一个数据包的6个字节。除非你非常小心地控制启动顺序,否则这不会很好地工作。该设备必须在程序启动后打开,这样您才能硬保证收到的第一个字节是数据包的第一个字节。如果必须向设备发送显式命令才能开始发送,则可能会起作用

或者,您可能需要通过一个特殊的字节值来检测数据包的开头,比如在您的示例中为251。然后,通过读取单个字节进行同步,丢弃一个字节直到得到251。如果ReceivedBytestThreshold>1,则无法执行此操作

使用ErrorReceived事件也是非常非常重要的。溢出错误会发生,特别是在没有握手的情况下,发生时必须重新同步


您还需要注意如何处理数据包。如果无法在DataReceived事件处理程序中执行此操作,则需要一个线程安全队列以确保没有数据丢失。

26是一个神奇的值。它是Ctrl+Z,文件结尾字符。它使您的DataReceived事件多触发一次,这次使用e.EventType=SerialData.Eof。非常有用,可以帮助您诊断代码中的错误。Array.Copy()语句不可能是正确的。啊,我想我明白了。我没有想到会再次引发datareceived事件。我会看看我是否能捕捉到这一点,这样我就能毫无问题地读取所有数据。对于Array.Copy(),它会将源数组DataArray_Temp复制到实际数组Da
   SP_TestCom.ReceivedBytesThreshold = 10
Private Sub SP_TestCom_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP_TestCom.DataReceived
    If e.EventType <> SerialData.Chars Then Return
    '' etc...
End Sub