by Gregory Mahan (2 Submissions)
Category: Coding Standards
Compatability: Visual Basic 3.0
Difficulty: Intermediate
Date Added: Wed 3rd February 2021
Rating: (4 Votes)
To demonstrate serial communications buffer handling. Helps stop data loss and other comm problems.
In serial communications (such as with a modem), most beginning programmers will suffer data loss, or other anomalies whenever data is sent at high rates. This behavior increases in severity the larger the bps rate of the communication. This is almost alwasys due to FIFO buffer overflows.
This article assumes: You already know how to connect to and get data from a serial port (such as with the MSComm Control). In common practice, the programmer uses a timer control to read any information in the MSComm contol and parses it, or perform other actions on the data. What many beginning serial communications programmers may not realize is that serial ports only have a 16-byte hardware buffer to hold incoming data. If you do a lot of work in your timer routine, this 16 byte buffer will tend to fill up, causing data loss or other communications anomalies.
The attached source code is fairly self explanatory, and simulates how to use a 2 buffer
system to prevent overflows and other problems dealing with async modem communications. A 16-byte hardware FIFO present in serial communications is simulated by Text1. If it ever gets above 16 characters, the Text1_Change event notifies us.
To simulate serial communications, simply type in Text1 as fast as you can. This simulates your serial FIFO buffer filling up with data from the serial port (modem, straight rs232 connection, etc).
If the first option button is selected, we use a 1 buffer and 1-timer system. The empty FOR-NEXT loops in the control represent time eaten up by all of the serial parsing usually necessary in such software. You'll notice that if you type as fast as you can you can quickly fill the 16 byte simulated serial FIFO buffer. This overflow would happen even faster in an actual serial communcations routine where data transmits many times faster than you can type.
If the second option button is selected, you'll see that all of the routines get shunted to a second timer. The two-buffer method dictates that the first timer's sole task is to empty the simulated input FIFO buffer into a second buffer as fast as possible, and do nothing else. You use a 2nd (slower) timer routine to handle any parsing of the data. This parsing is done on your second buffer, rather than directly on the input from the FIFO buffer.
In this example, buffIn is a form-scoped variable length string. In VB6, a variable-length string can be up to 2gigs (2 billion bytes) in size or so, giving you worlds more leeway in handling this buffer than the 16 byte serial buffer. With proper use of the 2-buffer system, a 1K input buffer would probably be sufficent in size.
In practice, you throw a DoEvents in the 2nd timer (the parsing routine) to handle things even more smoothly. This allows the processor intensive parsing routine to give up some time slices to the system so the first timer so it can continue to fill up the input buffer. (If you were to put a DoEvents in the first timeer, it would simply increase the amount of time necessary to complete the routine, causing an even faster buffer overflow.)
Notice that when we are using the 2-buffer system, processing may lag behind input by quite a bit but we never actually lose any information, nor do we overflow the simulated 16-byte FIFO.
Please note that the attached project is saved in VB6 format, but contains no special controls or VB6-required function calls. All of the code/theory is completely applicable to all versions of VB.
The following source code requires two text boxes (Text1 and Text2) on a form, as well as 2 timer controls (Timer1 and Timer2) and two option buttons (Option1 and Option2).
The attached project has everything layed out in an easy-to-view format.
Dim buffIn As String
Private Sub Option1_Click()
If Option1.Value = True Then
Timer2.Enabled = False
Else
Timer2.Enabled = True
End If
End Sub
Private Sub Option2_Click()
If Option1.Value = True Then
Timer2.Enabled = False
Else
Timer2.Enabled = True
End If
End Sub
Private Sub Text1_Change()
If Len(Text1) > 16 Then MsgBox "Simulated hardware buffer full!"
End Sub
Private Sub Text2_KeyPress(KeyAscii As Integer)
KeyAscii = 0
End Sub
Private Sub Timer1_Timer()
If Option1.Value = True Then
For x = 1 To 400
For i = 1 To 20000
'just eat up time
Next i
Next x
'the above loop simulates time eaten up because
'of buffer handling code (parsing, etc)
'do everything in this buffer
Text2 = Text2 & Text1.Text
Text1 = ""
Else
buffIn = buffIn & Text1.Text
Text1 = ""
End If
End Sub
Private Sub Timer2_Timer()
'all parsing and code timeouts happen here.
For x = 1 To 400
For i = 1 To 20000
'just eat up time
Next i
DoEvents
Next x
'the above loop simulates time eaten up because
'of buffer handling code (parsing, etc)
Text2 = Text2 & buffIn
buffIn = ""
End Sub