While not for this particular device, this document discusses a device that uses the same RS232 communication protocol and recommends the following SerialPort settings:
- Baud rate: 115200
- DataBits: 8
- StopBits: 1
- Parity: None
- No flow control
Note: Minimum baud rate is 57600.
According to this document
2.1 Message Grammar:
Each HL7 message is composed of segments that end with <CR>
3 Communication Process and Message Example:
A message of HL7 protocol is the format of: <SB> ddddd <EB><CR>
ASCII value (HEX)
<SB> (start of message): 0B (VT - vertical tab)
<EB> (end of message): 1C (FS - file separator)
<CR> (carriage return) 0D (carriage return)
In the code below, I'll show how to use a buffer to collect data when "start of message" is received (HEX: 0B) and fill the buffer until "end of message" (HEX: 1C) followed by a carriage return (HEX: 0D) is received - at which point we'll raise an event and/or output the data.
For testing, we'll also write the data to a file in the Documents folder - this file is deleted each time the program starts so that only data from the current execution of the program is contained in the file. Each byte of data is output as a 2-digit hexadecimal value which allows us to see if a value is a control character.
The following may be helpful for interpreting the values:
Create a class (name: HelperSerialPort.vb)
HelperSerialPort.vb
Note: The code in method Port_DataReceived
(within the if-elseif
statements) is untested - I don't have the particular device that you're using to be able to test it.
'(.NET Framework) - Add reference: Project => Add Reference => Assemblies => System.Management
'add using statement: Using System.Management;
'
'For >= .NET 5, install NuGet Package: System.IO.Ports and System.Management
'add Imports statements: Imports System.IO.Ports; Imports System.Management;
'
'
Imports System.Management
Imports System.IO.Ports
'specify valid baud rates
Public Enum PortBaudRate As Integer
Baud57600 = 57600
Baud76800 = 76800
Baud115200 = 115200
End Enum
Public Class HelperSerialPort
Implements IDisposable
Private Const BufferSize As Integer = 4096 'this value may need to be changed
Private Port As SerialPort = Nothing
Private BytesReadMessage As Integer = 0 'used to hold message bytes read
Private Buffer(BufferSize) As Byte 'used to hold data
Private Filename As String = Nothing
Private IsMessage As Boolean = False
'events that can be subscribed to
Public Event DataReceived(ByVal sender As Object, ByVal data As String)
Public Event ErrorReceived(ByVal sender As Object, ByVal errMsg As String)
Sub New()
'set value
'data will be written to this file for testing
Filename = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Mindray BS200.txt")
If Not String.IsNullOrEmpty(Filename) AndAlso System.IO.File.Exists(Filename) Then
'delete existing file
System.IO.File.Delete(Filename)
End If
System.Diagnostics.Debug.WriteLine("Filename: '" & Filename & "'")
End Sub
Public Function Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud115200) As String
Dim errMsg As String = String.Empty
Dim portName As String = String.Empty
Dim result As String = String.Empty
If String.IsNullOrEmpty(comPort) Then
errMsg = "COM port not selected"
Throw New Exception(errMsg)
End If
Try
If Port Is Nothing Then
'create new instance
Port = New SerialPort(comPort)
'subscribe to events (add event handlers)
AddHandler Port.DataReceived, AddressOf Port_DataReceived
AddHandler Port.ErrorReceived, AddressOf Port_ErrorReceived
End If
If Not Port.IsOpen Then
'set properties
Port.BaudRate = baudRate
Port.Handshake = Handshake.None
'if parity is even or odd, then set DataBits = 7
'if parity is none, set DataBits = 8
Port.Parity = Parity.None
Port.DataBits = 8
Port.StopBits = StopBits.One
'Port.ReadTimeout = 500 'this value may need to be adjusted
Port.WriteTimeout = 500 'this value may need to be adjusted
Port.DtrEnable = True 'enable Data Terminal Ready
'Port.RtsEnable = True 'enable Request to Send
'Port.DiscardNull = True
'Port.ReceivedBytesThreshold = 1 'number of bytes that causes 'DataReceived' event to be raised; default is 1
'open port
Port.Open()
result = "Status: Connected"
Else
result = "Status: Already Connected"
End If
Catch ex As System.IO.IOException
errMsg = "Error: " & ex.Message
result = errMsg 'set value
Debug.WriteLine(errMsg)
Dispose()
Catch ex As Exception
errMsg = "Error: " & ex.Message
result = errMsg 'set value
Debug.WriteLine(errMsg)
Throw ex
End Try
Debug.WriteLine(result)
Return result
End Function
Public Function Disconnect() As String
Dispose()
Return "Status: Disconnected"
End Function
Public Sub Dispose() Implements System.IDisposable.Dispose
If Port IsNot Nothing Then
'unsubscribe from events (remove event handlers)
RemoveHandler Port.DataReceived, AddressOf Port_DataReceived
RemoveHandler Port.ErrorReceived, AddressOf Port_ErrorReceived
Port.Dispose()
Port = Nothing
Else
Debug.WriteLine("Info: Port is null")
End If
End Sub
Public Function IsPortOpen() As Boolean
If Port IsNot Nothing Then
If Port.IsOpen Then
Return True
Else
Try
Port.Dispose()
Catch ex As Exception
'do nothing
Debug.WriteLine("Error (IsPortOpen): " & ex.Message)
End Try
End If
Port = Nothing
System.GC.Collect()
System.GC.Collect()
End If
Return False
End Function
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
'ToDo: add desired code
Dim bytesRead As Integer = 0
Dim bytesToRead As Integer = 1
Dim errMsg As String = String.Empty
'read SerialPort data
Do
'read 1 byte at a time
bytesRead = Port.Read(Buffer, BytesReadMessage, bytesToRead)
'when <SB> (HEX: 0B) is received, remove all existing data from buffer
'this will result in the buffer only containing our desired data.
'when <EB> (HEX: 1C) is received followed by <CR> (HEX: 0D),
'this is the end of the message, so we'll send the message and/or display it.
'Buffer(BytesReadMessage) contains the last byte of data that was read
'
If Buffer(BytesReadMessage) = &HB Then
'0x0B - VT (vertical tab); in the documentation this is '<SB>' - start of message
System.Diagnostics.Debug.WriteLine("<SB> (start of message)")
'remove existing data (get ready for new message)
Array.Clear(Buffer, 0, Buffer.Length)
're-initialize to -1. It's incremented below which will result in the value being 0
BytesReadMessage = -1
'set value - start saving data to the buffer
IsMessage = True
ElseIf IsMessage AndAlso Buffer(BytesReadMessage) = &HD AndAlso Buffer(BytesReadMessage - 1) = &H1C Then
'0x1C - FS (file separator); in the documentation this is '<EB>' - end of message
'0x0D - CR (carriage return); in the documentation this is '<CR>'
System.Diagnostics.Debug.WriteLine("<EB> (end of message)")
'raise event to send data
SendData(Buffer)
'set value - stop saving data to the buffer
IsMessage = False
ElseIf Not IsMessage Then
'for debugging/testing, display non-message data
System.Diagnostics.Debug.WriteLine("Non-message data: " & Buffer(BytesReadMessage).ToString("X2"))
End If
'set value
BytesReadMessage += bytesRead
Debug.WriteLine("Info: BytesReadMessage: " & BytesReadMessage.ToString() & " bytesRead: " & bytesRead.ToString() & " Port.BytesToRead: " & Port.BytesToRead.ToString())
Loop While (Port.BytesToRead > 0)
Debug.WriteLine(String.Format("{0}---------------------------{0}", System.Environment.NewLine))
End Sub
Private Sub Port_ErrorReceived(ByVal sender As Object, ByVal e As SerialErrorReceivedEventArgs)
'ToDo: add desired code
Dim errMsg As String = e.EventType.ToString()
Debug.WriteLine("Port_ErrorReceived: " & errMsg)
'raise event
RaiseEvent ErrorReceived(Me, errMsg)
End Sub
Public Sub SendData(buffer() As Byte)
'ToDo: modify the code below and/or add desired code
'convert to a string that's human-readable
Dim data As String = String.Empty
If buffer IsNot Nothing Then
For i As Integer = 0 To BytesReadMessage Step 1
If Not String.IsNullOrEmpty(data) Then
data += " " 'append space
End If
'for testing, convert to a 2-digit HEX value
data += buffer(i).ToString("X2")
Next
'add newline
data += System.Environment.NewLine
End If
System.Diagnostics.Debug.WriteLine("data: " & data)
'for testing save to file
If Not String.IsNullOrEmpty(Filename) Then
'append data to file
System.IO.File.AppendAllText(Filename, data)
End If
'raise event
RaiseEvent DataReceived(Me, data)
'Note: "When receiving the message, the LIS (Laboratory Information Management System) host first judges the legality and type of the message and then replies accordingly."
'ToDo: A response needs to be sent for each message received (see documentation for information on how to create the appropriate message - "3 Communication Process and Message Example")
End Sub
Public Sub WriteToSerialPort(ByVal data As String)
Dim errMsg As String = String.Empty
Try
If Port.IsOpen Then
'convert string to Byte array
Dim hexArr As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
For Each hexVal As Byte In hexArr
'convert byte to byte array
Dim tempArr As Byte() = New Byte() {hexVal}
'write
Port.Write(tempArr, 0, 1)
'add 1 ms delay before writing next byte
System.Threading.Thread.Sleep(1)
Next
Else
errMsg = "Error: Port is not open. Please open the connection and try again."
Debug.WriteLine(errMsg)
Throw New Exception(errMsg)
End If
Catch ex As Exception
errMsg = "Error: " & ex.Message
Debug.WriteLine(errMsg)
Throw ex
End Try
End Sub
End Class
Below is an alternative version of method Port_DataReceived
that uses ReadExisting()
instead - however, it may not work in your situation.
Port_DataReceived (version that uses ReadExisting):
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
'ToDo: add desired code
'read SerialPort data
Dim data As String = String.Empty
data = Port.ReadExisting()
'data = Port.ReadLine
Debug.WriteLine("Port_DataReceived: " & data)
'raise event
RaiseEvent DataReceived(Me, data)
End Sub
Form1:
- Add a Button (name: btnConnectDisconnect)
- Double-click the button to add the event handler
- Add a RichTextBox (name: RichTextBox1)

Form1.vb
Note: In the code below, you'll need to update helper.Connect("COM1")
with the correct COM port.
Public Class Form1
Private helper As HelperSerialPort = New HelperSerialPort()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Disconnect()
If helper IsNot Nothing Then
'unsubscribe from event(s)
RemoveHandler helper.DataReceived, AddressOf Helper_DataReceived
RemoveHandler helper.ErrorReceived, AddressOf Helper_ErrorReceived
helper.Dispose()
helper = Nothing
End If
End Sub
Private Sub btnConnectDisconnect_Click(sender As Object, e As EventArgs) Handles btnConnectDisconnect.Click
If helper Is Nothing Then
'create new instance
helper = New HelperSerialPort()
End If
If btnConnectDisconnect.Text = "Connect" Then
'clear existing data
RichTextBox1.Clear()
'ToDo: change to your desired COM port
helper.Connect("COM1")
'subscribe to event(s)
AddHandler helper.DataReceived, AddressOf Helper_DataReceived
AddHandler helper.ErrorReceived, AddressOf Helper_ErrorReceived
'set text
btnConnectDisconnect.Text = "Disconnect"
btnConnectDisconnect.Refresh()
Else
Disconnect()
'set text
btnConnectDisconnect.Text = "Connect"
btnConnectDisconnect.Refresh()
End If
End Sub
Private Sub Helper_DataReceived(ByVal sender As Object, ByVal data As String)
'ToDo: add desired code
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss") & " - Helper_DataReceived: " & data)
'append data to RichTextBox
RichTextBox1.Invoke(New MethodInvoker(Sub()
RichTextBox1.AppendText(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff") & " - " & data)
End Sub))
End Sub
Private Sub Helper_ErrorReceived(ByVal sender As Object, ByVal errMsg As String)
'ToDo: add desired code
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss") & " - Helper_ErrorReceived: " & errMsg)
'append error message to RichTextBox
RichTextBox1.Invoke(New MethodInvoker(Sub()
RichTextBox1.AppendText(errMsg)
End Sub))
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
Disconnect()
End Sub
End Class
Resources: