Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

MSComm to receive data of variable length

Status
Not open for further replies.

pancy

Technical User
Jan 23, 2004
17
HK
Dear all,
I am very new to VB 6. I would like to know how I can receive data of variable length because I know that I have to set the RTheshold value. My situation is like this:
I have to types of data:
1) starts with "A" + strings of data
2) starts with "B" + Hex numbers of 2 - 512 bytes
I need to handle these two types separately after I received the whole bulk.

if I fixed the data size to be say, 100 bytes, I can set
MSComm1.RTheshold = 100
then If MSComm1.CommEvent = comEvReceive
I can do the job

but I do not know the data size. What can I do?
Very urgent! Please offer some help! Thanks alot!

Pancy
 
Usually with situations like this you have the MScomm receive each byte until it gets a particular byte that tells your program that the end of the block of data has been reached. The RThreshold is set to 0 so that the OnComm event triggers for each byte received. You add the bytes to a string variable or array as they are received, until the "marker" is picked up. Usually the marker is something like a carriage return or line feed, or it could be a sequence of bytes in a particular order. Once you see the marker you process the data that you stored, clear the data and wait for more.

Robert
 
Dear Robert,
I see!!! Thanks a million!
Pancy
 
Sorry Robert,
I've some problem in my program.
here's my codings:

Private Sub Form_Load()
' Fire Rx Event Every 1 Byte
MSComm1.RThreshold = 1
MSComm1.InputLen = 0
MSComm1.Settings = "9600,N,8,1"
MSComm1.CommPort = 1
MSComm1.PortOpen = True
End Sub

Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
RData = RData + MSComm1.Input
End If
End Sub

But it doesn't work, when I show RData, there is nothing.

Could anyone kindly help. Thank you
 
Each time the OnComm event fires, RData will be re-initialised unless it's declared at Form level.

Use [tt]
Dim RData as String[/tt]
in the Declarations section of the Form module

________________________________________________________________
If you want to get the best response to a question, please check out FAQ222-2244 first

'If we're supposed to work in Hex, why have we only got A fingers?'
 
OK, here is a class that I use for when I am getting variable length data from the com port, and the data is terminated by a CR. Add the code below into a new class and save it as clsCOMMData.

Code:
Option Explicit

Event DataArrived(DataString As String)

Private m_COMMString As String
Private m_String As String

Property Let NewDataString(ByVal NwInput As String)
Dim I As Integer
Dim S As String
    
    ' add the characters onto the string until you reach the CR
    For I = 1 To Len(NwInput)
        ' get the next character
        S = Mid(NwInput, I, 1)
        
        Select Case S
        Case vbCr
            ' this is the CR character. Set the output string, erase the temp string, and raise the event.
            m_COMMString = m_String
            m_String = ""
            RaiseEvent DataArrived(m_COMMString)
        
        Case vbLf
            ' this is a Line Feed.  Ignore it
            
        Case Else
            ' this is any other character.  Add it onto the string.
            m_String = m_String & S
            
        End Select
    ' continue on if there are any remaining characters in the new input string
    Next I
    
End Property

Property Get COMMString() As String
    ' gets the last commstring that was transmitted
    
    COMMString = m_COMMString

End Property


OK, you need to declare the class using WithEvents in your forms declaration section:

Code:
'Dims the class for RS232 communication, and enables events to be driven by this class
Dim WithEvents COMMData As clsCOMMData

So, when you do this, you get a new event in your form code, like this:

Code:
Private Sub COMMData_DataArrived(DataString As String)
' this event fires whenever a new full data string has been prepared by the COMMData class.  DataString holds the data.

Debug.Print DataString

' Here is where you would process your data

End Sub

Try this and see how it goes.

Robert

 
Oops! Forgot an important step!

You need this in your comm port oncomm event.

Code:
Private Sub MSComm1_OnComm()

If MSComm1.CommEvent = comEvReceive Then
     ' send this new string to the COMMData class for assembly into the full string
    ' and possible activation of the DataArrived event.
    COMMData.NewDataString = MSComm1.Input
End If

End Sub

OK, that should do it.

Robert
 
Robert,
could you please tell me what your settings of RThreshold, InputLen etc. are?
Am I setting those right?
Thanks alot!
Pancy
 
The other method I've seen used is to transmit the size of your data first. So if you transmit two 4-byte values (Longs are four 4 bytes in VB), your receiver would first read those values and know how many A's and B's to expect.

Chip H.


If you want to get the best response to a question, please check out FAQ222-2244 first
 
One problem with mscomm is that it can fire the oncomm sub many times in the process of receiving one string although you arent aware of it.
I use a very simple method for receiving text of variable length that works every time.
First I would attach vbCrLf to the end of each string to be sent if it hasnt got one anyway and put a non printing character at the start to differentiate between the strings
To send:-
SendComm1.Output = Chr(200) & DataA & vbcrlf 'data a
SendComm1.Output = Chr(201) & DataB & vbcrlf 'data b


Then when I receive it I look for vbcrlf and it tells me the string has been fully received.

Dim RDatabuffer as string, DataA as string, DataB as string
Private Sub Form_Load()
'you can set these in the properties sheet instead
MSComm1.RThreshold = 1 ' Fire Rx Event Every 1 Byte
MSComm1.InputLen = 0
MSComm1.Settings = "9600,N,8,1"
MSComm1.CommPort = 1
MSComm1.PortOpen = True
End Sub

Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
RDataBuffer = RDataBufer + MSComm1.Input
If Instr(RDataBuffer,vbcrlf) then 'found the end
Select case Asc(left(RDataBuffer,1))
Case 200
DataA=Mid(RDataBuffer,2,len(RDataBuffer)-3)

Case 201
DataB=Mid(RDataBuffer,2,len(RDataBuffer)-3)

End Select
RDataBuffer=""
End if
End If
End Sub
 
Pancy,

Your settings are what they need to be already. You set it up so that the com port gets all of the data that is available in the buffer when the input method is used. The InputLen of 0 does this. The RThreshold of 1 sets it up so any new data fires the oncomm event.

tedsmith : The class code I posted handles the incoming string regardless of how many times the oncomm event fires for one string.

chiph : From the context of pancy's original question, I took it that he has no control over the format of the data coming into the serial port.

Robert
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top