Improved version of Simon Ford's TextDisplay library, with addressing and timing fixes. Supports up to 20x4 text displays.
TextLCD.cpp
00001 /* mbed TextLCD Library 00002 * Copyright (c) 2007-2009 sford 00003 * Released under the MIT License: http://mbed.org/license/mit 00004 * 00005 * Modified by Ned Konz to provide better support for 4-line LCDs and ones with other controller chips. 00006 */ 00007 00008 #include "TextLCD.h" 00009 #include "mbed.h" 00010 00011 /* 00012 * useful info found at http://www.a-netz.de/lcd.en.php 00013 * 00014 * Initialisation 00015 * ============== 00016 * 00017 * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state 00018 * 00019 * - wait approximately 15 ms so the display is ready to execute commands 00020 * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now). 00021 * - 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. 00022 * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now. 00023 * - Execute the "clear display" command 00024 * 00025 * Timing 00026 * ====== 00027 * 00028 * Nearly all commands transmitted to the display need 40us for execution. 00029 * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position" 00030 * These commands need 1.64ms for execution. These timings are valid for all displays working with an 00031 * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you 00032 * can use the busy flag to test if the display is ready to accept the next command. 00033 * 00034 * _e is kept low except when being used. 00035 * _rw is kept 0 (write) apart from actions that use it differently 00036 * _rs is set by the data/command writes 00037 */ 00038 00039 TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, 00040 PinName d2, PinName d3, uint16_t rows, uint16_t cols) : _rw(rw), _rs(rs), 00041 _e(e), _d(d0, d1, d2, d3), _rows(rows), _columns(cols) { 00042 00043 _rw = 0; 00044 wait_us(1); // min. 100nsec delay 00045 _e = 0; 00046 _rs = 0; // command mode 00047 _d.output(); 00048 00049 reset(); 00050 cls(); 00051 } 00052 00053 void TextLCD::reset() { 00054 wait_ms(15); 00055 // e is low at this point, as is rw. 00056 // 2. Send 0x3 and wait 150 ms (will stay in 8-bit mode if already there) 00057 writeHalfByte(0x3); 00058 wait_ms(5); 00059 // 3. Send 0x3 and wait 150 ms (will go to 8-bit mode if was in 4-bit without any garbage nibble) 00060 writeHalfByte(0x3); 00061 wait_ms(5); 00062 // 4. Send 0x3 and wait 250 ms (will go to 8-bit mode even if garbage nibble was previously received) 00063 writeHalfByte(0x3); 00064 wait_ms(5); 00065 // 5. Send 0x2 and wait 200 ms (should go to 4-bit mode now) 00066 writeHalfByte(0x2); 00067 wait_ms(5); 00068 // 7. Send LCD setup sequence (eg 0x2, 0x8 (=0x28), 0x0, 0x8 (=0x08), etc.) 00069 writeCommand(0x28); // Function set 001 BW N F - - 00070 wait_ms(15); 00071 00072 writeCommand(0x08); // display off, cursor invisible 00073 wait_ms(15); 00074 00075 writeCommand(0x01); 00076 wait_ms(15); // 1.64ms command 00077 00078 writeCommand(0x0C); // display enabled, cursor invisible 00079 wait_ms(15); 00080 00081 writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes 00082 wait_ms(15); 00083 00084 locate(0,0); 00085 } 00086 00087 // memory starts at 0x80, and is 0x40 chars long per row 00088 // However, rows 2 and 3 of 4-line displays are actually adjacent to rows 0 and 1. 00089 // 16x4 displays are addressed the same way as 20x4 ones. 00090 00091 void TextLCD::character(uint16_t column, uint16_t row, int c) { 00092 int address; 00093 address = 0x80 + ((row & ~2) * 0x40) + column; 00094 if (row > 1) 00095 address += 20; 00096 writeCommand(address); 00097 writeData(c); 00098 } 00099 00100 void TextLCD::writeHalfByte(uint16_t value) { 00101 _e = 1; 00102 wait_us(1); 00103 _d = value & 0x0F; // send data on bus 00104 wait_us(1); // setup time 00105 _e = 0; // strobe 00106 wait_us(1); // hold time 00107 } 00108 00109 void TextLCD::writeByte(uint16_t value) { 00110 writeHalfByte(value>>4); 00111 writeHalfByte(value); 00112 } 00113 00114 void TextLCD::writeCommand(uint16_t command) { 00115 _rs = 0; 00116 writeByte(command); 00117 waitUntilDone(); 00118 } 00119 00120 void TextLCD::writeData(uint16_t data) { 00121 _rs = 1; 00122 writeByte(data); 00123 waitUntilDone(); 00124 } 00125 00126 void TextLCD::cls() { 00127 writeCommand(0x01); 00128 wait_us(2000); // 1.64ms command 00129 locate(0,0); 00130 } 00131 00132 // This should be changed to use readAddressAndBusy() when that works. 00133 void TextLCD::waitUntilDone() { 00134 wait_us(60); 00135 } 00136 00137 // Return the busy/address byte. 00138 // The busy flag is the high bit. 00139 // Not yet working reliably. 00140 uint16_t TextLCD::readAddressAndBusy() { 00141 _d.input(); 00142 _rw = 1; 00143 wait_us(1); 00144 _e = 1; 00145 wait_us(1); 00146 _e = 0; 00147 00148 uint16_t retval = _d.read() << 4; 00149 00150 wait_us(1); 00151 _e = 1; 00152 wait_us(1); 00153 _e = 0; 00154 00155 retval |= _d.read(); 00156 _rw = 0; 00157 00158 _d.output(); 00159 return retval; 00160 } 00161
Generated on Thu Jul 14 2022 21:44:21 by 1.7.2