locked
Serial port (read and write)

    Question

  • Hello,

     

    I'm trying to send and receive data to and from a microcontroller (uc)  via the serial port.I send data to the uc by using a click event. It looks something like this:

     

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

    Using comPort As SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 9600)

    comPort.DtrEnable = True

    comPort.Write("0")

    End Using

    End Sub

     

    No problem so far. The uc reads the character "0".

     

    To receive data from the uc I use the DataReceived event and call the function below:

     

    Private Sub DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

    Dim ReceivedData As String

     

    ReceivedData = SerialPort1.ReadLine

    MsgBox(ReceivedData)

     

    End Sub

     

    But....the event will only be triggered if I open the port first using the function below:

     

    Private Sub OpenCom1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenCom.Click

    SerialPort1.Open()

    MsgBox("Port 1 opened")

    End Sub

     

    The problem is that when the port is opened I can not send data to uc anymore. I first have to close the port  (using SerialPort1.Close()) then send data to the uc end then open the port again to receive data drom the uc.

     

    Question:

     

    Is it possible to send and receive data with opening the com port once?

     

    I'm looking forward to your answer.

     

    With kind regards,

     

    Bas

     

     

    Saturday, December 01, 2007 7:27 PM

Answers

  • Hi Bas,

     

    Based on your post, your application can't write or read the serial port in this scenario. It is no problem to keep the serial port to open all time.

     

    In this scenario I think that your application maybe doesn't finish the reading operation. Here I use the chat application as the demo. It uses the serial port to communicate and keeps the serialport to open with properly reading and writing. We need to clearly finish the reading operation on the serial port. Also note that this event is running on a separate thread. We recommend that your application uses a delegate to update controls on the main thread. For more information about the serial port communication, read two articles: Communication on a serial port in NET 2.0 and Programming Serial Ports Using Visual Basic 2005. I put a button and two textboxs in the form.

    Code Block

    Imports System

    Imports System.IO.Ports

    Public Class Form1

    Private received As String = String.Empty

    Dim WithEvents port As SerialPort = New _

    System.IO.Ports.SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)

    Public Delegate Sub myDelegate()

    Public Sub updateTextBox()

    With TextBox2

    .Font = New Font("Garamond", 12.0!, FontStyle.Bold)

    received = port.ReadTo("!%")

    .AppendText(received)

    End With

    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As _

    System.EventArgs) Handles Me.Load

    CheckForIllegalCrossThreadCalls = False

    If port.IsOpen = False Then

    port.Open()

    End If

    End Sub

    Private Sub port_DataReceived(ByVal sender As Object, ByVal e As _

    System.IO.Ports.SerialDataReceivedEventArgs) Handles port.DataReceived

    TextBox1.Invoke(New myDelegate(AddressOf updateTextBox), New Object() {})

    received = String.Empty

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    If port.IsOpen = False Then

    port.Open()

    End If

    port.Write(TextBox1.Text & "!%")

    TextBox1.Text = ""

    End Sub

    Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing

    If port.IsOpen <> False Then

    port.Close()

    End If

    End Sub

    End Class

     

     


    Best regards,

    Riquel

    Wednesday, December 05, 2007 2:00 PM
  • Hi,

     

    Thank you for your reply.

     

    I think I know what i did wrong...

    I selected the the serialport from the toolbox AND i used the following code as well, so i used it twice .

     

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

    Using comPort As SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 9600)

    comPort.DtrEnable = True

    comPort.Write("0")

    End Using

    End Sub

     

    Greetz,

     

    Bas

     

     

     

    Wednesday, December 05, 2007 8:40 PM

All replies

  •  

    Hi,

    First, yes there is no problem to have the port open all the time. You maybe has problem with Readln? Maybe the uc do not send the expected end of line character? So you only get teh characters when closing?

     

    I use code like below, but it must be tailored for each particular device, since every device has its own special requirement.

     

    Hope it helps

     

    Regards

    Csaba

     

    Code Block

    Public Function GetRawDataStr(ByVal cmdStr As String) As String

    ' Avoid lot of strings that trigger garbage collection:

    Dim aStr As New System.Text.StringBuilder(500) ' Almemo may have long strings

    Try

    If Not ComPort.IsOpen Then ComPort.Open() ' May be blocked!

    For iRedundancy As Int32 = 1 To 3 ' redundant loop

    aStr.Length = 0

    ComPort.DiscardInBuffer() ' important to clean up

    ComPort.Write(cmdStr)

    Delay_ms(30) ' works well with 10 ms initial delay but it takes 30 ms anyhow

    ' Wait until all chars are recieved! Chr(3) terminates

    ' Some Almemo firmware has a delay in the communication

    For iDelayRepeat As Int32 = 1 To 25 ' 300 better for real Almemo purpose

    If ComPort.BytesToRead > 0 Then ' YES, started to recieve chars!

    ' build up the string - BytesToRead will be set to zero

    aStr.Append(ComPort.ReadExisting)

    ' search within last 3 chars from end if last chars

    For indexEoM As Integer = aStr.Length - 1 To Math.Max(aStr.Length - 4, 0) Step -1

    If aStr(indexEoM) = Chr(3) Then Exit Try ' The Almemo terminator, End Of Message

    Next

    End If

    Delay_ms(5) ' iDelayRepeat x 5 ms max delay if no communication response

    Next

    Next

    Catch When Err.Number = 5

    ' Also time out & ' System.UnauthorizedAccessException, denied access right right = serial port is used!

    Catch ex As Exception

    MsgBox("ERROR Almemo.GetRawDataStr, Error #" & Err.Number & "; " & Err.Description)

    'Debug.Print("Recieved Length:" & aStr.Length & " " & aStr.ToString)

    Finally 'RETURN is forbidden here - but executed even when Exit try!

    GetRawDataStr = aStr.ToString

    End Try

    End Function

     

     

    Sunday, December 02, 2007 3:10 PM
  • Hi,

     

    Thank you for your reply.

     

    Reading is no problem (I think). If I open the port and the uc sends a string I will get a messagebox with the string.

    But if i send a string or character back to the uc, I get the message:"Access to the port 'COM1' is denied."

    I now first have to close the port, then send data to the uc and then open it again to enable the DataReceive event.

     

    What do I forget?

     

    Greetz,

     

    Bas

     


     

    Sunday, December 02, 2007 8:10 PM
  • Hi Bas,

     

    Based on your post, your application can't write or read the serial port in this scenario. It is no problem to keep the serial port to open all time.

     

    In this scenario I think that your application maybe doesn't finish the reading operation. Here I use the chat application as the demo. It uses the serial port to communicate and keeps the serialport to open with properly reading and writing. We need to clearly finish the reading operation on the serial port. Also note that this event is running on a separate thread. We recommend that your application uses a delegate to update controls on the main thread. For more information about the serial port communication, read two articles: Communication on a serial port in NET 2.0 and Programming Serial Ports Using Visual Basic 2005. I put a button and two textboxs in the form.

    Code Block

    Imports System

    Imports System.IO.Ports

    Public Class Form1

    Private received As String = String.Empty

    Dim WithEvents port As SerialPort = New _

    System.IO.Ports.SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)

    Public Delegate Sub myDelegate()

    Public Sub updateTextBox()

    With TextBox2

    .Font = New Font("Garamond", 12.0!, FontStyle.Bold)

    received = port.ReadTo("!%")

    .AppendText(received)

    End With

    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As _

    System.EventArgs) Handles Me.Load

    CheckForIllegalCrossThreadCalls = False

    If port.IsOpen = False Then

    port.Open()

    End If

    End Sub

    Private Sub port_DataReceived(ByVal sender As Object, ByVal e As _

    System.IO.Ports.SerialDataReceivedEventArgs) Handles port.DataReceived

    TextBox1.Invoke(New myDelegate(AddressOf updateTextBox), New Object() {})

    received = String.Empty

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    If port.IsOpen = False Then

    port.Open()

    End If

    port.Write(TextBox1.Text & "!%")

    TextBox1.Text = ""

    End Sub

    Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing

    If port.IsOpen <> False Then

    port.Close()

    End If

    End Sub

    End Class

     

     


    Best regards,

    Riquel

    Wednesday, December 05, 2007 2:00 PM
  • Hi,

     

    Thank you for your reply.

     

    I think I know what i did wrong...

    I selected the the serialport from the toolbox AND i used the following code as well, so i used it twice .

     

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

    Using comPort As SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 9600)

    comPort.DtrEnable = True

    comPort.Write("0")

    End Using

    End Sub

     

    Greetz,

     

    Bas

     

     

     

    Wednesday, December 05, 2007 8:40 PM