Interfacing LCD via SPI

Not rated 5,428

Circuit Image

Over time, microcontrollers have become increasingly powerful, cost-effective, and compact. A typical microcontroller from the past may have had 40 pins and lacked internal memory, whereas modern J-series PICs feature 96K of program memory and only 28 pins. This allows for the control of numerous peripherals, although the limited number of pins can be a constraint. This article demonstrates how to drive a parallel interface peripheral in a serial manner. A suitable candidate for this approach is the HD44780-compatible LCD module, which is widely used, affordable, and operates at a slower speed, allowing for a seamless conversion from parallel to serial without losing performance. Utilizing a microcontroller with fewer pins can also result in cost savings. The Serial Peripheral Interface (SPI) is straightforward to implement, thanks to the synchronous serial communication hardware support found in newer PICs. An additional component required for the LCD is the 74HC595 double-buffered shift register, which can be easily procured from online electronic component distributors like Mouser or Digi-Key for approximately 48 cents in SMT package, with a slightly higher cost for DIP. Due to its simplicity, most of the necessary functionality will be handled through software. The HD44780-compatible LCD (referred to as LCD) is a parallel device that features eight data lines and three control signals. These signals indicate to the controller when the data lines contain valid data, the type of data being sent, and whether the operation involves writing to or reading from the controller (the latter will not be utilized in this instance). SPI transmits data serially, sending one byte at a time and marking the transmission of each bit with a clock pulse. The 74HC595 receives SPI data and relays it to its parallel outputs. The schematic symbol for the 74HC595 includes two buffers: one for serial data and another for parallel data. Serial data is input on pin 14, while the serial clock is provided on pin 11. When pin 12 transitions from low to high, the serial buffer's contents are copied to the parallel buffer, which then appears on the parallel output pins. An animation illustrates the transfer of two bytes, 0x55 (01010101) and 0xAA (10101010), from SPI to the parallel output.

The native LCD interface consists of eight data lines and three control signals, functioning in either 8-bit or 4-bit mode. In 8-bit mode, all data lines are utilized, making LCD control somewhat simpler; however, this mode does not allow for the use of control signals with the shift register. In contrast, 4-bit mode uses only the upper four bits of the data bus, necessitating the division of the data byte into two halves for transmission in two stages. This is the mode selected for implementation. The control signals include RS, RW, and E. The RS signal determines the type of data sent to the LCD: if RS is 0, a command is being sent; if RS is 1, the data represents a character to be displayed. The falling edge of the E signal initiates the transfer of the data bus and RS state to the LCD controller. The RW signal controls data direction; since a unidirectional shift register is used and reading back from the data bus is not possible, RW is connected to ground. In this configuration, instead of reading the LCD state, a sufficient delay is introduced before sending the next byte to the LCD.

The SPI-to-LCD circuit is designed on a small daughterboard that connects to the LCD display, with three signal wires and two power wires linking to the main board with the microcontroller. This daughterboard is intended for attachment to a standard LCD 2G-7 header. A schematic for this design is available, and the board can be ordered from BatchPCB. The main board featuring the microcontroller is kept simple, utilizing the widely-used PIC18F4520 mounted on a breadboard, without requiring a crystal oscillator. The schematic for the breadboard connections is provided. To send a byte to the LCD, the RS signal and the high nibble of the data byte must first be set. Following this, the E signal is activated and then deactivated, allowing the controller to read the data bus on the falling edge of E. Subsequently, the low nibble of the data bus is set, and E is toggled again. A waiting period is necessary before the next byte is transmitted, with the duration of the delay depending on the characteristics of the specific HD44780 LCD being utilized.As time goes by, microcontrollers become more powerful, cheaper, and smaller. A typical micro of the past could have had 40 pins and no internal memory. On the contrary, modern J-series PICs are made with 96K program memory and 28 pins. We can drive a lot of peripherals with that amount of memory, however we are getting short on pins. In this arti cle I will show how to drive a parallel interface peripheral serially. A HD44780-compatible LCD module is good candidate it is popular, inexpensive, and slow, so you won`t be losing any speed while converting parallel to serial. And you could even save some money using a micro with fewer pins. SPI is very easy to implement thanks to synchronous serial communication hardware support in newer PICs.

The only other thing necessary on the LCD end is 74HC595 double-buffered shift register. It can be easily obtained from on-line electronic components distributors, such as Mouser or Digi-Key for as little as 48 cents in SMT package, slightly more in DIP. Since it`s very simple device, most functionality that we need will be done in software. HD44780-compatible LCD (LCD for short) is a parallel device. It has 8 data lines and 3 control signals which tell the controller when data lines contain valid data, what kind of data it is and whether you want to write to the controller or read from it (we won`t be using the last one BTW).

SPI is serial it sends out a byte one bit at a time, marking  appearance of each bit with a clock pulse. The 74HC595 receives SPI data and sends is to it`s parallel outputs. Take a look at 74HC595 schematic symbol. It has two buffers one for serial data, another for parallel. Serial data go on pin 14. Serial clock goes on pin 11. When pin 12 goes from low to high serial buffer gets copied to parallel buffer and its contents appear on parallel output pins.

The following animation shows how two bytes 0G—55 ( 0101 0101 ) and 0xAA ( 1010 1010 ), are transferred from SPI to parallel output. Let`s talk briefly about native LCD interface. The device has 8 data lines and three control signals. It can work in either 8-bit or 4-bit mode. In 8-bit mode all data lines are used and LCD control is slightly easier, however, if we utilize this mode our little shift register won`t be able to accommodate any of the control signals.

In 4-bit mode only upper 4 bits of the data bus are used; the data byte needs to be split in two halves and sent in two transfers. This is the mode that we will be using. Control signals are RS, RW, and E. RS defines what kind of data is being sent to LCD. If RS is 0, we are sending a command, if RS is 1, the data is just a character to be printed on the screen.

Falling edge of E initiates transferring of data bus and RS state to LCD controller. The last signal is RW it controls data direction. Since we are using unidirectional shift register and won`t be able to read back the data bus, RW is simply tied to ground. In this mode, instead of reading LCD state we will just wait long enough before sending next byte to LCD.

The SPI-to-LCD circuit is made on a little daughter board. The idea is to attach it to LCD display and have 3 signal and 2 power wires run to the main board with MCU. The daughter board is designed to be attached to standard LCD 2G—7 header. Here is a schematic. The board is available to order at BatchPCB To keep you focused on communication with LCD the main board with MCU  is made very simple.

It`s ever-popular PIC18F4520 mounted on a breadboard. No crystal oscillator is used. Here is a schematic of breadboard connections. What do we need to send a byte to LCD First, RS and high nibble of data byte needs to be set. Then, E needs to be set and cleared controller reads data bus on the falling edge of E. After that, we need to set low nibble of data bus and toggle E again. We need to wait some time before sending next byte. The delay depends on characteristics of the specific HD447 🔗 External reference