flow control during serial communications

2.2k Views Asked by At

I have designed an application that communicates with an external device on my development box through a USB->serial adapter (Windows 7 64bit, VS2013, targeting .Net Framework 3.5 SP1). I also have a test box setup with a native serial port with Windows XP SP3 and .Net Framework 3.5 SP1. The external device communicates at 19200, N, 8, 1 and supports hardware flow control. I know the flow control works because when I initiate a report on the device, set flow control to none and manually create a checkbox to turn DTR on and off the device will pause when DTR is toggled off.

I'm having trouble making the hardware flow control work automatically through my Windows desktop application, however (Handshake.RequestToSend). If I leave handshaking set to None, communication is "usually" successful. Sometimes on the slower test box with the native serial port I believe the receive buffer is being overrun when requesting large amounts of data from the device, even though I've set a very large buffer and made the DataReceived routine as efficient as possible. I've tried various flow control settings in the driver itself with no effect. If I set handshaking to RequestToSend in my application communication appears to stall and the device never responds to my initial status request. I've tried various combinations of True/False with DtrEnable and RtsEnable to no avail. I've searched the internet for many hours and haven't seen anything that has so far helped. Here's some of my code:

  Private sbReceive_Extract As New StringBuilder 'Receive buffer

  Private WithEvents comPort As SerialPort

  Private bReady as Boolean = False 'data ready flag

  Private bExtract as Boolean = False 'type of data request

  Public Sub Status_Request()

    sbReceive_Extract.Length = 0 'clear buffer

    If Open_Port() = True

      comPort.DiscardInBuffer()
      comPort.DiscardOutBuffer()

      'Send status request to external serial device
      comPort.Write(Chr(27) & "?" & Chr(13))

      bExtract = False 'Just get status header this time    

      'Loop until device responds to request
      bReady = False
      Do Until bReady = True
        Application.DoEvents()
        'update an onscreen status label as buffer fills
        lblStatus.Text = "Buffer read: " & sbReceive_Extract.Length.ToString
      Loop

    End If

  End Sub


  Public Function Open_Port() As Boolean

      'return code for port open or closed
    Dim bReturnResult As Boolean = False

    If comPort Is Nothing Then
      comPort = New SerialPort
    End If

    Try
      With comPort
        .PortName = "COM1"       'comm port 1
        .BaudRate = 19200  'transfer speed
        .DataBits = 8       '8 bits
        .StopBits = StopBits.One
        .Parity = Parity.None
        .ReadBufferSize = 32768 '32768=size of buffer in bytes
        .ReadTimeout = SerialPort.InfiniteTimeout
        .Handshake = Handshake.RequestToSend 'works when set to none
        .DtrEnable = True 'tried both true/false
        .RtsEnable = True 'tried both true/false
        .Encoding = Encoding.Default
        .NewLine = Chr(13) '13=carriage return
        .ReceivedBytesThreshold = 1
      End With

      If comPort.IsOpen = False Then
        comPort.Open()
      End If

      If comPort.IsOpen = True Then
        bReturnResult = True
      Else
        bReturnResult = False
      End If

    Catch Ex As Exception
      bReturnResult = False
    End Try

    Return bReturnResult

  End Function

Private Sub comVoteExt_DataReceived(ByVal sender As SerialPort, ByVal eArgs As SerialDataReceivedEventArgs) Handles comVoteExt.DataReceived

Dim sData As Integer = 0 'integer to hold serial data

Try
  Do
    sData = sender.ReadChar 'take one char off the stack
    sbReceive_Extract.Append(Chr(sData))
    If bExtract = True Then
      'Check for data
      If iLength = 0 Then
          'hex 04 is end of data on tally stream
        If Chr(sData) = Chr("&H04") Then
          iLength = sbReceive_Extract.Length
        End If
      Else
           '6 bytes reserved for checksum and carriage return
        If sbReceive_Extract.Length >= iLength + 6 Then
            'Meets checksum length. Ready for next stage.
          bReady = True
        End If
      End If
    Else
        '20 bytes of header information 
      If sbReceive_Extract.Length > 20 Then
          'Data is ready for next stage. Minimum header length met.
        bReady = True
      End If
    End If
  Loop Until sender.BytesToRead = 0
Catch exc As Exception
End Try

End Sub

Does anything look like it could be causing my handshaking problem? Is there some way to "wake up" the device once the port is open so it starts communicating? I've tried setting DTREnable to true after the port is open and it doesn't seem to matter. I'm quite stumped.

0

There are 0 best solutions below