| A Simple Software UART For C167/6/4 |
A customer recently enquired if we knew of any way of using two of the 32 CAPCOM channels on a C167CR to make a second and third UART. Well we did and here it is:
A simple software UART for the C16x CAPCOM unit.
This simple function uses the CAPCOM unit to both detect the falling edge of the start bit and the providing the baudrate timebase for the clocking in of the serial bits. A negative-edge triggered capture into CC3 of a free running timer, timer 0 also produces the first interrupt which will usually be the falling edge of the start bit. The CAPCOM channel mode is then switched to compare mode and a number of timer counts corresponding to a one and a half single bit periods is added to the count captured in CC3. In one bit period time, the interrupt will occur in the middle of bit zero. The state of the pin (P2.3) is transferred into bit 9 of a bdata short variable which is then shifted one place to the right. A single bit period of timer 0 counts is then added to CC3 to produce the next interrupt at the centre of bit 1. The process is repeated until 8 bits have been collected from the pin. The value in the bdata variable is then transferred to a char variable for use elsewhere in the program. The CAPCOM mode is then switched back into negative-edge triggered capture mode, ready for the next start bit.
The CPU loading represented by the software UART receiver section
is around 2% at 9600 baud. The transmit section requires around
1% at the same baud rate. If you are interested in the complete
UART, please click here.
Simple Software UART Code Extract:
void uartA_rx_interrupt(void) interrupt 0x13 { if(!start_bit_detect_mode) { // If jump not taken, time is saved??? /*** Now in centre of bit period so sample uartA pin ***/ rxA_shift_reg_input = uartA_input_pin ; rxA_shift_reg = rxA_shift_reg >> 1 ; CC3 += SABRG ; // Make interrupt one bit period later uartA_bit_count-- ; if(Z) { uartA_bit_count = 9 ; _bfld_(CCM0,0xf000,0x2000) ; // Enable CC3, capture neg edge, T0, to // find next start bit SARBUF = rxA_shift_reg ; // Capture byte for use by background code SARIR = 1 ; // Set dummy receive interrupt pending flag } } else { /*** Start bit detected... ***/ CC3 += SABRG + SABRG/2 ; // Wait 1+1/2 bits until // first input pin sampling point for bit 0 _bfld_(CCM0,0xf000,0x4000) ; // Enable CC3, compare mode 0, T0 } }