LED Clock: Serial Communication, MAX232, and Programming the LogoChip UART

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 . . .

8 Responses to “LED Clock: Serial Communication, MAX232, and Programming the LogoChip UART”

  1. Tobie says:

    Hi Keith,

    I see you have made extensive Allegro’s A6276 LED driver.

    I’m having some problems addressing multiple A6276s. Singly I can get either to play nicely, but otherwise I get mess on the LEDs. One driver had a 10 bar display, the other has x2 seven segment arrays.

    I think I don’t fully understand how and when the latch enable should be used – I’m using picbasic pro with a 16F876.

    best wishes,
    Tobie

  2. Keith Neufeld says:

    Tobie, the latch enable tells each A6276 when it’s time to take the bits it’s holding internally and put them onto the output. Until you strobe the latch enable, the new data bits are only held internally.

    If you want to use two A6276s, you can hook them up in two ways: series or parallel.

    In series, the first chip’s serial data out (SDO) should connect to the second chip’s serial data in (SDI), the clock (CK) signal should connect to both chips, and the latch enable (L) should connect to both chips. Then any time you want to update a signal somewhere, you need to shift out 32 bits of data (enough to fill the entire pipeline of both chips) and then latch it. This is how I drive the two A6276s within one of my clock’s digits.

    In parallel, you connect your PIC to both chip’s SDI lines and clock lines, and connect a separate pin to each chip’s latch enable line. You only have to clock out sixteen bits of data at a time, enough to fill one chip. Both chips will have the new data in their buffers, but only the one you latch will then use it to drive its output. This is how I connect the six pairs of A6276s for my clock’s six digits.

  3. Tobie says:

    Thanks Keith,

    So in parallel, each A6276 needs its own Latch Enable (pin4) and its own output enable (pin21), then a common SDI and clock. Thats 6 pins for 2 drivers?

    Here’s the code that is broke:

    controlLEDdrivers:

    ‘enable driver for 10-bit bar
    LOW enable1_6276
    LOOKUP2 barIndex, [0,1,3,7,15,31,63,127,255,511,1023], bits_bar
    LOW latch_6276
    LOW clock_6276
    ‘shift data out
    SHIFTOUT data_6276, clock_6276, MSBFIRST, [bits_bar\10]
    HIGH latch_6276
    HIGH enable1_6276

    ‘enable driver for 7 segment displays
    LOW enable2_6276
    LOOKUP2 dig1Index, [252,96,218,242,102,182,190,224,254,246], bits_dig1
    LOOKUP2 dig2Index, [252,96,218,242,102,182,190,224,254,246], bits_dig2
    bits_dig.byte1 = bits_dig1
    bits_dig.byte0 = bits_dig2
    LOW latch_6276
    LOW clock_6276
    ‘shift data out
    SHIFTOUT data_6276, clock_6276, LSBFIRST, [bits_dig\16]
    HIGH latch_6276
    HIGH enable2_6276

    return

    If I were to use 2 pins for the latches (“latch1_6276″ and “latch2_6276″ for example) things would work?

    Well I’m trying it now…

    thanks again, Tobie

  4. Keith Neufeld says:

    I tie the output enable pin (/OE) low (active) in hardware. If I want all lights off, I just set all bits to 0. So I have common SDI and CK throughout, and a latch enable for each parallel section. 4 pins for 2 drivers.

    I’d suggest two fixes for your code. First, as you noted already, make two latch lines.

    Second, leave /OE low all the time. When you raise it high, you’re turning off the LEDs. Just strobe the latch high for at least 100ns when you want to latch the new data you’ve shifted in.

    So:


    ‘enable driver for 10-bit bar
    LOW enable1_6276
    LOOKUP2 barIndex, [0,1,3,7,15,31,63,127,255,511,1023], bits_bar
    LOW latch_6276
    LOW clock_6276
    ’shift data out
    SHIFTOUT data_6276, clock_6276, MSBFIRST, [bits_bar\10]
    HIGH latch_6276
    Add 100ns delay here -- maybe a few NOPs
    LOW latch_6276
    HIGH enable1_6276

    And then a similar change for your two-digit driver.

    What’s happening right now is that you’re shifting bar-graph bits into both the bar-graph and two-digit displays and latching it to both outputs, then shifting two-digit bits into both displays and latching to both outputs. You want to latch bar-graph data only into the bar-graph driver output, and two-digit data only into the two-digit output.

    Page 2 of the datasheet has a nice diagram showing the serial-parallel shift register separate from the output latch.

  5. Tobie says:

    It’s alive! Keith that’s a huge help, I can make sense of the block diagram and understand what the heck is going on now.

    Picbasic has a PAUSEUS to create a microsecond pause, I guess this is x10 the 100ns you and the datasheet suggest for the Latch pulse width – infact my PIC is using a 20 MHz clock to I only need 50ns.

    So my last question is, what is this NOP you mention to create a delay?

  6. Keith Neufeld says:

    Tobie, excellent! Glad it’s working now.

    NOP is “no operation,” an opcode in many assembly languages to do nothing for one clock cycle. Some higher-level languages, particularly for embedded systems programming, use it also, to cause a short delay.

    For example, LogoChip Logo, the language I’ve been using on PIC microcontrollers, has wait n (n intervals of .1 second) and mwait n (n μs); and also no-op, which waits for one cycle in the virtual machine — about 13 ns, if I recall correctly.

    I don’t know Picbasic, but you might look for a NOP or no-op in it. If not, your PAUSEUS should be more than adequate.

    So . . . what are you building with a bar-graph and two digits? :-)

  7. Tobie says:

    Hi Keith, I’m building a domestic sensor network, and it’s a bit mysterious to the user what each node is doing! The aim of the interface is to show live sensor data (using the bar graph as output of an analogue sensor) and the incrementation of ‘events’ which are triggered when the sensor tips a certain threshold – the 7 segment LEDs acts as a counter for the events.

    These displays are piggy-backing on motes, connecting through a DF9 socket (http://www.hirose.co.jp/cataloge_hp/e54000041.pdf) on the mote. The board I’m building is like a parasite which looks at the motes sensors, hopefully without disturbing the mote’s function which has off-the shelf firmware. Each node is runing off a power supply so I don’t have to worry about all that stuff!

    Here’s a link to the project: http://www.goldsmiths.ac.uk/interaction/health.html

    I’m a designer rather than an engineer, but I get there in the end, but not without kind help along the way!

    I’m going to insert some assembler code for the interval, I recall now a snippit on the pic basic forum which did something similar.

  8. russ_hensel says:

    As an option to the RS232 chip put the translation in the cable, use the cable over and over, smaller board, total translation chips 1. Make has the most inexpensive version, almost as cheap as the parts: http://store.makezine.com/ProductDetails.asp?ProductCode=BBBP4 or for usb translation: http://store.makezine.com/ProductDetails.asp?ProductCode=TTL232R

    I first saw the idea at: http://www.piclist.com/techref/io/serial/RCL1.htm

    russ_hensel

Leave a Reply