|
-
Jan 25th, 2011, 02:46 AM
#1
Thread Starter
Lively Member
[RESOLVED] Handle multiple COM ports using same AddressOf sub
I've got my serial/com port code working ok using the standard Port.DataReceived handler:
Code:
AddHandler Port.DataReceived, AddressOf port_DataReceived
I now want to be able to handle multiple COM ports. Do I have to create multiple copies of the handler sub or is there a way the handler sub can tell which COM port it was called for?
Last edited by consciouspnm; Jan 25th, 2011 at 01:27 PM.
-
Jan 25th, 2011, 01:15 PM
#2
Fanatic Member
Re: Handle multiple COM ports
Hi,
I generally use WithEvent syntax, and if I need a shared DataReceived handler, I simply add to the Handles clause.
However, you also can do it with AddHandler. Here is some "simple-minded" code. I have three serial ports on my computer that are active Com3 and Com7 are connected together using a null modem, so that the corresponding command button sends data to the other. Com13 is a GPS receiver, which sends data continuously.
The SerialPort_Data_DataReceived delegate receives data from each instance and identifies which port generated that event. You then can add code to actually process the data received.
Naturally, such a shared approach is appropriate only where the data format from each port is identical, and other serial port coding requirement still apply.
Code:
Public Class Form1
Private SerialPort1 As New System.IO.Ports.SerialPort
Private SerialPort2 As New System.IO.Ports.SerialPort
Private SerialPort3 As New System.IO.Ports.SerialPort
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With SerialPort1
.PortName = "Com3"
.BaudRate = 4800
.Open()
AddHandler SerialPort1.DataReceived, AddressOf SerialportX_DataReceived
End With
With SerialPort2
.PortName = "Com7"
.BaudRate = 4800
.Open()
AddHandler SerialPort2.DataReceived, AddressOf SerialportX_DataReceived
End With
With SerialPort3
.PortName = "Com13"
.BaudRate = 4800
.Open()
AddHandler SerialPort3.DataReceived, AddressOf SerialportX_DataReceived
End With
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SerialPort1.Write("SerialPort1" & vbCrLf)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
SerialPort2.Write("SerialPort2" & vbCrLf)
End Sub
Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim SerialPort As System.IO.Ports.SerialPort = sender
Debug.Print(SerialPort.PortName)
Dim Buffer As String = SerialPort.ReadExisting
Debug.Print(Buffer)
End Sub
End Class
Naturally, you don't want to do what I've done and simply display receive data in the Immediate Window. You will want to do something more interesting.
Dick
Richard Grier, Consultant, Hard & Software
Microsoft MVP (Visual Basic)
-
Jan 25th, 2011, 01:32 PM
#3
Thread Starter
Lively Member
Re: Handle multiple COM ports using same AddressOf sub
Code:
Dim SerialPort As System.IO.Ports.SerialPort = sender
Debug.Print(SerialPort.PortName)
Thanks, that's the bit I was missing. Intellisense wasn't offering any suggestions for what sender could be used for!
-
Jan 25th, 2011, 01:48 PM
#4
Fanatic Member
Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub
Hi,
sender is an Object, so Intellisense cannot be too detailed. You just have to "know, (or ask)."
BTW, there is a more flexible approach, that may not be obvious, for creating an arbitrarily large number of serial ports that share the same DataReceived event handler. This involves a little more code, but the port creation can be done dynamically; just move the port creation code to a routine that is called, "as needed."
Code:
Dim SerialPortCollection As New Collection
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim SerialPort As System.IO.Ports.SerialPort
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com3"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com7"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com13"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com3")
SerialPort.Write("SerialPort1" & vbCrLf)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com7")
SerialPort.Write("SerialPort2" & vbCrLf)
End Sub
Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim SerialPort As System.IO.Ports.SerialPort = sender
Debug.Print(SerialPort.PortName)
Dim Buffer As String = SerialPort.ReadExisting
Debug.Print(Buffer)
End Sub
Richard Grier, Consultant, Hard & Software
Microsoft MVP (Visual Basic)
-
Mar 5th, 2016, 02:32 AM
#5
New Member
Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub
 Originally Posted by DickGrier
Hi,
sender is an Object, so Intellisense cannot be too detailed. You just have to "know, (or ask)."
BTW, there is a more flexible approach, that may not be obvious, for creating an arbitrarily large number of serial ports that share the same DataReceived event handler. This involves a little more code, but the port creation can be done dynamically; just move the port creation code to a routine that is called, "as needed."
Code:
Dim SerialPortCollection As New Collection
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim SerialPort As System.IO.Ports.SerialPort
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com3"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com7"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
SerialPort = New System.IO.Ports.SerialPort
With SerialPort
.PortName = "Com13"
.BaudRate = 4800
.Open()
SerialPortCollection.Add(SerialPort, SerialPort.PortName)
AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
End With
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com3")
SerialPort.Write("SerialPort1" & vbCrLf)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com7")
SerialPort.Write("SerialPort2" & vbCrLf)
End Sub
Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim SerialPort As System.IO.Ports.SerialPort = sender
Debug.Print(SerialPort.PortName)
Dim Buffer As String = SerialPort.ReadExisting
Debug.Print(Buffer)
End Sub
Hi
I Know this went out some time ago however I would like to use the method for a job I have. My problem is cross threading. In the final section of code where we are required to replace the debug with real output the debugger is not happy with me addressing textboxes from this location. It call a cross threading error, how can i get past this.
Regards
clive
-
Mar 7th, 2016, 04:35 PM
#6
Addicted Member
Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub
Hi, the DataReceived event handler runs on its own thread which is separate from the main UI thread.
To pass information from the DataReceived handler to a control on the UI without throwing a crossthread exception you will need to use a delegate.
You begin by declaring the delegate and creating the sub routine which represents the delegate, in this case writing text to a RichTextbox on the main UI.
Code:
Public Delegate Sub myDelegate(ByVal sData As String)
Private Sub Text_Out(ByVal sData As String)
RichTextBox1.AppendText(sData & " ")
End Sub
The above delegate accepts one simple string as a paramater, in the DataReceived handler you would use an Invoke to replace the Debug line.
Code:
Dim Buffer As String = SerialPort.ReadExisting
Me.BeginInvoke((New myDelegate(AddressOf Text_Out)), Buffer)
Delegates can be designed to accept multiple paramaters of same or different data types
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|