This library is designed to work with LCD screens on the I2C bus. This library is an import of arduino library LiquidCrystal_I2C. This library was tested on the Nucleo F103 debug card using the LCD module 1602A.
Dependents: mbed-os-example-mbed6-wifi_MY_SOCKET_rigtech_copy_
LiquidCrystal_I2C.cpp@0:824096cc05af, 2017-05-19 (annotated)
- Committer:
- Yar
- Date:
- Fri May 19 18:21:24 2017 +0000
- Revision:
- 0:824096cc05af
Import arduino library for working with LCD screen. Checked work with the LCD display 1602A, with the control controller ks0066U.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Yar | 0:824096cc05af | 1 | #include "LiquidCrystal_I2C.h" |
Yar | 0:824096cc05af | 2 | #include "mbed.h" |
Yar | 0:824096cc05af | 3 | |
Yar | 0:824096cc05af | 4 | // When the display powers up, it is configured as follows: |
Yar | 0:824096cc05af | 5 | // |
Yar | 0:824096cc05af | 6 | // 1. Display clear |
Yar | 0:824096cc05af | 7 | // 2. Function set: |
Yar | 0:824096cc05af | 8 | // DL = 1; 8-bit interface data |
Yar | 0:824096cc05af | 9 | // N = 0; 1-line display |
Yar | 0:824096cc05af | 10 | // F = 0; 5x8 dot character font |
Yar | 0:824096cc05af | 11 | // 3. Display on/off control: |
Yar | 0:824096cc05af | 12 | // D = 0; Display off |
Yar | 0:824096cc05af | 13 | // C = 0; Cursor off |
Yar | 0:824096cc05af | 14 | // B = 0; Blinking off |
Yar | 0:824096cc05af | 15 | // 4. Entry mode set: |
Yar | 0:824096cc05af | 16 | // I/D = 1; Increment by 1 |
Yar | 0:824096cc05af | 17 | // S = 0; No shift |
Yar | 0:824096cc05af | 18 | // |
Yar | 0:824096cc05af | 19 | // Note, however, that resetting the Arduino doesn't reset the LCD, so we |
Yar | 0:824096cc05af | 20 | // can't assume that its in that state when a sketch starts (and the |
Yar | 0:824096cc05af | 21 | // LiquidCrystal constructor is called). |
Yar | 0:824096cc05af | 22 | |
Yar | 0:824096cc05af | 23 | |
Yar | 0:824096cc05af | 24 | I2C _i2c(PB_11, PB_10); // SDA, SCL |
Yar | 0:824096cc05af | 25 | |
Yar | 0:824096cc05af | 26 | LiquidCrystal_I2C::LiquidCrystal_I2C(unsigned char lcd_addr, unsigned char lcd_cols, unsigned char lcd_rows, unsigned char charsize) |
Yar | 0:824096cc05af | 27 | { |
Yar | 0:824096cc05af | 28 | _addr = lcd_addr; |
Yar | 0:824096cc05af | 29 | _cols = lcd_cols; |
Yar | 0:824096cc05af | 30 | _rows = lcd_rows; |
Yar | 0:824096cc05af | 31 | _charsize = charsize; |
Yar | 0:824096cc05af | 32 | _backlightval = LCD_BACKLIGHT; |
Yar | 0:824096cc05af | 33 | } |
Yar | 0:824096cc05af | 34 | |
Yar | 0:824096cc05af | 35 | void LiquidCrystal_I2C::begin() { |
Yar | 0:824096cc05af | 36 | //Wire.begin(); |
Yar | 0:824096cc05af | 37 | _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; |
Yar | 0:824096cc05af | 38 | |
Yar | 0:824096cc05af | 39 | if (_rows > 1) { |
Yar | 0:824096cc05af | 40 | _displayfunction |= LCD_2LINE; |
Yar | 0:824096cc05af | 41 | } |
Yar | 0:824096cc05af | 42 | |
Yar | 0:824096cc05af | 43 | // for some 1 line displays you can select a 10 pixel high font |
Yar | 0:824096cc05af | 44 | if ((_charsize != 0) && (_rows == 1)) { |
Yar | 0:824096cc05af | 45 | _displayfunction |= LCD_5x10DOTS; |
Yar | 0:824096cc05af | 46 | } |
Yar | 0:824096cc05af | 47 | |
Yar | 0:824096cc05af | 48 | // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! |
Yar | 0:824096cc05af | 49 | // according to datasheet, we need at least 40ms after power rises above 2.7V |
Yar | 0:824096cc05af | 50 | // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 |
Yar | 0:824096cc05af | 51 | wait_ms(50); |
Yar | 0:824096cc05af | 52 | |
Yar | 0:824096cc05af | 53 | // Now we pull both RS and R/W low to begin commands |
Yar | 0:824096cc05af | 54 | expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) |
Yar | 0:824096cc05af | 55 | wait_ms(1000); |
Yar | 0:824096cc05af | 56 | |
Yar | 0:824096cc05af | 57 | //put the LCD into 4 bit mode |
Yar | 0:824096cc05af | 58 | // this is according to the hitachi HD44780 datasheet |
Yar | 0:824096cc05af | 59 | // figure 24, pg 46 |
Yar | 0:824096cc05af | 60 | |
Yar | 0:824096cc05af | 61 | // we start in 8bit mode, try to set 4 bit mode |
Yar | 0:824096cc05af | 62 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 63 | wait_us(4500); // wait min 4.1ms |
Yar | 0:824096cc05af | 64 | |
Yar | 0:824096cc05af | 65 | // second try |
Yar | 0:824096cc05af | 66 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 67 | wait_us(4500); // wait min 4.1ms |
Yar | 0:824096cc05af | 68 | |
Yar | 0:824096cc05af | 69 | // third go! |
Yar | 0:824096cc05af | 70 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 71 | wait_us(150); |
Yar | 0:824096cc05af | 72 | |
Yar | 0:824096cc05af | 73 | // finally, set to 4-bit interface |
Yar | 0:824096cc05af | 74 | write4bits(0x02 << 4); |
Yar | 0:824096cc05af | 75 | |
Yar | 0:824096cc05af | 76 | // set # lines, font size, etc. |
Yar | 0:824096cc05af | 77 | command(LCD_FUNCTIONSET | _displayfunction); |
Yar | 0:824096cc05af | 78 | |
Yar | 0:824096cc05af | 79 | // turn the display on with no cursor or blinking default |
Yar | 0:824096cc05af | 80 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; |
Yar | 0:824096cc05af | 81 | display(); |
Yar | 0:824096cc05af | 82 | |
Yar | 0:824096cc05af | 83 | // clear it off |
Yar | 0:824096cc05af | 84 | clear(); |
Yar | 0:824096cc05af | 85 | |
Yar | 0:824096cc05af | 86 | // Initialize to default text direction (for roman languages) |
Yar | 0:824096cc05af | 87 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; |
Yar | 0:824096cc05af | 88 | |
Yar | 0:824096cc05af | 89 | // set the entry mode |
Yar | 0:824096cc05af | 90 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 91 | |
Yar | 0:824096cc05af | 92 | home(); |
Yar | 0:824096cc05af | 93 | } |
Yar | 0:824096cc05af | 94 | |
Yar | 0:824096cc05af | 95 | /********** high level commands, for the user! */ |
Yar | 0:824096cc05af | 96 | void LiquidCrystal_I2C::clear(){ |
Yar | 0:824096cc05af | 97 | command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero |
Yar | 0:824096cc05af | 98 | wait_us(2000); // this command takes a long time! |
Yar | 0:824096cc05af | 99 | } |
Yar | 0:824096cc05af | 100 | |
Yar | 0:824096cc05af | 101 | void LiquidCrystal_I2C::home(){ |
Yar | 0:824096cc05af | 102 | command(LCD_RETURNHOME); // set cursor position to zero |
Yar | 0:824096cc05af | 103 | wait_us(2000); // this command takes a long time! |
Yar | 0:824096cc05af | 104 | } |
Yar | 0:824096cc05af | 105 | |
Yar | 0:824096cc05af | 106 | void LiquidCrystal_I2C::setCursor(unsigned char col, unsigned char row){ |
Yar | 0:824096cc05af | 107 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; |
Yar | 0:824096cc05af | 108 | if (row > _rows) { |
Yar | 0:824096cc05af | 109 | row = _rows-1; // we count rows starting w/0 |
Yar | 0:824096cc05af | 110 | } |
Yar | 0:824096cc05af | 111 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); |
Yar | 0:824096cc05af | 112 | } |
Yar | 0:824096cc05af | 113 | |
Yar | 0:824096cc05af | 114 | // Turn the display on/off (quickly) |
Yar | 0:824096cc05af | 115 | void LiquidCrystal_I2C::noDisplay() { |
Yar | 0:824096cc05af | 116 | _displaycontrol &= ~LCD_DISPLAYON; |
Yar | 0:824096cc05af | 117 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 118 | } |
Yar | 0:824096cc05af | 119 | void LiquidCrystal_I2C::display() { |
Yar | 0:824096cc05af | 120 | _displaycontrol |= LCD_DISPLAYON; |
Yar | 0:824096cc05af | 121 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 122 | } |
Yar | 0:824096cc05af | 123 | |
Yar | 0:824096cc05af | 124 | // Turns the underline cursor on/off |
Yar | 0:824096cc05af | 125 | void LiquidCrystal_I2C::noCursor() { |
Yar | 0:824096cc05af | 126 | _displaycontrol &= ~LCD_CURSORON; |
Yar | 0:824096cc05af | 127 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 128 | } |
Yar | 0:824096cc05af | 129 | void LiquidCrystal_I2C::cursor() { |
Yar | 0:824096cc05af | 130 | _displaycontrol |= LCD_CURSORON; |
Yar | 0:824096cc05af | 131 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 132 | } |
Yar | 0:824096cc05af | 133 | |
Yar | 0:824096cc05af | 134 | // Turn on and off the blinking cursor |
Yar | 0:824096cc05af | 135 | void LiquidCrystal_I2C::noBlink() { |
Yar | 0:824096cc05af | 136 | _displaycontrol &= ~LCD_BLINKON; |
Yar | 0:824096cc05af | 137 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 138 | } |
Yar | 0:824096cc05af | 139 | void LiquidCrystal_I2C::blink() { |
Yar | 0:824096cc05af | 140 | _displaycontrol |= LCD_BLINKON; |
Yar | 0:824096cc05af | 141 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 142 | } |
Yar | 0:824096cc05af | 143 | |
Yar | 0:824096cc05af | 144 | // These commands scroll the display without changing the RAM |
Yar | 0:824096cc05af | 145 | void LiquidCrystal_I2C::scrollDisplayLeft(void) { |
Yar | 0:824096cc05af | 146 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); |
Yar | 0:824096cc05af | 147 | } |
Yar | 0:824096cc05af | 148 | void LiquidCrystal_I2C::scrollDisplayRight(void) { |
Yar | 0:824096cc05af | 149 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); |
Yar | 0:824096cc05af | 150 | } |
Yar | 0:824096cc05af | 151 | |
Yar | 0:824096cc05af | 152 | // This is for text that flows Left to Right |
Yar | 0:824096cc05af | 153 | void LiquidCrystal_I2C::leftToRight(void) { |
Yar | 0:824096cc05af | 154 | _displaymode |= LCD_ENTRYLEFT; |
Yar | 0:824096cc05af | 155 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 156 | } |
Yar | 0:824096cc05af | 157 | |
Yar | 0:824096cc05af | 158 | // This is for text that flows Right to Left |
Yar | 0:824096cc05af | 159 | void LiquidCrystal_I2C::rightToLeft(void) { |
Yar | 0:824096cc05af | 160 | _displaymode &= ~LCD_ENTRYLEFT; |
Yar | 0:824096cc05af | 161 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 162 | } |
Yar | 0:824096cc05af | 163 | |
Yar | 0:824096cc05af | 164 | // This will 'right justify' text from the cursor |
Yar | 0:824096cc05af | 165 | void LiquidCrystal_I2C::autoscroll(void) { |
Yar | 0:824096cc05af | 166 | _displaymode |= LCD_ENTRYSHIFTINCREMENT; |
Yar | 0:824096cc05af | 167 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 168 | } |
Yar | 0:824096cc05af | 169 | |
Yar | 0:824096cc05af | 170 | // This will 'left justify' text from the cursor |
Yar | 0:824096cc05af | 171 | void LiquidCrystal_I2C::noAutoscroll(void) { |
Yar | 0:824096cc05af | 172 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; |
Yar | 0:824096cc05af | 173 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 174 | } |
Yar | 0:824096cc05af | 175 | |
Yar | 0:824096cc05af | 176 | // Allows us to fill the first 8 CGRAM locations |
Yar | 0:824096cc05af | 177 | // with custom characters |
Yar | 0:824096cc05af | 178 | void LiquidCrystal_I2C::createChar(unsigned char location, unsigned char charmap[]) { |
Yar | 0:824096cc05af | 179 | location &= 0x7; // we only have 8 locations 0-7 |
Yar | 0:824096cc05af | 180 | command(LCD_SETCGRAMADDR | (location << 3)); |
Yar | 0:824096cc05af | 181 | for (int i=0; i<8; i++) { |
Yar | 0:824096cc05af | 182 | write(charmap[i]); |
Yar | 0:824096cc05af | 183 | } |
Yar | 0:824096cc05af | 184 | } |
Yar | 0:824096cc05af | 185 | |
Yar | 0:824096cc05af | 186 | // Turn the (optional) backlight off/on |
Yar | 0:824096cc05af | 187 | void LiquidCrystal_I2C::noBacklight(void) { |
Yar | 0:824096cc05af | 188 | _backlightval=LCD_NOBACKLIGHT; |
Yar | 0:824096cc05af | 189 | expanderWrite(0); |
Yar | 0:824096cc05af | 190 | } |
Yar | 0:824096cc05af | 191 | |
Yar | 0:824096cc05af | 192 | void LiquidCrystal_I2C::backlight(void) { |
Yar | 0:824096cc05af | 193 | _backlightval=LCD_BACKLIGHT; |
Yar | 0:824096cc05af | 194 | expanderWrite(0); |
Yar | 0:824096cc05af | 195 | } |
Yar | 0:824096cc05af | 196 | bool LiquidCrystal_I2C::getBacklight() { |
Yar | 0:824096cc05af | 197 | return _backlightval == LCD_BACKLIGHT; |
Yar | 0:824096cc05af | 198 | } |
Yar | 0:824096cc05af | 199 | |
Yar | 0:824096cc05af | 200 | |
Yar | 0:824096cc05af | 201 | /*********** mid level commands, for sending data/cmds */ |
Yar | 0:824096cc05af | 202 | |
Yar | 0:824096cc05af | 203 | inline void LiquidCrystal_I2C::command(unsigned char value) { |
Yar | 0:824096cc05af | 204 | send(value, 0); |
Yar | 0:824096cc05af | 205 | } |
Yar | 0:824096cc05af | 206 | |
Yar | 0:824096cc05af | 207 | inline int LiquidCrystal_I2C::write(unsigned char value) { |
Yar | 0:824096cc05af | 208 | send(value, Rs); |
Yar | 0:824096cc05af | 209 | return 1; |
Yar | 0:824096cc05af | 210 | } |
Yar | 0:824096cc05af | 211 | |
Yar | 0:824096cc05af | 212 | |
Yar | 0:824096cc05af | 213 | /************ low level data pushing commands **********/ |
Yar | 0:824096cc05af | 214 | |
Yar | 0:824096cc05af | 215 | // write either command or data |
Yar | 0:824096cc05af | 216 | void LiquidCrystal_I2C::send(unsigned char value, unsigned char mode) { |
Yar | 0:824096cc05af | 217 | unsigned char highnib=value&0xf0; |
Yar | 0:824096cc05af | 218 | unsigned char lownib=(value<<4)&0xf0; |
Yar | 0:824096cc05af | 219 | write4bits((highnib)|mode); |
Yar | 0:824096cc05af | 220 | write4bits((lownib)|mode); |
Yar | 0:824096cc05af | 221 | } |
Yar | 0:824096cc05af | 222 | |
Yar | 0:824096cc05af | 223 | void LiquidCrystal_I2C::write4bits(unsigned char value) { |
Yar | 0:824096cc05af | 224 | expanderWrite(value); |
Yar | 0:824096cc05af | 225 | pulseEnable(value); |
Yar | 0:824096cc05af | 226 | } |
Yar | 0:824096cc05af | 227 | |
Yar | 0:824096cc05af | 228 | void LiquidCrystal_I2C::expanderWrite(unsigned char _data){ |
Yar | 0:824096cc05af | 229 | char data_write[2]; |
Yar | 0:824096cc05af | 230 | data_write[0] = _data | _backlightval; |
Yar | 0:824096cc05af | 231 | //Wire.beginTransmission(_addr); |
Yar | 0:824096cc05af | 232 | //Wire.write((int)(_data) | _backlightval); |
Yar | 0:824096cc05af | 233 | //Wire.endTransmission(); |
Yar | 0:824096cc05af | 234 | _i2c.write(_addr, data_write, 1, 0); |
Yar | 0:824096cc05af | 235 | _i2c.stop(); |
Yar | 0:824096cc05af | 236 | } |
Yar | 0:824096cc05af | 237 | |
Yar | 0:824096cc05af | 238 | void LiquidCrystal_I2C::pulseEnable(unsigned char _data){ |
Yar | 0:824096cc05af | 239 | expanderWrite(_data | En); // En high |
Yar | 0:824096cc05af | 240 | wait_us(1); // enable pulse must be >450ns |
Yar | 0:824096cc05af | 241 | |
Yar | 0:824096cc05af | 242 | expanderWrite(_data & ~En); // En low |
Yar | 0:824096cc05af | 243 | wait_us(50); // commands need > 37us to settle |
Yar | 0:824096cc05af | 244 | } |
Yar | 0:824096cc05af | 245 | |
Yar | 0:824096cc05af | 246 | void LiquidCrystal_I2C::load_custom_character(unsigned char char_num, unsigned char *rows){ |
Yar | 0:824096cc05af | 247 | createChar(char_num, rows); |
Yar | 0:824096cc05af | 248 | } |
Yar | 0:824096cc05af | 249 | |
Yar | 0:824096cc05af | 250 | void LiquidCrystal_I2C::setBacklight(unsigned char new_val){ |
Yar | 0:824096cc05af | 251 | if (new_val) { |
Yar | 0:824096cc05af | 252 | backlight(); // turn backlight on |
Yar | 0:824096cc05af | 253 | } else { |
Yar | 0:824096cc05af | 254 | noBacklight(); // turn backlight off |
Yar | 0:824096cc05af | 255 | } |
Yar | 0:824096cc05af | 256 | } |
Yar | 0:824096cc05af | 257 | |
Yar | 0:824096cc05af | 258 | void LiquidCrystal_I2C::printstr(const char c[]){ |
Yar | 0:824096cc05af | 259 | //This function is not identical to the function used for "real" I2C displays |
Yar | 0:824096cc05af | 260 | //it's here so the user sketch doesn't have to be changed |
Yar | 0:824096cc05af | 261 | //print(c); |
Yar | 0:824096cc05af | 262 | } |
Yar | 0:824096cc05af | 263 | |
Yar | 0:824096cc05af | 264 | int LiquidCrystal_I2C::print(const char* text) { |
Yar | 0:824096cc05af | 265 | |
Yar | 0:824096cc05af | 266 | while (*text !=0) { |
Yar | 0:824096cc05af | 267 | //_putc(*text); |
Yar | 0:824096cc05af | 268 | send(*text, Rs); |
Yar | 0:824096cc05af | 269 | text++; |
Yar | 0:824096cc05af | 270 | } |
Yar | 0:824096cc05af | 271 | return 0; |
Yar | 0:824096cc05af | 272 | } |
Yar | 0:824096cc05af | 273 | |
Yar | 0:824096cc05af | 274 | /* |
Yar | 0:824096cc05af | 275 | void lcd_dat(unsigned char p) |
Yar | 0:824096cc05af | 276 | { |
Yar | 0:824096cc05af | 277 | PORTC |= (1 << RS)|(1 << EN); // RS = 1, EN = 1 (начало записи команды в LCD) |
Yar | 0:824096cc05af | 278 | PORTD = p; // Вывод команды на шину DB0-7 LCD |
Yar | 0:824096cc05af | 279 | _delay_us(100); // Длительность сигнала EN |
Yar | 0:824096cc05af | 280 | PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) |
Yar | 0:824096cc05af | 281 | _delay_us(100); // Пауза для выполнения команды |
Yar | 0:824096cc05af | 282 | } |
Yar | 0:824096cc05af | 283 | */ |