[EE]: Microcontroller with 4 USARTs and 40 pins
Bob Ammerman email (remove spam text)
This thread has fascinated me from the beginning. I was sure that it was
possible to do this on a PIC.
What I have come up with so far:
I have designed, and written the critical code for, a scheme permitting 5
full-duplex software UARTs. This code requires a timer-driven interrupt at 5
times the baud rate. Code path in the interrupt handler, counting all
overhead, with all 5 channels going full blast in both directions, is 55
instruction times max, 51 instruction times average. This drops down
somewhat if the channels are running at less than full speed.
The simulated UARTS sample the input at 5x the baud rate, and determine bits
using the majority vote of the center 3 samples for each bit.
They detect framing errors, and can handle receive data streams slightly
faster than the nominal rate (ie: the stop bit can be less than 5 samples
long, so the UART can slip properly to handle a slightly overspeed input).
Both receive and transmit are double-buffered so that task level has an
entire byte time to handle a received character or prepare the next
character for transmission.
Relating this to the problem at hand:
On a 10MIP 18CXX2 chip (10MHz clock, PLL'd to 40MHz on chip), with a baud
rate of 31250, the interrupt rate would be every 64 instruction times. This
will leave at least 9 and on average 13 instructions between interrupts.
Thus, 'task level' code will get about 13/64 = 20% or so of the 10MIPs. You
can get quite a bit done with the remaining 2 MIPS!
For anyone who is interested, the basic structure of the interrupt handler
is something like this (expressed in a combination of pseudocode and "C" to
make it easier to follow, but the real code is of course assembly):
send values computed by last interrupt for output bits to the hardware
fetch current values input bits from the hardware into 5 5-bit shift
registers, one per channel.
phase = 1;
compute next output bit for channel 0
process last 5 input bits received by channel 0
phase = 2;
compute next output bit for channel 1
process last 5 input bits received by channel 1
phase = 3;
compute next output bit for channel 2
process last 5 input bits received by channel 2
phase = 4;
compute next output bit for channel 3
process last 5 input bits received by channel 3
phase = 0;
compute next output bit for channel 4
process last 5 input bits received by channel 4
The phrase 'compute next output bit for channel N' simply figures out what
start, data, or stop bit is to be sent.
The phrase 'process last 5 input bits received by channel N' involves using
the 5 input bits, treated as a 5 bit number, as an input to a large state
machine stored as a table in program memory. This will determine a new
state, and possibly an action to be performed (setting a bit in the receiver
register, or marking a byte received (correctly or with a framing error)).
(high function, high performance, low-level software)
See also: www.piclist.com/techref/microchip/ios.htm?key=usart
You must be a member of the
piclist mailing list
(not only a www.piclist.com member) to post to the