如何将串口通信读入缓冲区并解析出完整的消息 [英] How to read serial port communication into buffer and parse out complete messages

查看:60
本文介绍了如何将串口通信读入缓冲区并解析出完整的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码从 com 端口读取值:

I am using the following code to read values from a com port:

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

这工作得很好,但它时不时地获取所有数据,并且返回结果是两个字符串而不是一个.

This works just fine, but every now and then it doesnt get all the data and in return results in two strings instead of just one.

一个例子是,如果 com 端口通过HELLO2YOU"这个词发送,它看起来像:

An example would be if the com port was sending over the word "HELLO2YOU" it was look like:

HEL
LO2YOU

HELLO2
YOU

如何在其中放置缓冲区以确保在显示之前读取了所有数据?

How can i place a buffer in there so that it makes sure it has all the data read before displaying it?

谢谢!

推荐答案

您必须将串行端口通信视为流数据.任何时候您接收数据时,您都必须预料到它可能是一条完整的消息、只是部分消息或多条消息.这完全取决于数据传入的速度以及您的应用程序能够从队列中读取的速度.因此,您认为需要缓冲区是正确的.但是,您可能还没有意识到,严格通过串行端口,无法知道每条消息的开始和结束位置.这必须通过发送方和接收方之间商定的协议来处理.例如,许多人使用标准的文本开始 (STX) 和文本结束 (ETX) 字符来表示每条消息发送的开始和结束.这样,当您收到数据时,您就可以知道何时收到了完整的消息.

You have to think of Serial Port communications as streaming data. Any time you receive data, you have to expect that it may be a complete message, only a partial message, or multiple messages. It all depends how fast the data is coming in and how fast you application is able to read from the queue. Therefore, you are right in thinking you need a buffer. However, what you may not be realizing yet, is that there is no way to know, strictly via, the Serial Port, where each message begins and ends. That has to be handled via some agreed upon protocol between the sender and the receiver. For instance, many people use the standard start-of-text (STX) and end-of-text (ETX) characters to indicate the beginning and ending of each message send. That way, when you receive the data, you can tell when you have received a complete message.

例如,如果您使用 STX 和 ETX 字符,您可以创建这样的类:

For instance, if you used STX and ETX characters, you could make a class like this:

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

我还应该提到,在通信协议中,通常有一个校验和字节,您可以通过它来确定消息在发送方和接收方之间的传输过程中是否被破坏.

I should also mention that, in communication protocols, it is typical to have a checksum byte by which you can determine if the message got corrupted during its transmission between the sender and the receiver.

这篇关于如何将串口通信读入缓冲区并解析出完整的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆