Table 2 . Timing errors
4 MHz | 10 MHz | |||||
equal | aligned | UART | equal | aligned | UART | |
57600 | 19% | 2.7% | 8.5% | 8% | 1.0% | 1.4% |
115200 | 33% | 5.1% | 8.5% | 12% | 2.3% | 8.5% |
230400 | 71% | 8.8% | 8.5% | 12% | 4.1% | 9.6% |
460800 | 71% | 23% | – | 71% | 8.3% | – |
921600 | – | – | – | 95% | 16% | – |
Considering 10% error in bit timing as acceptable we may make conclusion that the bit alignment is required starting from baud rate 57600 @ 4 MHz and 115200 @ 10 MHz.
Slowly emerging
Now let us try to apply this approach to lower speeds. With 115200 we get cycle lengths 9 8 9 9 8 9 9 8 9. So, sending the start bit may be the very first instruction and all preparation may be done while expiring the start bit.
bcf | port, 0 | ; 0: sending start bit | |
movwf | data | ; 1: put data to rotation buffer | |
rrf | data, W | ; 2: prepare data for output: | |
xorwf | data, F | ; 3: '1' in DATA means toggle port | |
movlw | 1 | ; 4: load port-toggling mask | |
delay | 3 | ; 5, 6, 7 | |
skpnc | ; 8: first bit is already in C | ||
xorwf | port, F | ; 9: send bit 0 | |
delay | 6 | ; 10, 11, 12, 13, 14, 15 | |
btfsc | data, 0 | ; 16: test data | |
xorwf | port, F | ; 17: send bit 1 | |
delay | 7 | ; 18, 19, 20, 21, 22, 23, 24 | |
... | |||
xorwf | port, F | ; 78: send bit 7 | |
delay | 8 | ; | |
bsf | port, 0 | ; 87: sending stop bit | |
return | ; Routine length 30 words |
Four delay intervals are needed: 3, 6, 7 and 8. We still cannot use a counter for measuring delays because loading the counter would discard the port-toggling mask. Call to a subroutine takes at least 4 IC, so we may declare a subroutine with three entrees that, along with calls to d8, d7, d6, will implement these delays:
d8 | nop | ||
d7 | nop | ||
d6 | goto | $+1 | |
return | ; Routine length 4 words |
Next in the list is 57600 with cycle lengths 17 18 17 17 18 17 18 17 17. The bit length is already long enough to use loop. However, this loop should also use some kind of aligning. What code may give us desired results? The following sequence is executed in 3 or 4 IC, depending on the content of align file:
rrf | align, F | ; 1: rotate align bits | |
skpnc | ; 2: align if indicated by C | ||
goto | $+1 | ; 3: this instruction alings the cycle |
Thereby, if we make a loop of 17 IC long and put B’001010010′ into align, we get bit lengths as required. We also have to change the way we test data bit. Previously used btfsc data,<i> will not work in the loop, so data should be rolled bit by bit into C. This requires changing data preparation. In previous examples our code places bit 0 into carry, now all bits must be in the file register. Considering all this, the routine will look like:
bcf | port, 0 | ; 0: sending start bit | |
movwf | data | ; 1: put data to rotation buffer | |
clrc | ; 2: C will be rolled in, so clear it | ||
rlf | data, W | ; 3: prepare data for output | |
xorwf | data, F | ; 4: '1' in DATA means toggle port | |
movlw | .8 | ; 5: load bit count | |
movwf | count | ; 6: into counter | |
movlw | B'00101001' | ; 7: load alignment bits, not including start bit | |
movwf | align | ; 8: load to alignment rotation file | |
delay | 5 | ; 9, 10, 11, 12, 13 | |
_bit | movlw | 1 | ; 14: load port-toggling mask |
rrf | data, F | ; 15: put data bit into C | |
skpnc | ; 16: test data bit | ||
xorwf | port, F | ; 17: send bit | |
rrf | aling, F | ; 1: rotate align bits | |
skpnc | ; 2: align if indicated | ||
goto | $+1 | ; 3: this instruction alings the cycle | |
delay | 7 | ; 4, 5, 6, 7, 8, 9, 10 | |
decfsz | count,F | ; 11: counting bits | |
goto | _bit | ; 12: | |
stop | delay | 4 | ; 13, 14, 15, 16 |
bsf | port, 0 | ; 17: sending stop bit | |
return | ; Routine length 23 words |
The shortest bit length we may achieve with this loop is 10 instruction cycles. One may notice, that movlw 1, being placed out of the loop, would make it even shorter: 9 cycles. However there is a reason to keep it inside of the loop, which I’ll tell in the next chapter.
Post a Comment