I've had correspondence where people are unsure of the code that performs the "USART" serialisation. Constructors want to make changes to the serial data rate. They have applications monitor remotely, using simple FSK radio transmission. Dropping the speed from 19200 bps down to 2400 makes the modulation fit in to the pass band of an audio receiver.
In the design I'm not using a discrete USART Universal Synchronous Asynchronous Receiver Transmitter chip. I'm not using a PIC (16F628/20) that could do this for me. I actually chose to use timing delays.
I specified a crystal frequency of 2.4576 MHz. This gives an instruction delay of 1.627 us. To delay one bit period at 19200 bps, 52.08 us, the PIC needs to execute 32 instructions. But where are the instructions?
Here's the serialisation source:
Why does the delay subroutine bitdly16 only have 16 NOP's? Shouldn't there be 32?
No, the rest of the delay is in the decision logic and in actually setting the port I/O to a one or zero.
I'll unravel the first part of the code, documenting the instruction set cycle count from the time the start bit begins.
The I/O pin is at the logic 1 from the last call to send a character. The last call would have left the pin in logic state 1, the stop bit value. We start by sending a logic 0 for the initial transition of the stop bit, then set the I/O pin back to a 1 for a contrived data bit 0.
| TxChar1 movlw .9 movwf RS232_COUNT call OutZero ; start bit // this calls: |
|
| bcf PORTA, RS232_BIT; 1 // Pin is now at logic 0 goto bitdly16 // 2 bitdly16 |
|
| nop ; trim!
// 21 nop // 22 SendLp0 decfsz RS232_COUNT, f ; // 23 goto SendBit ; 2 // 25 SendBit rrf RS232_DATA, f ; // 26 btfss STATUS, C ; // 28 goto SendZero ; nop // 29 call OutOne ; send 1 // 31 // this calls: |
|
| OutOne bsf PORTA, RS232_BIT // 32 // Pin is now at logic 1 |
I could carry on and pick out the delays for each data bit, and finally the 2 stop bits.
I haven't tried this, but....
For 2400 bps bit period we need a delay of 416.66 us. That's 256 instruction cycles in place of 32. We could insert extra NOP instructions at label bitdly16. Adding 224 NOP's would do the trick.
A more elegant solution is to set up a loop counter as below:
bitdly16
movlw .73 //
1
73 = 224/ 3
movwf MY_COUNT // 2
L1
DECFSZ MY_COUNT,f // 3 (6, 9.....
222)
goto L1 // 5 (8, 11.....224)
NOP // and
carry on with existing code...
NOP
NOP
NOP
NOP
NOP
NOP
NOP
bitdly8
NOP
Back to the Schematics page