2017-06-06 52 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