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.