vb.net – 如何将串行端口通信读入缓冲区并解析出完整的消息
发布时间:2020-12-17 00:31:07 所属栏目:大数据 来源:网络整理
导读:我使用以下代码从COM端口读取值: Private port As New SerialPort("COM13",9600,Parity.None,8,StopBits.One)Private Sub port_DataReceived(ByVal sender As Object,ByVal e As SerialDataReceivedEventArgs) Debug.Print(port.ReadExisting())End SubPriv
我使用以下代码从COM端口读取值:
Private port As New SerialPort("COM13",9600,Parity.None,8,StopBits.One) Private Sub port_DataReceived(ByVal sender As Object,ByVal e As SerialDataReceivedEventArgs) Debug.Print(port.ReadExisting()) End Sub Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load AddHandler port.DataReceived,New SerialDataReceivedEventHandler(AddressOf port_DataReceived) port.Open() End Sub 这工作得很好,但是偶尔它不会获得所有数据,并且返回结果是两个字符串而不是一个. 一个例子是如果com端口发送单词“HELLO2YOU”,它看起来像: HEL LO2YOU 要么 HELLO2 YOU 如何在其中放置一个缓冲区,以确保在显示之前读取所有数据? 谢谢!
您必须将串行端口通信视为流数据.无论何时收到数据,您都必须预期它可能是完整的消息,只是部分消息或多条消息.这一切都取决于数据进入的速度以及应用程序从队列中读取的速度.因此,你认为你需要一个缓冲区是正确的.但是,您可能还没有意识到的是,没有办法严格通过串行端口来了解每条消息的开始和结束位置.这必须通过发送方和接收方之间达成一致的协议来处理.例如,许多人使用标准的文本开头(STX)和文本结束(ETX)字符来指示每个消息发送的开始和结束.这样,当您收到数据时,您可以知道何时收到完整的消息.
例如,如果您使用STX和ETX字符,则可以创建如下类: Public Class DataBuffer Private ReadOnly _startOfText As String = ASCII.GetChars(New Byte() {2}) Private ReadOnly _endOfText As String = ASCII.GetChars(New Byte() {4}) Public Event MessageReceived(ByVal message As String) Public Event DataIgnored(ByVal text As String) Private _buffer As StringBuilder = New StringBuilder Public Sub AppendText(ByVal text As String) _buffer.Append(text) While processBuffer(_buffer) End While End Sub Private Function processBuffer(ByVal buffer As StringBuilder) As Boolean Dim foundSomethingToProcess As Boolean = False Dim current As String = buffer.ToString() Dim stxPosition As Integer = current.IndexOf(_startOfText) Dim etxPosition As Integer = current.IndexOf(_endOfText) If (stxPosition >= 0) And (etxPosition >= 0) And (etxPosition > stxPosition) Then Dim messageText As String = current.Substring(0,etxPosition + 1) buffer.Remove(0,messageText.Length) If stxPosition > 0 Then RaiseEvent DataIgnored(messageText.Substring(0,stxPosition)) messageText = messageText.Substring(stxPosition) End If RaiseEvent MessageReceived(messageText) foundSomethingToProcess = True ElseIf (stxPosition = -1) And (current.Length <> 0) Then buffer.Remove(0,current.Length) RaiseEvent DataIgnored(current) foundSomethingToProcess = True End If Return foundSomethingToProcess End Function Public Sub Flush() If _buffer.Length <> 0 Then RaiseEvent DataIgnored(_buffer.ToString()) End If End Sub End Class 我还要提一下,在通信协议中,通常有一个校验和字节,通过它可以确定消息在发送方和接收方之间传输过程中是否被破坏. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |