2017-06-06 40 views
1

我正在设计一个windows用户窗体,通过串行端口与微控制器进行交互。以多种形式使用串行端口的方法

GUI包含多个用户表单,它们将使用相同的串行端口。我研究了如何做到这一点,我发现了不同的想法。有些我不知道它是否适用于其他人,我不知道如何在代码中实现它。比方说,我有

Form1中:Start.vb 窗体2:Shield1.vb

1)我可以声明串口在启动窗体为:

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)第二替代:通过一个串口在开始形式的构造,然后将数据传递到其他形式,如在此后mentionned:Alternate Solution 1

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 2

是用C#这里右边的代码?我正在VB.net编写我的程序,但我可以把它作为参考。

哪个是初学者推荐的解决方案?如果您有其他建议或更正,您可以用小码写下来吗?

对于任何不明确或虚假使用的术语,我提前表示歉意。

谢谢你!

+0

那么这取决于你如何组织你的程序,如果你真的把在适当的类和模块的功能,并保持你的表格只用于启动这些功能/子你可以简单地把它作为一个参数,如果你的代码是不是最好的结构化,那么它可能会更好地使用模块aproach – Mederic

+0

这实际上是我在VB网络中的第一个项目,我试图用最好的结构来学习最佳实践技巧。所以我正在尝试与类。我的一个大问题实际上是解决方案的实现,因为我似乎在一些初学者中很欣赏它。你能看看我在上次回答中转换的单身课程吗?谢谢! –

回答

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多年的设计模式,当您只需要一个对象副本时仍然可以工作。

+0

感谢您的回复。是的,sigleton类解决方案似乎是最好的。我是初学者,非常感谢你的信息。可以请看看我的下一篇文章,我找到了一个C#类的例子,并使用代码转换器将其转换为VB.net?你能告诉我,如果代码是正确的?谢谢! –

+0

让我们在开始另一个之前完成这个问题,如果你愿意的话。或者只是编辑这一个,因为我可能无法轻松找到你的下一个问题。 – TomServo

+0

哦,我的意思是这是同一个问题。我只是在这里发布它作为第二个答案和一个建议。 –

0

我发现串口sigleton C#类的这个非常有用的例子: C# Singleton Example

由于我使用的码转换器有它在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 
+0

嗯,我无法检查或测试这个给你,但乍一看它看起来好像你已经把Singleton的东西翻译成了正确的。我认为我的建议你现在走在正确的轨道上,它只会进行测试。 – TomServo