TextLCD with I2C Interface

This was the original motivation for playing with the PCF8574A I2C IO expander. The LCDs have a 7 pin interface that can be bit banged, and since you dont usually care about the update speed of the display, it seems like a good idea to try and bit bang it over I2C.

This frees up 5 mbed pins, and means that the LCD interface can share with other I2C slaves in the system

Hardware

The LCD is hooked up to the PCF8475 with the following pin configuration :

LCD Pin IO bit PCF8574 Pin
RS 4 9
RW 5 10
E 6 11
D4 0 4
D5 1 5
D6 2 6
D7 3 7

Note that if you power the LCD from 3.3v, you need a 1k resistor from Gnd to Vo (pin 1 to pin 3). If you are powering form 5v, then a use a wire link from Gnd to Vo

The PCF8574 has the following connections :

Pin Function Connection
1 Address 0 Gnd
2 Address 1 Gnd
3 Address 2 Gnd
8 VSS Gnd
14 SCL 10 - with a 2k2 pullup to VDD
15 SDA 9 - with a 2k2 pullup to VDD
16 VDD 3.3v or 5v

Software

I'm basing this work on the existing LCD library written by Simon, which you can find here :

The original library implements the bit banged protocol by assignmens to 3 DigitalOuts (_rs, _rw, _e) and a 4 bit BusOut (_d), so it seemed logical to leave the rest of the library in tact, and just meddle with this.

The result is this :

All I have done is create four local functions :

  • void _rs (int)
  • void _rw (int)
  • void _e (int)
  • void _d (int)

These are direct replacements for the four DigitalOut/BusOut objects, so instead of making an assignments to objects, I'm calling the functions. This means that the library remains almost untouched, except _rw=1; becomes _rw(1);

The next thing I did was create a local variable (_iodata) that holds the state of the I2C IO pins. Each of the 4 function simply updates the relevent bit(s), and squirts the new 8 bit value to the PCF8574.

#include "mbed.h"
#include "TextLCD_I2C.h"

DigitalOut myled(LED1);

TextLCD_I2C lcd (p9,p10,0x20);

int main() {

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Hello world!");

    lcd.locate(0,1);
    lcd.printf("I2C Kicks ass!");
}

Results

It works a treat :-)

I've not stress tested it to see how fast the display updates, but as it is a 2x16 character display, I figure the update speed isnt too important as no-one is going to be playing quake.