Updated for more display types. Fixed memoryaddress confusion in address() method. Added new getAddress() method. Added support for UDCs, Backlight control and other features such as control through I2C and SPI port expanders and controllers with native I2C and SPI interfaces. Refactored to fix issue with pins that are default declared as NC.

Dependents:   GPSDevice TestTextLCD SD to Flash Data Transfer DrumMachine ... more

Fork of TextLCD by Simon Ford

Example

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);                // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=HD44780
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x4);   // SPI bus, 74595 expander, CS pin, LCD Type  
TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4);  // I2C bus, PCF8574 Slaveaddress, LCD Type
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2, TextLCD::WS0010); // I2C bus, PCF8574 Slaveaddress, LCD Type, Device Type
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9);               // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7032_3V3   
//TextLCD_I2C_N lcd(&i2c_lcd, ST7032_SA, TextLCD::LCD16x2, NC, TextLCD::ST7032_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=ST7032_3V3  

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);    

}

Handbook page

More info is here

Committer:
wim
Date:
Thu Jan 31 19:46:00 2013 +0000
Revision:
9:0893d986e717
Parent:
8:03116f75b66e
Child:
10:dd9b3a696acd
Tested on several LCD types

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 1:ac48b187213c 1 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
simon 6:e4cb7ddee0d3 2 * Copyright (c) 2007-2010, sford, http://mbed.org
wim 8:03116f75b66e 3 * 2013, WH, Updated LCD types and fixed lcd address issues
simon 1:ac48b187213c 4 *
simon 1:ac48b187213c 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 6 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 7 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 9 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 10 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 11 *
simon 1:ac48b187213c 12 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 13 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 14 *
simon 1:ac48b187213c 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 21 * THE SOFTWARE.
simon 1:ac48b187213c 22 */
simon 1:ac48b187213c 23
simon 1:ac48b187213c 24 #include "TextLCD.h"
simon 1:ac48b187213c 25 #include "mbed.h"
simon 1:ac48b187213c 26
simon 7:44f34c09bd37 27 TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5,
simon 7:44f34c09bd37 28 PinName d6, PinName d7, LCDType type) : _rs(rs),
simon 7:44f34c09bd37 29 _e(e), _d(d4, d5, d6, d7),
simon 1:ac48b187213c 30 _type(type) {
simon 1:ac48b187213c 31
simon 1:ac48b187213c 32 _e = 1;
simon 1:ac48b187213c 33 _rs = 0; // command mode
simon 1:ac48b187213c 34
simon 1:ac48b187213c 35 wait(0.015); // Wait 15ms to ensure powered up
simon 1:ac48b187213c 36
simon 1:ac48b187213c 37 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
simon 1:ac48b187213c 38 for (int i=0; i<3; i++) {
simon 1:ac48b187213c 39 writeByte(0x3);
simon 1:ac48b187213c 40 wait(0.00164); // this command takes 1.64ms, so wait for it
simon 1:ac48b187213c 41 }
simon 1:ac48b187213c 42 writeByte(0x2); // 4-bit mode
simon 1:ac48b187213c 43 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 44
simon 1:ac48b187213c 45 writeCommand(0x28); // Function set 001 BW N F - -
simon 1:ac48b187213c 46 writeCommand(0x0C);
wim 8:03116f75b66e 47 writeCommand(0x06); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
simon 1:ac48b187213c 48 cls();
simon 1:ac48b187213c 49 }
simon 1:ac48b187213c 50
wim 8:03116f75b66e 51
simon 1:ac48b187213c 52 void TextLCD::character(int column, int row, int c) {
wim 8:03116f75b66e 53 int addr = getAddress(column, row);
wim 8:03116f75b66e 54
wim 8:03116f75b66e 55 writeCommand(0x80 | addr);
simon 1:ac48b187213c 56 writeData(c);
simon 1:ac48b187213c 57 }
simon 1:ac48b187213c 58
wim 8:03116f75b66e 59
simon 1:ac48b187213c 60 void TextLCD::cls() {
simon 1:ac48b187213c 61 writeCommand(0x01); // cls, and set cursor to 0
simon 1:ac48b187213c 62 wait(0.00164f); // This command takes 1.64 ms
simon 1:ac48b187213c 63 locate(0, 0);
simon 1:ac48b187213c 64 }
simon 1:ac48b187213c 65
simon 1:ac48b187213c 66 void TextLCD::locate(int column, int row) {
simon 1:ac48b187213c 67 _column = column;
simon 1:ac48b187213c 68 _row = row;
simon 1:ac48b187213c 69 }
simon 1:ac48b187213c 70
simon 1:ac48b187213c 71 int TextLCD::_putc(int value) {
simon 1:ac48b187213c 72 if (value == '\n') {
simon 1:ac48b187213c 73 _column = 0;
simon 1:ac48b187213c 74 _row++;
simon 1:ac48b187213c 75 if (_row >= rows()) {
simon 1:ac48b187213c 76 _row = 0;
simon 1:ac48b187213c 77 }
simon 1:ac48b187213c 78 } else {
simon 1:ac48b187213c 79 character(_column, _row, value);
simon 1:ac48b187213c 80 _column++;
simon 1:ac48b187213c 81 if (_column >= columns()) {
simon 1:ac48b187213c 82 _column = 0;
simon 1:ac48b187213c 83 _row++;
simon 1:ac48b187213c 84 if (_row >= rows()) {
simon 1:ac48b187213c 85 _row = 0;
simon 1:ac48b187213c 86 }
simon 1:ac48b187213c 87 }
simon 1:ac48b187213c 88 }
simon 1:ac48b187213c 89 return value;
simon 1:ac48b187213c 90 }
simon 1:ac48b187213c 91
simon 1:ac48b187213c 92 int TextLCD::_getc() {
simon 1:ac48b187213c 93 return -1;
simon 1:ac48b187213c 94 }
simon 1:ac48b187213c 95
simon 1:ac48b187213c 96 void TextLCD::writeByte(int value) {
simon 1:ac48b187213c 97 _d = value >> 4;
simon 1:ac48b187213c 98 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 99 _e = 0;
simon 1:ac48b187213c 100 wait(0.000040f);
simon 1:ac48b187213c 101 _e = 1;
simon 1:ac48b187213c 102 _d = value >> 0;
simon 1:ac48b187213c 103 wait(0.000040f);
simon 1:ac48b187213c 104 _e = 0;
simon 1:ac48b187213c 105 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 106 _e = 1;
simon 1:ac48b187213c 107 }
simon 1:ac48b187213c 108
simon 1:ac48b187213c 109 void TextLCD::writeCommand(int command) {
simon 1:ac48b187213c 110 _rs = 0;
simon 1:ac48b187213c 111 writeByte(command);
simon 1:ac48b187213c 112 }
simon 1:ac48b187213c 113
simon 1:ac48b187213c 114 void TextLCD::writeData(int data) {
simon 1:ac48b187213c 115 _rs = 1;
simon 1:ac48b187213c 116 writeByte(data);
simon 1:ac48b187213c 117 }
simon 1:ac48b187213c 118
wim 8:03116f75b66e 119
wim 8:03116f75b66e 120 #if (0)
wim 8:03116f75b66e 121 // This is the original method.
wim 8:03116f75b66e 122 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 123 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 124 //
simon 1:ac48b187213c 125 int TextLCD::address(int column, int row) {
simon 1:ac48b187213c 126 switch (_type) {
simon 1:ac48b187213c 127 case LCD20x4:
simon 1:ac48b187213c 128 switch (row) {
simon 1:ac48b187213c 129 case 0:
simon 1:ac48b187213c 130 return 0x80 + column;
simon 1:ac48b187213c 131 case 1:
simon 1:ac48b187213c 132 return 0xc0 + column;
simon 1:ac48b187213c 133 case 2:
simon 1:ac48b187213c 134 return 0x94 + column;
simon 1:ac48b187213c 135 case 3:
simon 1:ac48b187213c 136 return 0xd4 + column;
simon 1:ac48b187213c 137 }
simon 1:ac48b187213c 138 case LCD16x2B:
simon 4:bf5b706f8d32 139 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 140 case LCD16x2:
simon 1:ac48b187213c 141 case LCD20x2:
simon 1:ac48b187213c 142 default:
simon 4:bf5b706f8d32 143 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 144 }
simon 1:ac48b187213c 145 }
wim 8:03116f75b66e 146 #endif
wim 8:03116f75b66e 147
wim 8:03116f75b66e 148
wim 8:03116f75b66e 149 // This replaces the original method.
wim 8:03116f75b66e 150 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 151 int TextLCD::address(int column, int row) {
wim 8:03116f75b66e 152 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 153 }
wim 8:03116f75b66e 154
wim 8:03116f75b66e 155 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 156 //
wim 8:03116f75b66e 157 int TextLCD::getAddress(int column, int row) {
wim 8:03116f75b66e 158
wim 8:03116f75b66e 159 switch (_type) {
wim 8:03116f75b66e 160 case LCD8x1:
wim 8:03116f75b66e 161 return 0x00 + column;
wim 8:03116f75b66e 162
wim 8:03116f75b66e 163 case LCD16x4:
wim 8:03116f75b66e 164 switch (row) {
wim 8:03116f75b66e 165 case 0:
wim 8:03116f75b66e 166 return 0x00 + column;
wim 8:03116f75b66e 167 case 1:
wim 8:03116f75b66e 168 return 0x40 + column;
wim 8:03116f75b66e 169 case 2:
wim 8:03116f75b66e 170 return 0x10 + column;
wim 8:03116f75b66e 171 case 3:
wim 8:03116f75b66e 172 return 0x50 + column;
wim 8:03116f75b66e 173 }
wim 8:03116f75b66e 174
wim 8:03116f75b66e 175 case LCD20x4:
wim 8:03116f75b66e 176 switch (row) {
wim 8:03116f75b66e 177 case 0:
wim 8:03116f75b66e 178 return 0x00 + column;
wim 8:03116f75b66e 179 case 1:
wim 8:03116f75b66e 180 return 0x40 + column;
wim 8:03116f75b66e 181 case 2:
wim 8:03116f75b66e 182 return 0x14 + column;
wim 8:03116f75b66e 183 case 3:
wim 8:03116f75b66e 184 return 0x54 + column;
wim 8:03116f75b66e 185 }
wim 8:03116f75b66e 186
wim 8:03116f75b66e 187 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 188 case LCD16x2B:
wim 8:03116f75b66e 189 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 190
wim 8:03116f75b66e 191 case LCD8x2:
wim 8:03116f75b66e 192 case LCD16x2:
wim 8:03116f75b66e 193 case LCD20x2:
wim 8:03116f75b66e 194 case LCD24x2:
wim 9:0893d986e717 195 case LCD40x2:
wim 8:03116f75b66e 196 return 0x00 + (row * 0x40) + column;
wim 8:03116f75b66e 197
wim 8:03116f75b66e 198 // Should never get here.
wim 8:03116f75b66e 199 default:
wim 8:03116f75b66e 200 return 0x00;
wim 8:03116f75b66e 201 }
wim 8:03116f75b66e 202 }
wim 8:03116f75b66e 203
wim 8:03116f75b66e 204
wim 8:03116f75b66e 205 // Added for consistency. Set row, colum and update memoryaddress.
wim 8:03116f75b66e 206 //
wim 8:03116f75b66e 207 void TextLCD::setAddress(int column, int row) {
wim 8:03116f75b66e 208
wim 8:03116f75b66e 209 locate(column, row);
wim 8:03116f75b66e 210
wim 8:03116f75b66e 211 int addr = getAddress(column, row);
wim 8:03116f75b66e 212
wim 8:03116f75b66e 213 writeCommand(0x80 | addr);
wim 8:03116f75b66e 214 }
simon 1:ac48b187213c 215
simon 1:ac48b187213c 216 int TextLCD::columns() {
simon 1:ac48b187213c 217 switch (_type) {
wim 8:03116f75b66e 218 case LCD8x1:
wim 8:03116f75b66e 219 case LCD8x2:
wim 8:03116f75b66e 220 return 8;
wim 8:03116f75b66e 221
simon 1:ac48b187213c 222 case LCD16x2:
simon 1:ac48b187213c 223 case LCD16x2B:
wim 8:03116f75b66e 224 case LCD16x4:
wim 8:03116f75b66e 225 return 16;
wim 8:03116f75b66e 226
wim 8:03116f75b66e 227 case LCD20x2:
wim 8:03116f75b66e 228 case LCD20x4:
wim 8:03116f75b66e 229 return 20;
wim 8:03116f75b66e 230
wim 8:03116f75b66e 231 case LCD24x2:
wim 8:03116f75b66e 232 return 24;
wim 9:0893d986e717 233
wim 9:0893d986e717 234 case LCD40x2:
wim 9:0893d986e717 235 return 40;
wim 8:03116f75b66e 236
wim 8:03116f75b66e 237 // Should never get here.
simon 1:ac48b187213c 238 default:
wim 8:03116f75b66e 239 return 0;
simon 1:ac48b187213c 240 }
simon 1:ac48b187213c 241 }
simon 1:ac48b187213c 242
simon 1:ac48b187213c 243 int TextLCD::rows() {
simon 1:ac48b187213c 244 switch (_type) {
wim 8:03116f75b66e 245 case LCD8x1:
wim 8:03116f75b66e 246 return 1;
wim 8:03116f75b66e 247
wim 8:03116f75b66e 248 case LCD8x2:
simon 1:ac48b187213c 249 case LCD16x2:
simon 1:ac48b187213c 250 case LCD16x2B:
simon 1:ac48b187213c 251 case LCD20x2:
wim 8:03116f75b66e 252 case LCD24x2:
wim 9:0893d986e717 253 case LCD40x2:
wim 8:03116f75b66e 254 return 2;
wim 8:03116f75b66e 255
wim 8:03116f75b66e 256 case LCD16x4:
wim 8:03116f75b66e 257 case LCD20x4:
wim 8:03116f75b66e 258 return 4;
wim 8:03116f75b66e 259
simon 1:ac48b187213c 260 default:
wim 8:03116f75b66e 261 return 0;
simon 1:ac48b187213c 262 }
simon 1:ac48b187213c 263 }