问题
我有一个在 Windows 上创建虚拟串行端口的 USB 设备。我正在使用 VB.Net 从端口写入和读取。我的设备以特定大小的字节集响应,但我发现 SerialPort.Read(byte-array,offset,number-bytes) 不会返回完整的数字字节,但它也不会超时或生成异常。重复调用会返回额外的片段(最多需要 3 次调用)。我不明白为什么这种读取方法的行为方式如此?它是否认为请求的字节数只是一个建议?:-)。我希望它会等待完成整个请求,除非它首先超时。
使用 pySerial 的 Python 代码没有同样的问题。
那么,我在这里做错了什么?我期待太多了吗?
一些场景是:
- 我向端口写了一个命令,并期望得到 4 个字节的响应。我先得到 1 个字节,然后在随后的调用中得到 3 个字节。
- 我写了一个命令并期望 21120 字节作为响应。在从端口读取的 3 次调用中,我得到 1、12671 和 8448 字节。
以下是我的代码的一些摘录:
Private Sub SetupVirtualSerialPort()
Dim portName As String = "COM" + (m_DeviceContext * -1).ToString
Const baud As Int32 = 9600 '7680000
Const parity As Parity = parity.None
Const databits As Int32 = 8
Const stopbits As StopBits = stopbits.One
m_SerialPort = New SerialPort(portName, baud, parity, databits, stopbits)
m_SerialPort.WriteTimeout = VSPtimeout
m_SerialPort.ReadTimeout = VSPtimeout
m_SerialPort.ReadBufferSize = 2 * RETURN_BUFFER_SIZE
m_SerialPort.WriteBufferSize = 2 * COMMAND_BUFFER_SIZE
m_SerialPort.Open()
' Register event handlers
AddHandler m_SerialPort.ErrorReceived, AddressOf m_DriverInterface.Handle_VSP_Error
End Sub
Public Function WriteReadVSPort(ByVal commandLength As Int32, ByVal returnLength As Int32) As Int32
Const RetryLimit As Int32 = 5
Dim NumberRetries As Int32 = 0
Dim Offset As Int32 = 0
Dim ExceptionOccurred As Boolean = False
Dim NumberBytes As Int32 = 0
Try ' Writing
m_SerialPort.Write(m_CommandBuffer, 0, commandLength)
Catch exc As InvalidOperationException
MessageBox.Show("InvalidOperationException", Application.ProductName)
ExceptionOccurred = True
Catch exc As TimeoutException
MessageBox.Show("TimeoutException", Application.ProductName)
ExceptionOccurred = True
End Try
If Not ExceptionOccurred Then
Try ' Reading
' Working around a problem here: reads are returning fewer
' bytes than requested, though not signalling a timeout exception.
' Therefore, we retry if we got fewer bytes than expected, up to five times.
While NumberRetries < RetryLimit And returnLength > Offset
NumberBytes = m_SerialPort.Read(m_ReturnBytes, Offset, returnLength - Offset)
Offset += NumberBytes
NumberRetries += 1
If returnLength <> NumberBytes Then
System.Diagnostics.Debug.Print("Number of bytes read (" & NumberBytes &
") not what was requested (" & returnLength & "). Accumulated " & Offset)
End If
End While
Catch exc As InvalidOperationException
MessageBox.Show("InvalidOperationException", Application.ProductName)
ExceptionOccurred = True
Catch exc As TimeoutException
MessageBox.Show("TimeoutException", Application.ProductName)
ExceptionOccurred = True
End Try
If ExceptionOccurred Then
Return 1
Else
Return 0
End If
End Function
谢谢你。