问题描述
大家晚上好,我一直在开发一个通过串口读取余额的应用程序很长时间了,经过很长时间只是尝试读取数据,我很高兴得到了结果,但数据不同步,更改重量需要不确定的时间,处理数据时会删除多余的字符,因为秤发送的数据如下:ww0000.00kg
,经过一些更改后,我设法使它变成00.00kg
。重量必须实时同步:
它应该是这样工作的,当放置重量时,秤必须是它的值,例如13.75kg
,然后打印出来,然后在不到3秒的时间内移除重量并恢复正常(00.00kg
)。
编码:
Dim decWeightReading As Decimal, strScaleCommand As String
Dim strSerialData As String
Dim strSerialDataNew As String
Dim strFirstData As String
Dim cnt As Integer
Dim diffDate As TimeSpan
Dim initRunning As Integer
Dim IntWeightReading As Integer
Dim DecWeightReadingLast As Decimal
Dim datetime1 As Date, datetime2 As Date
表单加载:
Private Sub Menufrm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SerialPort1.Open()
Timer1.Start()
End Sub
TickTimer:
Private Sub TickTimer2()
decWeightReading = CDec("0.000")
strScaleCommand = "IP" + vbCrLf
strFirstData = ""
SerialPort1.WriteLine(strScaleCommand)
strSerialData = SerialPort1.ReadLine
strSerialDataNew = ""
cnt = 0
Do Until cnt = 10
SerialPort1.WriteLine(strScaleCommand)
strSerialDataNew = SerialPort1.ReadLine
If strSerialDataNew = strSerialData Then
cnt = cnt + 1
Else
strSerialData = strSerialDataNew
strSerialDataNew = ""
cnt = 0
End If
datetime2 = DateTime.Now
diffDate = datetime2.Subtract(datetime1)
Loop
End Sub
时间勾选并修剪ww00:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
TickTimer2()
Dim header As String = strSerialData
strSerialData = (header)
Weight.Text = (strSerialData)
strSerialData.Trim({"w"c, "w"c, "0"c})
Weight.Text = (header.Trim({"w"c, "w"c, "0"c}))
结束订阅
我面临的另一个困难是,当从天平读取数据并打印到文本框中时,过程变得非常慢,甚至很难单击按钮或查看组合框中的值列表。
如果有人能帮上忙,我将不胜感激
推荐答案
下面显示如何使用SerialPort读取数据-它订阅DataReceired事件。在VB.NET中,订阅事件有两个不同的选项。
选项1(WithEvents)
Private WithEvents Port As SerialPort = Nothing
Public Function Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600) As String
Dim result As String = String.Empty
If Port Is Nothing Then
'create new instance
Port = New SerialPort(comPort)
End If
...
Return result
End Function
订阅Port.DataReceired事件:
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles Port.DataReceived
End Sub
选项2(AddHandler)
Private Port As SerialPort = Nothing
Public Function Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600) As String
Dim result As String = String.Empty
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
...
Return result
End Function
订阅Port.DataReceired事件:
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
End Sub
下面是创建使用SerialPort读取数据和必要代码的新Windows窗体(WinForms)项目的步骤。
创建WinForms项目
vs 2017:
打开Visual Studio 单击文件 选择新建 选择项目 展开已安装 展开Visual Basic 单击Windows桌面 选择Windows窗体App(.NET框架) 指定项目名称(名称:ReadSerialPort) 单击确定vs 2019:
打开Visual Studio 单击不带代码继续 单击文件 选择新建 选择项目 Visual Basic Windows桌面 单击Windows Forms App(.NET框架) 单击下一步 指定项目名称(名称:ReadSerialPort) 单击创建注意:从现在开始,VS 2017和VS 2019的流程相同。
向Form1添加一些控件
打开属性窗口
在VS菜单中,选择查看 选择属性窗口打开解决方案资源管理器
在VS菜单中,选择查看 选择解决方案资源管理器 在解决方案资源管理器中,双击Form1.vb打开设计器。将连接按钮添加到Form 1
在VS菜单中,选择查看 选择工具箱 选择按钮 单击Form1将该按钮添加到该表单 在属性窗口中,为";Button1";设置(名称):btnConnect;设置文本:连接 在属性窗口中,单击(事件)。双击单击将事件处理程序添加到Form1.vb将断开连接按钮添加到窗体1
在VS菜单中,选择查看 选择工具箱 选择按钮 单击Form1将该按钮添加到该表单 在"属性"窗口中,为";Button1";设置(名称):btn断开连接;设置文本:断开连接 在属性窗口中,单击(事件)。双击单击将事件处理程序添加到Form1.vb将文本框添加到Form1
在VS菜单中,选择查看 选择工具箱 选择文本框 单击Form1将该按钮添加到该表单向Form1添加加载事件处理程序
在属性窗口中,对于";Form1";,单击(事件)。双击加载将事件处理程序添加到Form1.vb将FormClosing事件处理程序添加到Form1
在属性窗口中,对于";Form1";,单击(事件)。双击窗体关闭将事件处理程序添加到Form1.vb添加类:HelperSerialPort
在VS菜单上,选择项目 选择添加类(名称:HelperSerialPort.vb)选项1(WithEvents)
HelperSerialPort.vb
Imports System.IO.Ports
Public Enum PortBaudRate As Integer
Baud1200 = 1200
Baud2400 = 2400
Baud4800 = 4800
Baud9600 = 9600
Baud14400 = 14400
Baud19200 = 19200
Baud28800 = 28800
Baud38400 = 38400
Baud56000 = 56000
Baud76800 = 76800
Baud115200 = 115200
End Enum
Public Class HelperSerialPort
Implements IDisposable
Private WithEvents Port As SerialPort = Nothing
'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()
End Sub
Public Function Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600) 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)
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.Even 'Even, None, Odd
Port.DataBits = 7
Port.StopBits = StopBits.One
Port.ReadTimeout = 200
Port.WriteTimeout = 50
Port.DtrEnable = True 'enable Data Terminal Ready
Port.RtsEnable = True 'enable Request to Send
'open port
Port.Open()
result = "Status: Connected"
Else
result = "Status: Already Connected"
End If
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 Sub Disconnect()
Dispose()
End Sub
Public Sub Dispose() Implements System.IDisposable.Dispose
If Port IsNot Nothing Then
Port.Dispose()
Port = Nothing
End If
End Sub
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles Port.DataReceived
'read SerialPort data
Dim data As String = String.Empty
data = Port.ReadExisting()
'data = Port.ReadLine
Debug.WriteLine("Data: " & data)
'raise event
RaiseEvent DataReceived(Me, data)
End Sub
Private Sub Port_ErrorReceived(ByVal sender As Object, ByVal e As SerialErrorReceivedEventArgs) Handles Port.ErrorReceived
Dim errMsg As String = e.EventType.ToString()
Debug.WriteLine("Error: " & errMsg)
'raise event
RaiseEvent ErrorReceived(Me, errMsg)
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
修改Form1.vb代码
在解决方案资源管理器中,右键单击Form1.vb 选择查看代码Form1.vb
Imports System.IO.Ports
Public Class Form1
Private WithEvents helper As HelperSerialPort = New HelperSerialPort
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'get port names
For Each portName In SerialPort.GetPortNames()
Debug.WriteLine("portName: " & portName)
Next
End Sub
Private Sub Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600)
If helper IsNot Nothing Then
Debug.WriteLine("comPort: " & comPort & " baudRate: " & baudRate.ToString())
helper.Connect(comPort, baudRate)
End If
End Sub
Private Sub Helper_DataReceived(ByVal sender As Object, ByVal data As String) Handles helper.DataReceived
Debug.WriteLine("Data: " & data)
'set value
Dim tempData As String = data
If tempData.StartsWith("ww") AndAlso tempData.EndsWith("kg") Then
tempData = tempData.Substring(2, data.Length - 4)
End If
'If tempData.StartsWith("ww") Then
'tempData = tempData.Substring(2)
'End If
'If tempData.EndsWith("kg") Then
'tempData = tempData.Substring(0, tempData.IndexOf("kg"))
'End If
'set text in TextBox
TextBox1.Invoke(New MethodInvoker(Sub()
TextBox1.Text = tempData
TextBox1.Refresh()
End Sub))
End Sub
Private Sub Helper_ErrorReceived(ByVal sender As Object, ByVal errMsg As String) Handles helper.ErrorReceived
Debug.WriteLine(errMsg)
End Sub
Private Sub Disconnect()
If helper IsNot Nothing Then
helper.Disconnect()
End If
End Sub
Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
Connect("COM1", PortBaudRate.Baud9600)
End Sub
Private Sub btnDisconnect_Click(sender As Object, e As EventArgs) Handles btnDisconnect.Click
Disconnect()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
'dispose
If helper IsNot Nothing Then
helper.Dispose()
End If
End Sub
End Class
选项2(AddHandler)
HelperSerialPort.vb
Imports System.IO.Ports
Public Enum PortBaudRate As Integer
Baud1200 = 1200
Baud2400 = 2400
Baud4800 = 4800
Baud9600 = 9600
Baud14400 = 14400
Baud19200 = 19200
Baud28800 = 28800
Baud38400 = 38400
Baud56000 = 56000
Baud76800 = 76800
Baud115200 = 115200
End Enum
Public Class HelperSerialPort
Implements IDisposable
Private Port As SerialPort = Nothing
Public Event DataReceived(ByVal sender As Object, ByVal data As String)
Public Event ErrorReceived(ByVal sender As Object, ByVal errMsg As String)
Sub New()
End Sub
Public Function Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600) 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
Debug.WriteLine("comPort: " & comPort)
Try
If Port Is Nothing Then
Debug.WriteLine("creating new instance of SerialPort")
'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
Debug.WriteLine("Port isn't open")
'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.Even 'Even, None, Odd
Port.DataBits = 7
Port.StopBits = StopBits.One
Port.ReadTimeout = 200
Port.WriteTimeout = 50
Port.DtrEnable = True 'enable Data Terminal Ready
Port.RtsEnable = True 'enable Request to Send
'open port
Port.Open()
result = "Status: Connected"
Else
result = "Status: Already Connected"
End If
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 Sub Disconnect()
Dispose()
End Sub
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
End If
End Sub
Private Sub Port_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
'read SerialPort data
Dim data As String = String.Empty
data = Port.ReadExisting()
'data = Port.ReadLine
Debug.WriteLine("Data: " & data)
'raise event
RaiseEvent DataReceived(Me, data)
End Sub
Private Sub Port_ErrorReceived(ByVal sender As Object, ByVal e As SerialErrorReceivedEventArgs)
Dim errMsg As String = e.EventType.ToString()
Debug.WriteLine("Error: " & errMsg)
'raise event
RaiseEvent ErrorReceived(Me, errMsg)
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
修改Form1.vb代码
在解决方案资源管理器中,右键单击Form1.vb 选择查看代码Form1.vb
Imports System.IO.Ports
Public Class Form1
Private helper As HelperSerialPort = Nothing
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'create new instance
helper = New HelperSerialPort()
'subscribe to events (add event handlers)
AddHandler helper.DataReceived, AddressOf Helper_DataReceived
AddHandler helper.ErrorReceived, AddressOf Helper_ErrorReceived
'get port names
For Each portName In SerialPort.GetPortNames()
Debug.WriteLine("portName: " & portName)
Next
End Sub
Private Sub Connect(ByVal comPort As String, ByVal Optional baudRate As PortBaudRate = PortBaudRate.Baud9600)
If helper IsNot Nothing Then
Debug.WriteLine("comPort: " & comPort & " baudRate: " & baudRate.ToString())
helper.Connect(comPort, baudRate)
End If
End Sub
Private Sub Helper_DataReceived(ByVal sender As Object, ByVal data As String)
Debug.WriteLine("Data: " & data)
'set value
Dim tempData As String = data
If tempData.StartsWith("ww") AndAlso tempData.EndsWith("kg") Then
tempData = tempData.Substring(2, data.Length - 4)
End If
'If tempData.StartsWith("ww") Then
'tempData = tempData.Substring(2)
'End If
'If tempData.EndsWith("kg") Then
'tempData = tempData.Substring(0, tempData.IndexOf("kg"))
'End If
'set text in TextBox
TextBox1.Invoke(New MethodInvoker(Sub()
TextBox1.Text = tempData
TextBox1.Refresh()
End Sub))
End Sub
Private Sub Helper_ErrorReceived(ByVal sender As Object, ByVal errMsg As String)
Debug.WriteLine(errMsg)
End Sub
Private Sub Disconnect()
If helper IsNot Nothing Then
helper.Disconnect()
End If
End Sub
Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
Connect("COM1", PortBaudRate.Baud9600)
End Sub
Private Sub btnDisconnect_Click(sender As Object, e As EventArgs) Handles btnDisconnect.Click
Disconnect()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
'dispose
If helper IsNot Nothing Then
helper.Dispose()
End If
End Sub
End Class
资源:
What does 'InvokeRequired' and 'Invoke' mean in .Net?