How to read serial port communication to buffer and parse completed messages

I use 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 fine, but from time to time it does not receive all the data and as a result returns two rows instead of one.

For example, if the COM port sent the word "HELLO2YOU", it looked like this:

 HEL LO2YOU 

or

 HELLO2 YOU 

How can I place the buffer there to make sure that it all reads the data before displaying it?

Thanks!

+6
source share
2 answers

You should think of Serial Port connections as streaming data. Each time you receive data, you should expect that it can be a full message, only a partial message or several messages. It all depends on how fast the data arrives and how quickly you can read the application from the queue. Therefore, you are right in thinking that you need a buffer. However, what you may not yet realize is that there is no way to know, strictly through the serial port, where each message starts and ends. This must be processed according to an agreed protocol between the sender and the recipient. For example, many people use the standard start of text (STX) and end of text (ETX) characters to indicate the start and end of each message. That way, when you receive the data, you can find out when you received the full message.

For example, if you used the characters STX and ETX, you can 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 it is typical for communication protocols to have a checksum bike through which you can determine if a message has been damaged during transmission between the sender and the receiver.

+9
source

This is quite normal, serial ports are very slow devices. With bauds like 9600, and the machine doesn't clog too much, you only get one or two bytes from the port when using ReadExisting (). Debug.Print () prints the line terminator so that you see everything that was received, broken into pieces.

The easiest way to fix this is to use ReadLine (). This requires devices to send a special character at the end of the line that matches the value of the SerialPort.NewLine property. Which is pretty common, linear feed is a template.

If not, you will need a different buffering scheme.

+3
source

Source: https://habr.com/ru/post/920359/


All Articles