我正在设计一个windows userform,通过串口与微控制器进行交互。
GUI包含多个用户表单,这些用户表单将使用相同的串行端口。我研究了如何做到这一点,我发现了不同的想法。有些我不知道它是否适用于其他我不知道如何在代码中实现它。假设我有
Form1:Start.vb Form2:Shield1.vb
1)我可以将start userform中的串口声明为:
Public Shared SerialPort1 As New System.IO.Ports.SerialPort
并以其他形式使用它?
2)第一种选择:使用模块声明新的Serialport
Module Module1
Public WithEvents mySerialPort1 As New IO.Ports.SerialPort
Private Sub mySerialPort1_DataReceived(sender As Object, _
e As System.IO.Ports.SerialDataReceivedEventArgs) _
Handles mySerialPort1.DataReceived
End Sub
End Module
这种方法对吗?如果是,我如何在表格代码中使用它?如何在表单代码中包含DataReceived事件?
3)第二种选择:在开始表单中使用Serialport的构造函数,然后将数据传递给本文中提到的其他表单:
private void OnSetup(object sender, EventArgs e)
{
this.port = new SerialPort(...);
// TODO: initialize port
Form2 f2 = new Form2(this.port);
f2.Show();
Form3 f3 = new Form3(this.port);
f3.Show();
Form4 f4 = new Form4(this.port);
f4.Show();
}
那么活动还包括在内吗?我该如何使用它们?
4)第三种选择:使用类似于此解决方案中完成的静态类: Alternate Solution 1
用C#写的代码在这里吗?我正在VB.net中编写我的程序,但我可以将其作为参考。
对于初学者,推荐哪种解决方案?如果您有其他建议或更正,可以用小码编写吗?
我提前为任何歧义或错误使用的条款道歉。
谢谢!
答案 0 :(得分:1)
我会遵循“Singleton”设计模式,这样可以确保只创建一个类的一个实例。这是一个广为接受的类这样的模板:
Public NotInheritable Class MySerial
Private Shared ReadOnly _instance As New Lazy(Of MySerial)(Function() New
MySerial(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)
Private Sub New()
End Sub
Public Shared ReadOnly Property Instance() As MySerial
Get
Return _instance.Value
End Get
End Property
结束班
在New()
方法中,您应该根据需要设置串口。然后,无论您在何处使用该端口,都可以引用实例:
Dim singletonSerial As MySerial = MySerial.Instance
这是规范模式,用于确保您只有一个对象副本而无需使用静态类。这是一种可以追溯到20多年的设计模式,当您只需要一个对象的副本时,它仍然可以很好地工作。
答案 1 :(得分:0)
我发现这是一个非常有用的串口C#类的示例: C# Singleton Example
作为一名初学者,我使用了Code转换器在VB.Net中使用它。如果结果代码正确并且我可以使用它,你能告诉我吗?非常感谢!!
Imports System
Imports System.IO
Imports System.IO.Ports
Imports System.Threading
Namespace HeiswayiNrird.Singleton
Public NotInheritable Class SerialPortManager
Private Shared lazy As Lazy(Of SerialPortManager) = New Lazy(Of SerialPortManager)(() => { }, New SerialPortManager)
Public Shared ReadOnly Property Instance As SerialPortManager
Get
Return lazy.Value
End Get
End Property
Private _serialPort As SerialPort
Private _readThread As Thread
Private _keepReading As Boolean
Private Sub New()
MyBase.New
Me._serialPort = New SerialPort
Me._readThread = Nothing
Me._keepReading = false
End Sub
''' <summary>
''' Update the serial port status to the event subscriber
''' </summary>
Public Event OnStatusChanged As EventHandler(Of String)
''' <summary>
''' Update received data from the serial port to the event subscriber
''' </summary>
Public Event OnDataReceived As EventHandler(Of String)
''' <summary>
''' Update TRUE/FALSE for the serial port connection to the event subscriber
''' </summary>
Public Event OnSerialPortOpened As EventHandler(Of Boolean)
''' <summary>
''' Return TRUE if the serial port is currently connected
''' </summary>
Public ReadOnly Property IsOpen As Boolean
Get
Return Me._serialPort.IsOpen
End Get
End Property
''' <summary>
''' Open the serial port connection using basic serial port settings
''' </summary>
''' <param name="portname">COM1 / COM3 / COM4 / etc.</param>
''' <param name="baudrate">0 / 100 / 300 / 600 / 1200 / 2400 / 4800 / 9600 / 14400 / 19200 / 38400 / 56000 / 57600 / 115200 / 128000 / 256000</param>
''' <param name="parity">None / Odd / Even / Mark / Space</param>
''' <param name="databits">5 / 6 / 7 / 8</param>
''' <param name="stopbits">None / One / Two / OnePointFive</param>
''' <param name="handshake">None / XOnXOff / RequestToSend / RequestToSendXOnXOff</param>
Public Sub Open(Optional ByVal portname As String = "COM1", Optional ByVal baudrate As Integer = 9600, Optional ByVal parity As Parity = Parity.None, Optional ByVal databits As Integer = 8, Optional ByVal stopbits As StopBits = StopBits.One, Optional ByVal handshake As Handshake = Handshake.None)
Me.Close
Try
Me._serialPort.PortName = portname
Me._serialPort.BaudRate = baudrate
Me._serialPort.Parity = parity
Me._serialPort.DataBits = databits
Me._serialPort.StopBits = stopbits
Me._serialPort.Handshake = handshake
Me._serialPort.ReadTimeout = 50
Me._serialPort.WriteTimeout = 50
Me._serialPort.Open
Me.StartReading
Catch As IOException
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} does not exist.", portname))
End If
Catch As UnauthorizedAccessException
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} already in use.", portname))
End If
Catch ex As Exception
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, ("Error: " + ex.Message))
End If
End Try
If Me._serialPort.IsOpen Then
Dim sb As String = StopBits.None.ToString.Substring(0, 1)
Select Case (Me._serialPort.StopBits)
Case StopBits.One
sb = "1"
Case StopBits.OnePointFive
sb = "1.5"
Case StopBits.Two
sb = "2"
End Select
Dim p As String = Me._serialPort.Parity.ToString.Substring(0, 1)
Dim hs As String = "No Handshake"
'TODO: Warning!!!, inline IF is not supported ?
(Me._serialPort.Handshake = Handshake.None)
Me._serialPort.Handshake.ToString
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Connected to {0}: {1} bps, {2}{3}{4}, {5}.", Me._serialPort.PortName, Me._serialPort.BaudRate, Me._serialPort.DataBits, p, sb, hs))
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, true)
End If
Else
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} already in use.", portname))
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, false)
End If
End If
End Sub
''' <summary>
''' Close the serial port connection
''' </summary>
Public Sub Close()
Me.StopReading
Me._serialPort.Close
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, "Connection closed.")
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, false)
End If
End Sub
''' <summary>
''' Send/write string to the serial port
''' </summary>
''' <param name="message"></param>
Public Sub SendString(ByVal message As String)
If Me._serialPort.IsOpen Then
Try
Me._serialPort.Write(message)
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Message sent: {0}", message))
End If
Catch ex As Exception
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Failed to send string: {0}", ex.Message))
End If
End Try
End If
End Sub
Private Sub StartReading()
If Not Me._keepReading Then
Me._keepReading = true
Me._readThread = New Thread(ReadPort)
Me._readThread.Start
End If
End Sub
Private Sub StopReading()
If Me._keepReading Then
Me._keepReading = false
Me._readThread.Join
Me._readThread = Nothing
End If
End Sub
Private Sub ReadPort()
While Me._keepReading
If Me._serialPort.IsOpen Then
'byte[] readBuffer = new byte[_serialPort.ReadBufferSize + 1];
Try
'int count = _serialPort.Read(readBuffer, 0, _serialPort.ReadBufferSize);
'string data = Encoding.ASCII.GetString(readBuffer, 0, count);
Dim data As String = Me._serialPort.ReadLine
If (Not (OnDataReceived) Is Nothing) Then
OnDataReceived(Me, data)
End If
Catch As TimeoutException
End Try
Else
Dim waitTime As TimeSpan = New TimeSpan(0, 0, 0, 0, 50)
Thread.Sleep(waitTime)
End If
End While
End Sub
End Class
End Namespace