RickyHanna
asked on
Basic comms coding
I have my serial port connected to one of my companies proprietary circuit boards. I send for instance : MSComm1.Output = "p14" and then imediately do Temp1 = MSComm1.Input.
Temp1 being the return value.
First of all is this the corect way?
If it is surely there is a chance that my code will move to the read line when the chip on the board is still processing the write? How an this be avoided if it is possible?
Temp1 being the return value.
First of all is this the corect way?
If it is surely there is a chance that my code will move to the read line when the chip on the board is still processing the write? How an this be avoided if it is possible?
There is a general problem if you don't know the protocol of knowing when to stop listening. You might, for instance, have an idea of how long to wait, or the expected message length
When the Input buffer is read, it is emptied, so repeated tries should be concatenated to a string variable.
Const buflen = 100 'say
Const Waitcount = 10000 'say
Buffer$ = ""
i = 0
Do
DoEvents
i = i + 1
Buffer$ = Buffer$ & MSComm1.Input 'concatenate
Loop Until Len(Buffer$) = buflen or i = Waitcount
MsgBox Buffer$
When the Input buffer is read, it is emptied, so repeated tries should be concatenated to a string variable.
Const buflen = 100 'say
Const Waitcount = 10000 'say
Buffer$ = ""
i = 0
Do
DoEvents
i = i + 1
Buffer$ = Buffer$ & MSComm1.Input 'concatenate
Loop Until Len(Buffer$) = buflen or i = Waitcount
MsgBox Buffer$
ASKER
Is there no OnComm event that handles this?
No, as per my knowledge
Option Explicit
'flow control variables. Strings for now. Integers taking enumerated constants would be better
'eg.
'Const phSending = 0
'Const phReceiving = 1
Dim Phase As String
Dim Stage As String
Dim ReceiveBuffer As String
Const ReceivingInterval = 100
Private Sub Command1_Click()
Dim b As String
Dim i As Integer
MSComm1.Settings = "56000,N,8,1"
MSComm1.CommPort = 2
MSComm1.InputLen = 0 'Default anyway
MSComm1.RThreshold = 1 'Fire OnComm event with a single character in input buffer
MSComm1.PortOpen = True
Transact "ATE0", 500 'command to tell the modem not to echo the "AT" back
Stage = "Initialising Modem"
End Sub
Sub Transact(SendText As String, TimeOut As Integer)
ReportIt "Sending: " & SendText
Timer1.Interval = TimeOut 'milliseconds
ReceiveBuffer = ""
MSComm1.Output = SendText & vbCr
Timer1.Enabled = True
Phase = "Sending"
End Sub
Private Sub Timer1_Timer()
Dim b As String
ReportIt "Timer: Interval: " & Timer1.Interval & " Stage: " & Stage & " Phase: " & Phase
Select Case Phase
Case "Sending"
ReportIt "Nothing Received"
Case "Receiving"
b = TrimBoth(ReceiveBuffer)
ReportIt "Received: " & b
Select Case Stage
Case "Initialising Modem"
If Right$(b, 2) = "OK" Then
Transact "ATDT 12345", 30000 ' Hard coded for now
Stage = "Dialling"
Phase = "Sending"
Else
ReportIt "Modem not responding"
End If
Case "Dialling"
Select Case Left$(b, 7)
Case "CONNECT"
'this is where you start to control the device
Transact "Device Command", 30000
Stage = "Device1"
Phase = "Sending"
Case Else
'some sort of error
End Select
End Select
End Select
Timer1.Enabled = False
End Sub
Function TrimRight(Intext As String) As String
'strip blanks, tabs, line feeds etc from end of string
Dim Text As String
Text = Intext
If Len(Intext) > 0 Then
Do While Asc(Right$(Text, 1)) <= 32
Text = Left$(Text, Len(Text) - 1)
Loop
TrimRight = Text
End If
End Function
Private Sub MSComm1_OnComm()
ReportIt "OnComm: " & MSComm1.CommEvent
Select Case MSComm1.CommEvent
Case comEvSend '1 Send event.
Case comEvReceive '2 Receive event.
Phase = "Receiving"
ReceiveBuffer = ReceiveBuffer & MSComm1.Input
ReportIt "ReceiveBuffer: " & ReceiveBuffer
Timer1.Enabled = False
Timer1.Interval = ReceivingInterval
Timer1.Enabled = True
Case comEvCTS '3 Change in clear-to-send line.
Case comEvDSR '4 Change in data-set ready line.
Case comEvCD '5 Change in carrier detect line.
Case comEvRing '6 Ring detect.
Case comEvEOF '7 End of file.
'errors
Case comEventBreak '1001 A Break signal was received.
Case comEventFrame '1004 Framing Error. The hardware detected a framing error.
Case comEventOverrun '1006 Port Overrun. A character was not read from the hardware before the next character arrived and was lost.
Case comEventRxOver '1008 Receive Buffer Overflow. There is no room in the receive buffer.
Case comEventRxParity '1009 Parity Error. The hardware detected a parity error.
Case comEventTxFull '1010 Transmit Buffer Full. The transmit buffer was full while trying to queue a character.
Case comEventDCB '1011 Unexpected error retrieving Device Control Block (DCB) for the port.
End Select
End Sub
Function TrimLeft(Intext As String) As String
Dim Text As String
If Len(Intext) > 0 Then
Text = Intext
Do While Asc(Text) <= 32
Text = Mid$(Text, 2)
Loop
TrimLeft = Text
End If
End Function
Function TrimBoth(Intext As String) As String
TrimBoth = TrimLeft(TrimRight(Intext) )
End Function
Sub ReportIt(Text As String)
'This could be modified to write to a log file
Dim b As String
b = TrimBoth(Text)
If Len(b) > 0 Then
Debug.Print Now & " " & b
End If
End Sub
'flow control variables. Strings for now. Integers taking enumerated constants would be better
'eg.
'Const phSending = 0
'Const phReceiving = 1
Dim Phase As String
Dim Stage As String
Dim ReceiveBuffer As String
Const ReceivingInterval = 100
Private Sub Command1_Click()
Dim b As String
Dim i As Integer
MSComm1.Settings = "56000,N,8,1"
MSComm1.CommPort = 2
MSComm1.InputLen = 0 'Default anyway
MSComm1.RThreshold = 1 'Fire OnComm event with a single character in input buffer
MSComm1.PortOpen = True
Transact "ATE0", 500 'command to tell the modem not to echo the "AT" back
Stage = "Initialising Modem"
End Sub
Sub Transact(SendText As String, TimeOut As Integer)
ReportIt "Sending: " & SendText
Timer1.Interval = TimeOut 'milliseconds
ReceiveBuffer = ""
MSComm1.Output = SendText & vbCr
Timer1.Enabled = True
Phase = "Sending"
End Sub
Private Sub Timer1_Timer()
Dim b As String
ReportIt "Timer: Interval: " & Timer1.Interval & " Stage: " & Stage & " Phase: " & Phase
Select Case Phase
Case "Sending"
ReportIt "Nothing Received"
Case "Receiving"
b = TrimBoth(ReceiveBuffer)
ReportIt "Received: " & b
Select Case Stage
Case "Initialising Modem"
If Right$(b, 2) = "OK" Then
Transact "ATDT 12345", 30000 ' Hard coded for now
Stage = "Dialling"
Phase = "Sending"
Else
ReportIt "Modem not responding"
End If
Case "Dialling"
Select Case Left$(b, 7)
Case "CONNECT"
'this is where you start to control the device
Transact "Device Command", 30000
Stage = "Device1"
Phase = "Sending"
Case Else
'some sort of error
End Select
End Select
End Select
Timer1.Enabled = False
End Sub
Function TrimRight(Intext As String) As String
'strip blanks, tabs, line feeds etc from end of string
Dim Text As String
Text = Intext
If Len(Intext) > 0 Then
Do While Asc(Right$(Text, 1)) <= 32
Text = Left$(Text, Len(Text) - 1)
Loop
TrimRight = Text
End If
End Function
Private Sub MSComm1_OnComm()
ReportIt "OnComm: " & MSComm1.CommEvent
Select Case MSComm1.CommEvent
Case comEvSend '1 Send event.
Case comEvReceive '2 Receive event.
Phase = "Receiving"
ReceiveBuffer = ReceiveBuffer & MSComm1.Input
ReportIt "ReceiveBuffer: " & ReceiveBuffer
Timer1.Enabled = False
Timer1.Interval = ReceivingInterval
Timer1.Enabled = True
Case comEvCTS '3 Change in clear-to-send line.
Case comEvDSR '4 Change in data-set ready line.
Case comEvCD '5 Change in carrier detect line.
Case comEvRing '6 Ring detect.
Case comEvEOF '7 End of file.
'errors
Case comEventBreak '1001 A Break signal was received.
Case comEventFrame '1004 Framing Error. The hardware detected a framing error.
Case comEventOverrun '1006 Port Overrun. A character was not read from the hardware before the next character arrived and was lost.
Case comEventRxOver '1008 Receive Buffer Overflow. There is no room in the receive buffer.
Case comEventRxParity '1009 Parity Error. The hardware detected a parity error.
Case comEventTxFull '1010 Transmit Buffer Full. The transmit buffer was full while trying to queue a character.
Case comEventDCB '1011 Unexpected error retrieving Device Control Block (DCB) for the port.
End Select
End Sub
Function TrimLeft(Intext As String) As String
Dim Text As String
If Len(Intext) > 0 Then
Text = Intext
Do While Asc(Text) <= 32
Text = Mid$(Text, 2)
Loop
TrimLeft = Text
End If
End Function
Function TrimBoth(Intext As String) As String
TrimBoth = TrimLeft(TrimRight(Intext)
End Function
Sub ReportIt(Text As String)
'This could be modified to write to a log file
Dim b As String
b = TrimBoth(Text)
If Len(b) > 0 Then
Debug.Print Now & " " & b
End If
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I will leave the following recommendation for this question in the Cleanup topic area:
Accept: GrahamSkan
Any objections should be posted here in the next 4 days. After that time, the question will be closed.
Matti
Experts Exchange CleanUp volenteer
Accept: GrahamSkan
Any objections should be posted here in the next 4 days. After that time, the question will be closed.
Matti
Experts Exchange CleanUp volenteer
I mean like this
MSComm1.Output = "p14"
' write a code here for sleeping the application for few seconds
Temp1 = MSComm1.Input.
though this is not a correct solution, i think this solves your problem. (Because we need to do some thread related program here, where we need to do application in wait mode until the statement was witten to com port)
Regards
sudha