----- /-------------\-/-------------\-/-------------\-/----
| start bit / data bit 0 X data bit 1 X data bit 2 X
|--------------/---------------/-\-------------/-\-------------/-\----
------ /-------------\-/-------------\-/-------------\-/----
| start bit / data bit 0 X data bit 1 X data bit 2 X
|--------------/---------------/-\-------------/-\-------------/-\----
| | | |
0000000000111111111122222222223333333333444444444455555555556666666666
0123456789012345678901234567890123456789012345678901234567890123456789
^ ^ ^ ^
start bit detected first data bit subsequent data
within first 1/16 bit sampled 24 bits sampled every
time of leading edge intervals later 16 sample intervals
thereafter
Most UARTs will actually sample the middle of the start bit (eight sample
periods after the leading edge is recognized) and verify that it is low in
case the detected leading edge was just a glitch. Some UARTs will also take
multiple samples in the middle of the bit time (i.e, at 23, 24, and 25 in the
diagram above) and set error flags for noise if they don't all match.
Many application notes on implementing software UARTs, including the Microchip
ap notes, suggest sampling at two times the bit rate. This results in the
following:
----- /-------------\-/-------------\-/-------------\-/----
| start bit / data bit 0 X data bit 1 X data bit 2 X
|--------------/---------------/-\-------------/-\-------------/-\----
------------- /-------------\-/-------------\-/-------------\-
| start bit / data bit 0 X data bit 1 X data bit 2 X
|--------------/---------------/-\-------------/-\-------------/-
| | | | |
0 1 2 3 4 5 6 7 8
^ ^ ^ ^ ^
start bit detected first data bit subsequent data
within first 1/2 bit sampled 2 bits sampled every
time of leading edge intervals later 2 sample intervals
thereafter
This results in a 1/2 bit time uncertainty regarding when the start bit
actually arrived. As a consequence the data bit sampling can occur any time
within the first half of the data bit, including right at the leading edge.
This allows no margin for rate mismatch.
An alternative would be to sample the first data bit three sample periods
after the start bit is detected, and every two sample periods thereafter.
This is no better as the window is then from the middle to the end of the
data bit, so the bits could be sampled right at the trailing edge, again
allowing no margin for rate mismatch.
The Microchip ap note does at least suggest waiting 1.25 bit times from the
leading edge of the start bit to sample the first data bit, which results in
the sample window being in the middle 50% of the bit. That's great unless you
want to do full duplex serial and use the same time base for transmit. Since
you can't get a 1.25 bit time delay using a 0.5 bit time timebase, you
maintain proper transmitter timing during that 1.25 bit time delay.
The correct solution (IMHO) is to sample at 3 times the bit rate:
----- /------------\-/------------\-/------------\-/-----------
| start bit / data bit 0 X data bit 1 X data bit 2 X
|-------------/--------------/-\------------/-\------------/-\-----------
---------- /------------\-/------------\-/------------\-/-------
| start bit / data bit 0 X data bit 1 X data bit 2 X
|-------------/--------------/-\------------/-\------------/-\-------
| | | | |
0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3
^ ^ ^ ^ ^
start bit detected first data bit subsequent data
within first 1/3 bit sampled 4 bits sampled every
time of leading edge intervals later 3 sample intervals
thereafter
As you can see, this reduces the uncertainty of the timing of the start bit
to 1/3 of a bit time, and guarantees that the sampling of the data bits will
occur within the middle 1/3 of the bit time, thus providing better tolerance
to speed variation than the 1/2 bit time scheme provides (even with the 1.25
bit time delay). It also uses fewer CPU cycles than would be required to
sample at 4 times the bit rate.
I've implemented this scheme on a PIC16C84 and it seems to work quite well.
I use the RTCC timer to generate interrupts at three times the bit rate, and
the interrupt routine has simple receive and transmit state machines to do the
work. I'll make the code available after I do some more testing.
Back to my PIC Projects page
Back to my home page
Last updated June 5, 1995
Copyright 1995 Eric Smith