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:
simon
Date:
Thu May 27 13:44:15 2010 +0000
Revision:
1:ac48b187213c
Parent:
0:edfb85c53631
Child:
2:227356c7d12c

        

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 1:ac48b187213c 2 * Copyright (c) 2007-2010, sford
simon 1:ac48b187213c 3 *
simon 1:ac48b187213c 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 5 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 6 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 8 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 9 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 10 *
simon 1:ac48b187213c 11 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 12 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 13 *
simon 1:ac48b187213c 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 20 * THE SOFTWARE.
simon 1:ac48b187213c 21 */
simon 1:ac48b187213c 22
simon 1:ac48b187213c 23 #include "TextLCD.h"
simon 1:ac48b187213c 24 #include "mbed.h"
simon 1:ac48b187213c 25
simon 1:ac48b187213c 26 /* useful info found at http://www.a-netz.de/lcd.en.php
simon 1:ac48b187213c 27 *
simon 1:ac48b187213c 28 * Initialisation
simon 1:ac48b187213c 29 * ==============
simon 1:ac48b187213c 30 *
simon 1:ac48b187213c 31 * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state
simon 1:ac48b187213c 32 *
simon 1:ac48b187213c 33 * - wait approximately 15 ms so the display is ready to execute commands
simon 1:ac48b187213c 34 * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now).
simon 1:ac48b187213c 35 * - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command.
simon 1:ac48b187213c 36 * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now.
simon 1:ac48b187213c 37 * - Execute the "clear display" command
simon 1:ac48b187213c 38 *
simon 1:ac48b187213c 39 * Timing
simon 1:ac48b187213c 40 * ======
simon 1:ac48b187213c 41 *
simon 1:ac48b187213c 42 * Nearly all commands transmitted to the display need 40us for execution.
simon 1:ac48b187213c 43 * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position"
simon 1:ac48b187213c 44 * These commands need 1.64ms for execution. These timings are valid for all displays working with an
simon 1:ac48b187213c 45 * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you
simon 1:ac48b187213c 46 * can use the busy flag to test if the display is ready to accept the next command.
simon 1:ac48b187213c 47 *
simon 1:ac48b187213c 48 * _e is kept high apart from calling clock
simon 1:ac48b187213c 49 * _rw is kept 0 (write) apart from actions that uyse it differently
simon 1:ac48b187213c 50 * _rs is set by the data/command writes
simon 1:ac48b187213c 51 */
simon 1:ac48b187213c 52
simon 1:ac48b187213c 53 TextLCD::TextLCD(PinName rs, PinName e, PinName d0, PinName d1,
simon 1:ac48b187213c 54 PinName d2, PinName d3, LCDType type) : _rs(rs),
simon 1:ac48b187213c 55 _e(e), _d(d0, d1, d2, d3),
simon 1:ac48b187213c 56 _type(type) {
simon 1:ac48b187213c 57
simon 1:ac48b187213c 58 _e = 1;
simon 1:ac48b187213c 59 _rs = 0; // command mode
simon 1:ac48b187213c 60
simon 1:ac48b187213c 61 wait(0.015); // Wait 15ms to ensure powered up
simon 1:ac48b187213c 62
simon 1:ac48b187213c 63 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
simon 1:ac48b187213c 64 for (int i=0; i<3; i++) {
simon 1:ac48b187213c 65 writeByte(0x3);
simon 1:ac48b187213c 66 wait(0.00164); // this command takes 1.64ms, so wait for it
simon 1:ac48b187213c 67 }
simon 1:ac48b187213c 68 writeByte(0x2); // 4-bit mode
simon 1:ac48b187213c 69 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 70
simon 1:ac48b187213c 71 writeCommand(0x28); // Function set 001 BW N F - -
simon 1:ac48b187213c 72 writeCommand(0x0C);
simon 1:ac48b187213c 73 writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
simon 1:ac48b187213c 74 cls();
simon 1:ac48b187213c 75 }
simon 1:ac48b187213c 76
simon 1:ac48b187213c 77 void TextLCD::character(int column, int row, int c) {
simon 1:ac48b187213c 78 int a = address(column, row);
simon 1:ac48b187213c 79 writeCommand(a);
simon 1:ac48b187213c 80 writeData(c);
simon 1:ac48b187213c 81 }
simon 1:ac48b187213c 82
simon 1:ac48b187213c 83 void TextLCD::cls() {
simon 1:ac48b187213c 84 writeCommand(0x01); // cls, and set cursor to 0
simon 1:ac48b187213c 85 wait(0.00164f); // This command takes 1.64 ms
simon 1:ac48b187213c 86 locate(0, 0);
simon 1:ac48b187213c 87 }
simon 1:ac48b187213c 88
simon 1:ac48b187213c 89 void TextLCD::locate(int column, int row) {
simon 1:ac48b187213c 90 _column = column;
simon 1:ac48b187213c 91 _row = row;
simon 1:ac48b187213c 92 }
simon 1:ac48b187213c 93
simon 1:ac48b187213c 94 int TextLCD::_putc(int value) {
simon 1:ac48b187213c 95 if (value == '\n') {
simon 1:ac48b187213c 96 _column = 0;
simon 1:ac48b187213c 97 _row++;
simon 1:ac48b187213c 98 if (_row >= rows()) {
simon 1:ac48b187213c 99 _row = 0;
simon 1:ac48b187213c 100 }
simon 1:ac48b187213c 101 } else {
simon 1:ac48b187213c 102 character(_column, _row, value);
simon 1:ac48b187213c 103 _column++;
simon 1:ac48b187213c 104 if (_column >= columns()) {
simon 1:ac48b187213c 105 _column = 0;
simon 1:ac48b187213c 106 _row++;
simon 1:ac48b187213c 107 if (_row >= rows()) {
simon 1:ac48b187213c 108 _row = 0;
simon 1:ac48b187213c 109 }
simon 1:ac48b187213c 110 }
simon 1:ac48b187213c 111 }
simon 1:ac48b187213c 112 return value;
simon 1:ac48b187213c 113 }
simon 1:ac48b187213c 114
simon 1:ac48b187213c 115 int TextLCD::_getc() {
simon 1:ac48b187213c 116 return -1;
simon 1:ac48b187213c 117 }
simon 1:ac48b187213c 118
simon 1:ac48b187213c 119 void TextLCD::writeByte(int value) {
simon 1:ac48b187213c 120 _d = value >> 4;
simon 1:ac48b187213c 121 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 122 _e = 0;
simon 1:ac48b187213c 123 wait(0.000040f);
simon 1:ac48b187213c 124 _e = 1;
simon 1:ac48b187213c 125 _d = value >> 0;
simon 1:ac48b187213c 126 wait(0.000040f);
simon 1:ac48b187213c 127 _e = 0;
simon 1:ac48b187213c 128 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 129 _e = 1;
simon 1:ac48b187213c 130 }
simon 1:ac48b187213c 131
simon 1:ac48b187213c 132 void TextLCD::writeCommand(int command) {
simon 1:ac48b187213c 133 _rs = 0;
simon 1:ac48b187213c 134 writeByte(command);
simon 1:ac48b187213c 135 }
simon 1:ac48b187213c 136
simon 1:ac48b187213c 137 void TextLCD::writeData(int data) {
simon 1:ac48b187213c 138 _rs = 1;
simon 1:ac48b187213c 139 writeByte(data);
simon 1:ac48b187213c 140 }
simon 1:ac48b187213c 141
simon 1:ac48b187213c 142 int TextLCD::address(int column, int row) {
simon 1:ac48b187213c 143 switch (_type) {
simon 1:ac48b187213c 144 case LCD20x4:
simon 1:ac48b187213c 145 switch (row) {
simon 1:ac48b187213c 146 case 0:
simon 1:ac48b187213c 147 return 0x80 + column;
simon 1:ac48b187213c 148 case 1:
simon 1:ac48b187213c 149 return 0xc0 + column;
simon 1:ac48b187213c 150 case 2:
simon 1:ac48b187213c 151 return 0x94 + column;
simon 1:ac48b187213c 152 case 3:
simon 1:ac48b187213c 153 return 0xd4 + column;
simon 1:ac48b187213c 154 }
simon 1:ac48b187213c 155 case LCD16x2B:
simon 1:ac48b187213c 156 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 157 case LCD16x2:
simon 1:ac48b187213c 158 case LCD20x2:
simon 1:ac48b187213c 159 default:
simon 1:ac48b187213c 160 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 161 }
simon 1:ac48b187213c 162 }
simon 1:ac48b187213c 163
simon 1:ac48b187213c 164 int TextLCD::columns() {
simon 1:ac48b187213c 165 switch (_type) {
simon 1:ac48b187213c 166 case LCD20x4:
simon 1:ac48b187213c 167 case LCD20x2:
simon 1:ac48b187213c 168 return 20;
simon 1:ac48b187213c 169 case LCD16x2:
simon 1:ac48b187213c 170 case LCD16x2B:
simon 1:ac48b187213c 171 default:
simon 1:ac48b187213c 172 return 16;
simon 1:ac48b187213c 173 }
simon 1:ac48b187213c 174 }
simon 1:ac48b187213c 175
simon 1:ac48b187213c 176 int TextLCD::rows() {
simon 1:ac48b187213c 177 switch (_type) {
simon 1:ac48b187213c 178 case LCD20x4:
simon 1:ac48b187213c 179 return 4;
simon 1:ac48b187213c 180 case LCD16x2:
simon 1:ac48b187213c 181 case LCD16x2B:
simon 1:ac48b187213c 182 case LCD20x2:
simon 1:ac48b187213c 183 default:
simon 1:ac48b187213c 184 return 2;
simon 1:ac48b187213c 185 }
simon 1:ac48b187213c 186 }