我有一个vb.net winforms应用程序,可以读取/写入连接到USB-RS485设备的多个设备的串行数据。该应用程序是用Visual Basic .NET 2008编写的,尽管我也尝试过.NET 2015。
几乎一切都运行良好,除非其中一个设备发送一个字节值为26的消息。然后我不确定究竟发生了什么但是在字节值26之后,读数似乎停止了。之后的所有数据都会在下一个DataReceived事件中读取。
我做了一个简短的程序来测试serialport。它显示完全相同。此外,我只有一个设备连接测试。 设备发送的数据由10个字节组成。值为251,20,(6个数据字节),校验和,校验和。
前两个和后两个字节永远不会达到26的值,它只是可以做到的数据字节。
进口:
Imports System.IO.Ports
Imports System.Text
变量:
Dim WithEvents SP_TestCom As SerialPort
Public DataArray() As Byte
潜艇:
Public Sub OpenCom()
If SP_TestCom.IsOpen Then
Exit Sub
End If
SP_TestCom.Open()
End Sub
Public Sub CloseCom()
If Not SP_TestCom.IsOpen Then
Exit Sub
End If
SP_TestCom.Close()
End Sub
Public Sub SendData(ByVal Data() As Byte)
Try
If SP_TestCom.IsOpen Then
SP_TestCom.Write(Data, 0, Data.Length)
End If
Catch ex As Exception
End Try
End Sub
Private Sub SP_TestCom_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP_TestCom.DataReceived
Try
If SP_TestCom.BytesToRead > 0 Then
Dim DataArray_Temp(SP_TestCom.BytesToRead + 1) As Byte
SP_TestCom.Read(DataArray_Temp, 0, SP_TestCom.BytesToRead)
Array.Copy(DataArray_Temp, DataArray, DataArray_Temp.Length)
End If
Catch ex As Exception
End Try
End Sub
我有一个带有两个按钮和一个计时器的主表单。按钮用于打开和关闭端口。计时器读取数据表
我尝试了几种阅读方法。
我也尝试了不同的编码。虽然我不确定它是否会产生任何影响。
All给出了同样的错误。
我可以通过忽略包含字节值26的任何消息来绕过错误。这至少不会在我的应用程序的其余部分给出奇怪的结果,但它不是完美的解决方案。
有没有人知道问题可能是什么?
编辑:
Public Sub InitSerial()
SP_TestCom = New SerialPort
SP_TestCom.PortName = "COM26"
SP_TestCom.ReadTimeout = 20
SP_TestCom.BaudRate = 19200
SP_TestCom.DataBits = 8
SP_TestCom.StopBits = StopBits.One
SP_TestCom.Parity = Parity.None
SP_TestCom.ReceivedBytesThreshold = 10
End Sub
答案 0 :(得分:4)
SP_TestCom.ReceivedBytesThreshold = 10
这是一个相当麻烦的财产。是的,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
不是该属性的唯一问题。您现在可以保证ReceivedBytes 至少 10.确保您实际将10传递给Read()方法。但是你不知道你会得到哪10个。例如,它可以是前一个数据包的4个字节和下一个数据包的6个字节。除非你非常小心地控制启动顺序,否则这样做不会很好。在程序启动后,必须打开设备,这样您才能确保收到的第一个字节是数据包的第一个字节。如果必须向设备发送显式命令以开始发送,则可以正常工作。
或者您可能需要通过特殊字节值检测数据包的开头,例如251。然后通过读取单个字节进行同步,将其丢弃,直到获得251.您不能使用ReceivedBytesThreshold&gt;来执行此操作。 1。
使用ErrorReceived事件也非常非常重要。发生溢出错误,尤其是在没有握手时,必须在发生错误时重新进行同步。
您还需要注意处理数据包的方式。如果你不能在DataReceived事件处理程序中这样做,那么你需要一个线程安全的队列来确保没有数据丢失。