You are viewing an older revision! See the latest version
Text LCD Enhanced
This page describes an enhanced forked version of the basic driver code library for Text LCD panels using the 4-bit HD44780 lcd display driver.
New features¶
- Support for more LCD types
- TextLCD::LCD8x1 8x1 LCD panel
- TextLCD::LCD8x2 8x2 LCD panel
- TextLCD::LCD16x4 12x4 LCD panel (soon)
- TextLCD::LCD16x1 16x1 LCD panel (actually 8x2 in different layout)
- TextLCD::LCD16x1 16x2 LCD panel (default)
- TextLCD::LCD16x4 16x4 LCD panel
- TextLCD::LCD24x2 20x2 LCD panel
- TextLCD::LCD24x2 20x4 LCD panel
- TextLCD::LCD24x2 24x2 LCD panel
- TextLCD::LCD24x4 24x4 LCD panel (for KS0078 controller)
- TextLCD::LCD40x2 40x2 LCD panel
- TextLCD::LCD40x2 40x4 LCD panel (soon)
- Support for Cursor and/or Blinking current character
- Support for User Defined Characters to display special symbols
- Improved methods to get and set the memory address of the current character
- Support for I2C PCF8574 Portexpander or SPI as alternate interface to save on mbed pins
Background¶
The LCD driver HD44780 is designed for 2 rows of max 40 chars. Note that it needs some support drivers to control that maximum number of chars.
The address for the first char on the first line is 0x00. The address for the first char on the second line is 0x40. Four line displays are generally created by splitting the two line display and arranging the two parts above eachother. For example 2x40 is split in 2 parts of 2x20 and arranged as 4x20. The adddresses for the 3rd and 4th line just continue where the split was made:
- The address for the first char on the first line is 0x00, the last char is 0x13.
- The address for the first char on the second line is 0x40, the last char is 0x53.
- The address for the first char on the third line is 0x14, the last char is 0x27.
- The address for the first char on the fourth line is 0x54, the last char is 0x67.
The original TextLCD lib uses the address(column,row) method to return the memory address. However, the method adds 0x80 to the returned addressvalue to include the 'set display datamemory address' command. This is rather confusing when you try to make sense of the actual address. See discussion here.
The enhanced library provides the getAddress(column,row) method to return the correct address. The original method is still provided for compatibility reasons.
Notes: The HD44780 is pretty flexible and variations of driverhardware and LCD glass layout may result in differences. Some 4 line displays actually use two controllers with separate enable pins. The HD44780 supports left/right shifting of memory locations (address) wrt displayposition. That changes the address of the char that is shown on a displaylocation.
LCD wiring¶
The new lib supports several ways of connecting with mbed:
- Direct connection with mbed pins using a parallel bus (same as original TextLCD)
- Serial connection using mbed I2C bus and a PCF8574 portexpander
- Serial connection using mbed SPI bus and a 74595 shiftregister
Warning
The most commonly found connector on LCDs has 14 pins in a single row or as 2x7 pins. Note there may also be 2 additional pins for the backlight. The pinout for the LCD connector is fairly standard. However, exceptions are known. Always check the datasheet and verify by visual or conductivity testing of the GND pin. GND is normally connected to the metal frame around the LCD glass.
The 'standard' pinout has been used in the tables below.

Warning
The contrast VO pin may have different behaviour on different displays, so you may need to experiment for your display to see anything. Adjustable contrast can be achieved with a 10k trim-pot in a voltage divider configuration: one side to Vcc, other side to GND, wiper to VO. Adjust until you see a line of solid squares, then back off until they just disappear.
Displays powered at 3V3 instead of 5V may need a (small) negative voltage at VO. One side of the trimpot is connected to the negative voltage instead of GND in that case.
Use decoupling capacitors (100uF parallel to 100nF) on your 5V or 3V3 powersupply for the display, especially when the power is provided my mbed. This will help avoid brief powerline dips which could lead to distorted characters on the display.
Parallel bus wiring¶
| TextLCD pins | mbed pins |
|---|---|
| p1 GND | p1 0V |
| p2 VCC | p40 5V Vout |
| p3 VO | via wiper of 10k pot |
| p4 RS | p15 |
| p5 RW | p1 0V |
| p6 E | p16 |
| p7 D0 | not connected |
| p8 D1 | not connected |
| p9 D2 | not connected |
| p10 D3 | not connected |
| p11 D4 | p17 |
| p12 D5 | p18 |
| p13 D6 | p19 |
| p14 D7 | p20 |
The mbed pins can be supplied in the TextLCD constructor and may be changed. Some LCD displays will work OK with a 3V3 powersupply voltage. You may have to provide a small negative Vo in that case to get good contrast.
Serial I2C bus wiring¶
The advantage of using the I2C bus is that you save on mbed pins. This is even more true when you use the bus anyhow for other purposes. The small disadvantage that the I2C may be slower than a parallel bus is not a big problem for a slow device like a text display.
| TextLCD pins | PCF8574 pins | mbed pins |
|---|---|---|
| p1 GND | p8 0V | p1 0V |
| p2 VCC | p16 Vcc | p40 5V Vout |
| p3 VO | via wiper of 10k pot | not connected |
| p4 RS | p9 P4 | not connected |
| p5 RW | p8 0V | p1 0V |
| p6 E | p10 P5 | not connected |
| p7 D0 | not connected | not connected |
| p8 D1 | not connected | not connected |
| p9 D2 | not connected | not connected |
| p10 D3 | not connected | not connected |
| p11 D4 | p4 P0 | not connected |
| p12 D5 | p5 P1 | not connected |
| p13 D6 | p6 P2 | not connected |
| p14 D7 | p7 P3 | not connected |
| not connected | p1 A0 GND or Vcc | not connected |
| not connected | p2 A1 GND or Vcc | not connected |
| not connected | p3 A2 GND or Vcc | not connected |
| not connected | p15 SDA | p9 or p28 |
| not connected | p14 SCL | p10 or p27 |
The mbed I2C bus must be supplied in the TextLCD constructor and may be changed (p9,p10) or (p28,p27). Note that you must provide pullup Rs of about 4K7. PCF8574 addresspins (p1,p2,p3) must be strapped to GND or Vcc to set the deviceAddress. That address must also be supplied in the LCDText constructor. The PCF8574 supports 8 different addresses (0x40..0x4E). The PCF8574A is similar but has a different baseaddress (0x70..0x7E). So in total you can connect upto 16 LCDs to one I2C bus!
- Note1: Several other vendors supply clones of the PCF8574 (eg Texas Instruments)
- Note2: You can change the connections between the PCF8574 pins and the LCD. Just update the appropriate pin definitions in TextLCD.h
- Note3: You can roll-your-own PCF8574 interface or try to find one ready made on ebay. Search for TWI or I2C and LCD. You may have to change the pin definitions.
Example of ready made I2C expander for LCDs

Serial SPI bus wiring¶
The advantage of using the SPI bus rather than I2C is that the 74595 shiftregister is cheaper than a PCF8574. Disadvantages are that it needs more pins (MOSI, SCLK and CS). You also need a separate CS for every new device since SPI does not support a slaveAddress.
| TextLCD pins | 74595 pins | mbed pins |
|---|---|---|
| p1 GND | p8 0V | p1 0V |
| p2 VCC | p16 Vcc | p40 5V Vout |
| p3 VO | via wiper of 10k pot | not connected |
| p4 RS | p4 Q4 | not connected |
| p5 RW | p8 0V | p1 0V |
| p6 E | p5 Q5 | not connected |
| p7 D0 | not connected | not connected |
| p8 D1 | not connected | not connected |
| p9 D2 | not connected | not connected |
| p10 D3 | not connected | not connected |
| p11 D4 | p15 Q0 | not connected |
| p12 D5 | p1 Q1 | not connected |
| p13 D6 | p2 Q2 | not connected |
| p14 D7 | p3 Q3 | not connected |
| not connected | p10 nMR Vcc | p40 5V |
| not connected | p11 SHCP | p7 or p13 SCK |
| not connected | p12 STCP | p8 CS |
| not connected | p14 DS | p5 or p11 MOSI |
| not connected | p13 nOE GND | p1 0V |
The mbed SPI bus must be supplied in the TextLCD constructor and may be changed (p5,NC,p7) or (p11,NC,p13). You must also provide a CS pin.
- Note1: The 74HC595 should work on 3V3, but 5V is the prefered supplyvoltage
- Note2: You can change the connections between the 74595 pins and the LCD. Just update the appropriate pin definitions in TextLCD.h
Serial SPI bus wiring for 40x4 LCDs¶
The 40x4 LCDs are different from the regular types because they have two controllers. In fact this is a combination of two 40x2 displays. They have a different pinout with two enable lines (e1 and e2). The example below shows how to connect it using the SPI 74595 shiftregister. The display can also be interfaced to the I2C portexpander or directly to mbed pins using an additional pin for E2.
| TextLCD pins | 74595 pins | mbed pins |
|---|---|---|
| p1 D7 | p3 Q3 | not connected |
| p2 D6 | p2 Q2 | not connected |
| p3 D5 | p1 Q1 | not connected |
| p4 D4 | p15 Q0 | not connected |
| p5 D3 | not connected | not connected |
| p6 D2 | not connected | not connected |
| p7 D1 | not connected | not connected |
| p8 D0 | not connected | not connected |
| p9 E1 | p5 Q5 | not connected |
| p10 RW | p8 0V | p1 0V |
| p11 RS | p4 Q4 | not connected |
| p12 VO | via wiper of 10k pot | not connected |
| p13 GND | p8 0V | p1 0V |
| p14 VCC | p16 Vcc | p40 5V Vout |
| p15 E2 | p6 Q6 | not connected |
| p16 NC/Vee | not connected | not connected |
| not connected | p10 nMR Vcc | p40 5V |
| not connected | p11 SHCP | p7 or p13 SCK |
| not connected | p12 STCP | p8 CS |
| not connected | p14 DS | p5 or p11 MOSI |
| not connected | p13 nOE GND | p1 0V |
The mbed SPI bus must be supplied in the TextLCD constructor and may be changed (p5,NC,p7) or (p11,NC,p13). You must also provide a CS pin.
- Note1: The 74HC595 should work on 3V3, but 5V is the prefered supplyvoltage
- Note2: You can change the connections between the 74595 pins and the LCD. Just update the appropriate pin definitions in TextLCD.h
Text LCD Enhanced Library¶
Import library
Public Types |
|
| enum |
LCDType
{
LCD8x1 , LCD8x2 , LCD16x1 , LCD16x2 , LCD16x2B , LCD16x4 , LCD20x2 , LCD20x4 , LCD24x2 , LCD24x4 , LCD40x2 } |
|
LCD panel format. More... |
|
| enum | LCDCursor { CurOff_BlkOff , CurOn_BlkOff , CurOff_BlkOn , CurOn_BlkOn } |
|
LCD Cursor control. More... |
|
Public Member Functions |
|
| TextLCD (PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, LCDType type=LCD16x2) | |
|
Create a
TextLCD
interface for using regural mbed pins.
|
|
| TextLCD (I2C *i2c, char deviceAddress, LCDType type=LCD16x2) | |
|
Create a
TextLCD
interface using an I2C PC8574 portexpander.
|
|
| TextLCD (SPI *spi, PinName cs, LCDType type=LCD16x2) | |
|
Create a
TextLCD
interface using an SPI 74595 portexpander.
|
|
| int | putc (int c) |
|
Write a character to the LCD.
|
|
| int | printf (const char *format,...) |
|
Write a formated string to the LCD.
|
|
| void | locate (int column, int row) |
|
Locate to a screen column and row.
|
|
| int | getAddress (int column, int row) |
|
Return the memoryaddress of screen column and row location.
|
|
| void | setAddress (int column, int row) |
|
Set the memoryaddress of screen column and row location.
|
|
| void | cls () |
|
Clear the screen and locate to 0,0.
|
|
| int | rows () |
|
Return the number of rows.
|
|
| int | columns () |
|
Return the number of columns.
|
|
| void | setCursor ( LCDCursor show) |
|
Set the Cursormode.
|
|
| void | setUDC (unsigned char c, char *udc_data) |
|
Set User Defined Characters.
|
|
Example Code¶
// Hello World! for the TextLCD
#include "mbed.h"
#include "TextLCD.h"
// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx
// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL
// SPI Communication
SPI spi_lcd(p5, NC, p7); // MOSI, MISO, SCLK
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x4); // rs, e, d4-d7 ok
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD20x2); // rs, e, d4-d7 ok
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD20x4); // rs, e, d4-d7 ok
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD24x4); // rs, e, d4-d7 ok
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD24x2); // rs, e, d4-d7 ok
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD40x2); // rs, e, d4-d7 ok
TextLCD lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4); // I2C bus, PCF8574 Slaveaddress, LCD Type ok
//TextLCD lcd(&spi_lcd, p8, TextLCD::LCD24x4); // SPI bus, CS pin, LCD Type ok
int main() {
pc.printf("LCD Test. Columns=%d, Rows=%d\n\r", lcd.columns(), lcd.rows());
for (int row=0; row<lcd.rows(); row++) {
int col=0;
pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));
// lcd.putc('-');
lcd.putc('0' + row);
for (col=1; col<lcd.columns()-1; col++) {
lcd.putc('*');
}
pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));
lcd.putc('+');
}
// Show cursor as blinking character
lcd.setCursor(TextLCD::CurOff_BlkOn);
// Set and show user defined characters. A maximum of 8 UDCs are supported by the HD44780.
// They are defined by a 5x7 bitpattern.
lcd.setUDC(0, (char *) udc_0); // Show |>
lcd.putc(0);
lcd.setUDC(1, (char *) udc_1); // Show <|
lcd.putc(1);
lcd.setUDC(2, (char *) udc_2);
lcd.putc(2);
lcd.setUDC(3, (char *) udc_3);
lcd.putc(3);
lcd.setUDC(4, (char *) udc_4);
lcd.putc(4);
lcd.setUDC(5, (char *) udc_5);
lcd.putc(5);
lcd.setUDC(6, (char *) udc_6);
lcd.putc(6);
lcd.setUDC(7, (char *) udc_7);
lcd.putc(7);
}
The terminal will print the actual memory addresses like this:
LCD Test. Columns=20, Rows=4 MemAddr(Col=0, Row=0)=0x00 MemAddr(Col=19, Row=0)=0x13 MemAddr(Col=0, Row=1)=0x40 MemAddr(Col=19, Row=1)=0x53 MemAddr(Col=0, Row=2)=0x14 MemAddr(Col=19, Row=2)=0x27 MemAddr(Col=0, Row=3)=0x54 MemAddr(Col=19, Row=3)=0x67
Examples¶
Some results are shown here:
LCD20x2

LCD24x2

LCD40x2

LCD16x4

LCD20x4

LCD24x4

LCD40x4
Soon...
User Defined Characters

References¶
- You can find the new lib here: http://mbed.org/users/wim/code/TextLCD/