For precision timekeeping, both to set the time initially and to correct any drift that may occur, I want the LED clock to have a means to connect to a PC. Further, having serial communication available means that a PC could be used to trigger some of the clock’s special modes, like nuclear meltdown. A wireless ethernet connection would be ideal; but I don’t have the time to devote to it right now, and it would add significantly to the cost. Wired ethernet and USB share the same problems. Wired serial communication is easy.
Well, supposed to be easy. The LogoChip has built-in serial communication; the hitch is that receiving data halts the running program in order to process the data. In other words, any time you set the time, the program would stop running and be unable to receive the data. That’s a drawback.
There’s a better way. The PIC chip that runs the LogoChip firmware has a built-in Universal Asynchronous Receiver/Transmitter (UART–a device to run serial communication in hardware). The LogoChip firmware doesn’t use the UART, but I can use it myself through software–and that’s exactly what I’ve done.
Level Conversion and the MAX232
There’s one trick to using the UART: RS-232 specifies ±12V for its signalling, but the PIC chip runs at 0/5V logic levels. The LogoChip gets away with interfacing to RS-232 by using a substandard transmit voltage and a resistor-based divider on the receive voltage; but there’s one more reason I can’t do that when I use the native UART: Line driver chips invert the signal so that 5V source becomes -12V on the line. The LogoChip is doing the inversion in software when it drives its hacky serial ports, but the UART requires an inverting level converter and has no facility to invert for you.
That means I need an external line driver chip (or hack something together with transistors, but I’d rather not), and that means I need a MAX232. The MAX232 not only converts from 0/5V to ±12V, but also does so without requiring ±12V power connections–it generates ±12V from a single 5V supply.
I ordered samples of the MAX232 in three different packages a while back, and received one of my samples and one of someone else’s samples. I’m trying to get Maxim to send me the rest of my samples order . . . but that’s a whole ‘nother story.
Prototyping the MAX232
A week ago, I gave up waiting on the DIP MAX232 sample and soldered leads onto my surface-mount sample so I could stick it into the breadboard. I plugged in the five 1μF capacitors it uses to step up the voltage, wired it to the LogoChip, and got pretty quick success–I could translate voltage levels going in and out. Cool!
Programming the UART
Then I tried to configure the UART so I could send data, and I couldn’t manage to get anything meaningful to go across the link. Not cool!
On the datasheet, the UART looks a little intimidating to get set up, but it’s really not too bad once you get into it. (Well, mostly.) There’s a little more to it; but you mostly enable UART mode (the pins are regular I/O pins if you’re not in UART mode), set the number of bits you want, program the baud rate generator, and drop data into the transmit register or pick it up out of the receive register.
The baud rate generator (BRG) was my sticking point. It’s set as what divisor to use of the oscillator frequency; except I couldn’t find anywhere that said whether that was the oscillator running the chip or one of the programmable timers. Turns out it’s the main oscillator–mostly.
My first problem was a think-o on the write
instruction I used to configure the baud rate generator speed–I had the operand and address reversed. The proper syntax is
write <address> <value>
but I wrote
write SPBRG-9600 SPBRG
I don’t know why, but write <address> <value>
just feels wrong to me. English uses verb indirect-object direct-object syntax. (“Give me the money.”) I’m pretty sure the old 8-bit microcomputer BASICs used POKE <address> <value>
. So what’s my problem???
Anyway, once I got that sorted out, I had a small matter of determining the correct divisor to put into the BRG. I thought I was trying all the appropriate values from the table in the datasheet, but I could never get real text to come out on my computer. Testing was a hassle, too, as I had only one serial port available on the PowerBook, so I had to keep moving it back and forth between the programming port and the UART.
The datasheet says the divisor for 9600bps from a 40MHz oscillator is 64, but I kept getting garbage on my screen. I thought I was also testing all the different receive rates on my computer each time to see whether I was accidentally at some other rate; but even then, I could never find good data. (In retrospect, that’s especially puzzling, since I should have been at different usable data rates a number of times.) I ended up spewing dummy data (capital “U” is 01010101 in binary) from the LogoChip and looking at it on my scope to see what speed it was.
With the BRG divisor at 64, I got one bit measuring about 5.3 divisions at 20μs/div, or about 9420 bits/second. After some fiddling around, that seemed to work properly (and matches what’s on the datasheet for 40MHz), so I thought I was fine. And at that point, I was able to transmit data to the computer.
Receiving Data from the UART
Receiving is much more difficult, apparently, as I was still unable to get data from my computer into the LogoChip. It would just sit and wait for incoming data, and never actually receive it into the buffer.
Since transmit and receive share the same BRG, I knew I didn’t have a speed problem. I wondered whether the MAX232 was bad; but with my scope, I was able to confirm the flow of 5V translated data from the MAX232 to the PIC. I wondered whether the PIC was bad; but I wrote a test routine to take the PIC out of UART mode, and I was able to see changing data levels on the receive pin when accessing it manually.
What the heck???
I knew Tom McGuire had got RS-232 communication working using the UART, and so I asked him about it. He sent me some sample code (which was virtually identical to mine) and some things to check (which were all okay), and then volunteered to help me troubleshoot it. I dropped by last night after work, we hooked it up to his digital scope and saw that data was flowing where it was supposed to, we compared it to more of his code and found it was the same, and so once again, what the heck???
And then we looked at the receive error flags. I’d been wondering whether I was going to have to deal with them, but figured I’d let the master inspect my circuit and code first. But he found some other of his code that examined the receive overflow flag, and when I tested mine, I found it was set. Overflow? The UART hadn’t received any data successfully; how could it overflow???
Well, you clear the overflow bit by taking the UART out of continuous receive mode (and putting it back in). I added code to my receive routine to check for and clear the error, and BLAMMO! Instant working serial communications!
Next Steps
As noted yesterday, I’ve got my board for the first third of the six-digit display laid out (with the other two-thirds requiring simple clone/shift/chop operations). I added some identifying text to it last night, and I have a tentative appointment with Tom on Friday to mill the board.
Meanwhile, I now know that my serial port hardware is all okay. So even though I haven’t written the software to sync time with a PC, I can go ahead and design and build the clock’s controller board.
I should have two-digit display pictures up by sometime Saturday or Sunday . . .