Character LCDs over SPI

Character LCDs with HD44780/KS0066U-compatible controllers are a widespread standard in electronics equipment, and are readily available and accessible to the hobbyist. However, microcontroller I/O pins are a scarce resource, and these LCDs use a parallel interface that requires 11 pins for a full implementation of the 8-bit interface. These controllers do have a 4-bit mode that reduces the requirement by 4 pins, and one pin can be saved by hard wiring the display in write mode, but 6 I/O pins must still be dedicated to the display, or at least shared with things that tolerate having the display connected. The big 4×40 displays are worse…these controllers are rather archaic, and each can only handle 2×40 lines. These “4×40” displays thus actually have two controllers, sharing data and control lines but with separate enable lines, and so require 7 IO pins at minimum.

One common solution: the 74595 shift register. This device consists of an 8 bit long shift register with separate output latches…you shift data in, and then latch it into the output registers to update all outputs simultaneously. This is essentially the same hardware used for SPI, and conveniently, the ‘595 can be wired to take input directly from a SPI bus, serving as a primitive port expander. For some reason many people bit-bang the shift register, manually toggling GPIO pins to clock data into it, but the ‘595 is perfectly capable of being driven faster and more efficiently by an AVR’s SPI hardware. 8 outputs is enough to talk to a dual-controller 4×40 LCD with one pin free for a smaller LCD or backlight control, or up to 3 separate LCDs, while only using the SPI bus and one slave select. An example for a single-controller LCD:

The shift register data is transferred to the output latches on the positive going edge of the store clock input. That input thus behaves much like a slave select, the only difference being the behavior when less than 8 bits are clocked in before the rising “deselect” edge…the chip has no “selected” state and will output whatever the last 8 bits on the bus were on the “deselect” rising edge, so make sure not to select it if you don’t intend to write to it. The output enable and shift register clear inputs are active low: the first is tied to ground so that the outputs are always enabled, and the shift register clear input is tied to VCC .

This does come at some cost. An additional part is required, obviously: the shift register itself. The 4-bit protocol is a little more complicated to initialize and use, and takes two SPI transfers for every command to the LCD. Perhaps the biggest drawback is that the shift register is incapable of reading from the LCD. Data can not be stored in the LCD DDRAM, and it is not possible to poll the LCD state, so control is purely open-loop: you must wait for the LCD to process each operation before proceeding to the next. The cost of the ‘595 is a small fraction of that of the LCD though, and readback from the display is generally not needed. And as a side benefit to all this, if the VHC logic family is used, the shift register will handle 3.3V or 5V inputs regardless of the LCD/shift register power supply…no additional translation of logic levels is necessary. With the increasing use of 3.3V parts and the high availability of old but cheap 5V LCD modules, this can be particularly useful.

When prototyping, it also takes up breadboard space, which is nearly as precious a resource as GPIO pins. I made an adaptor board for my 4×40 character module that allows it to be connected via a 5-pin connector (never mind the “screensaver”):

Some people do clever things with RC networks to automatically latch the data in the shift register after a transfer is done, which can save the slave select pin, but I’ve gone for SPI compatibility instead. With the separate slave select, the LCD can share the bus with other SPI devices.

Source code for AVR microcontrollers with SPI ports, using AVR-GCC:

More information:

Leave a Reply

Your email address will not be published. Required fields are marked *