wifi_mqtt_hcsr04_lcd1602_i2c
LiquidCrystal_I2C.cpp@1:e045394f109e, 2022-01-20 (annotated)
- Committer:
- awali
- Date:
- Thu Jan 20 09:26:21 2022 +0000
- Revision:
- 1:e045394f109e
- Parent:
- 0:824096cc05af
1
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 | |
awali | 1:e045394f109e | 24 | I2C _i2c(D14, D15); // 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 |
awali | 1:e045394f109e | 51 | // wait_ms(50); |
awali | 1:e045394f109e | 52 | wait_us(50000); |
Yar | 0:824096cc05af | 53 | |
Yar | 0:824096cc05af | 54 | // Now we pull both RS and R/W low to begin commands |
Yar | 0:824096cc05af | 55 | expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) |
awali | 1:e045394f109e | 56 | // wait_ms(1000); |
awali | 1:e045394f109e | 57 | wait_us(10000); |
Yar | 0:824096cc05af | 58 | |
Yar | 0:824096cc05af | 59 | //put the LCD into 4 bit mode |
Yar | 0:824096cc05af | 60 | // this is according to the hitachi HD44780 datasheet |
Yar | 0:824096cc05af | 61 | // figure 24, pg 46 |
Yar | 0:824096cc05af | 62 | |
Yar | 0:824096cc05af | 63 | // we start in 8bit mode, try to set 4 bit mode |
Yar | 0:824096cc05af | 64 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 65 | wait_us(4500); // wait min 4.1ms |
Yar | 0:824096cc05af | 66 | |
Yar | 0:824096cc05af | 67 | // second try |
Yar | 0:824096cc05af | 68 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 69 | wait_us(4500); // wait min 4.1ms |
Yar | 0:824096cc05af | 70 | |
Yar | 0:824096cc05af | 71 | // third go! |
Yar | 0:824096cc05af | 72 | write4bits(0x03 << 4); |
Yar | 0:824096cc05af | 73 | wait_us(150); |
Yar | 0:824096cc05af | 74 | |
Yar | 0:824096cc05af | 75 | // finally, set to 4-bit interface |
Yar | 0:824096cc05af | 76 | write4bits(0x02 << 4); |
Yar | 0:824096cc05af | 77 | |
Yar | 0:824096cc05af | 78 | // set # lines, font size, etc. |
Yar | 0:824096cc05af | 79 | command(LCD_FUNCTIONSET | _displayfunction); |
Yar | 0:824096cc05af | 80 | |
Yar | 0:824096cc05af | 81 | // turn the display on with no cursor or blinking default |
Yar | 0:824096cc05af | 82 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; |
Yar | 0:824096cc05af | 83 | display(); |
Yar | 0:824096cc05af | 84 | |
Yar | 0:824096cc05af | 85 | // clear it off |
Yar | 0:824096cc05af | 86 | clear(); |
Yar | 0:824096cc05af | 87 | |
Yar | 0:824096cc05af | 88 | // Initialize to default text direction (for roman languages) |
Yar | 0:824096cc05af | 89 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; |
Yar | 0:824096cc05af | 90 | |
Yar | 0:824096cc05af | 91 | // set the entry mode |
Yar | 0:824096cc05af | 92 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 93 | |
Yar | 0:824096cc05af | 94 | home(); |
Yar | 0:824096cc05af | 95 | } |
Yar | 0:824096cc05af | 96 | |
Yar | 0:824096cc05af | 97 | /********** high level commands, for the user! */ |
Yar | 0:824096cc05af | 98 | void LiquidCrystal_I2C::clear(){ |
Yar | 0:824096cc05af | 99 | command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero |
Yar | 0:824096cc05af | 100 | wait_us(2000); // this command takes a long time! |
Yar | 0:824096cc05af | 101 | } |
Yar | 0:824096cc05af | 102 | |
Yar | 0:824096cc05af | 103 | void LiquidCrystal_I2C::home(){ |
Yar | 0:824096cc05af | 104 | command(LCD_RETURNHOME); // set cursor position to zero |
Yar | 0:824096cc05af | 105 | wait_us(2000); // this command takes a long time! |
Yar | 0:824096cc05af | 106 | } |
Yar | 0:824096cc05af | 107 | |
Yar | 0:824096cc05af | 108 | void LiquidCrystal_I2C::setCursor(unsigned char col, unsigned char row){ |
Yar | 0:824096cc05af | 109 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; |
Yar | 0:824096cc05af | 110 | if (row > _rows) { |
Yar | 0:824096cc05af | 111 | row = _rows-1; // we count rows starting w/0 |
Yar | 0:824096cc05af | 112 | } |
Yar | 0:824096cc05af | 113 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); |
Yar | 0:824096cc05af | 114 | } |
Yar | 0:824096cc05af | 115 | |
Yar | 0:824096cc05af | 116 | // Turn the display on/off (quickly) |
Yar | 0:824096cc05af | 117 | void LiquidCrystal_I2C::noDisplay() { |
Yar | 0:824096cc05af | 118 | _displaycontrol &= ~LCD_DISPLAYON; |
Yar | 0:824096cc05af | 119 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 120 | } |
Yar | 0:824096cc05af | 121 | void LiquidCrystal_I2C::display() { |
Yar | 0:824096cc05af | 122 | _displaycontrol |= LCD_DISPLAYON; |
Yar | 0:824096cc05af | 123 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 124 | } |
Yar | 0:824096cc05af | 125 | |
Yar | 0:824096cc05af | 126 | // Turns the underline cursor on/off |
Yar | 0:824096cc05af | 127 | void LiquidCrystal_I2C::noCursor() { |
Yar | 0:824096cc05af | 128 | _displaycontrol &= ~LCD_CURSORON; |
Yar | 0:824096cc05af | 129 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 130 | } |
Yar | 0:824096cc05af | 131 | void LiquidCrystal_I2C::cursor() { |
Yar | 0:824096cc05af | 132 | _displaycontrol |= LCD_CURSORON; |
Yar | 0:824096cc05af | 133 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 134 | } |
Yar | 0:824096cc05af | 135 | |
Yar | 0:824096cc05af | 136 | // Turn on and off the blinking cursor |
Yar | 0:824096cc05af | 137 | void LiquidCrystal_I2C::noBlink() { |
Yar | 0:824096cc05af | 138 | _displaycontrol &= ~LCD_BLINKON; |
Yar | 0:824096cc05af | 139 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 140 | } |
Yar | 0:824096cc05af | 141 | void LiquidCrystal_I2C::blink() { |
Yar | 0:824096cc05af | 142 | _displaycontrol |= LCD_BLINKON; |
Yar | 0:824096cc05af | 143 | command(LCD_DISPLAYCONTROL | _displaycontrol); |
Yar | 0:824096cc05af | 144 | } |
Yar | 0:824096cc05af | 145 | |
Yar | 0:824096cc05af | 146 | // These commands scroll the display without changing the RAM |
Yar | 0:824096cc05af | 147 | void LiquidCrystal_I2C::scrollDisplayLeft(void) { |
Yar | 0:824096cc05af | 148 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); |
Yar | 0:824096cc05af | 149 | } |
Yar | 0:824096cc05af | 150 | void LiquidCrystal_I2C::scrollDisplayRight(void) { |
Yar | 0:824096cc05af | 151 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); |
Yar | 0:824096cc05af | 152 | } |
Yar | 0:824096cc05af | 153 | |
Yar | 0:824096cc05af | 154 | // This is for text that flows Left to Right |
Yar | 0:824096cc05af | 155 | void LiquidCrystal_I2C::leftToRight(void) { |
Yar | 0:824096cc05af | 156 | _displaymode |= LCD_ENTRYLEFT; |
Yar | 0:824096cc05af | 157 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 158 | } |
Yar | 0:824096cc05af | 159 | |
Yar | 0:824096cc05af | 160 | // This is for text that flows Right to Left |
Yar | 0:824096cc05af | 161 | void LiquidCrystal_I2C::rightToLeft(void) { |
Yar | 0:824096cc05af | 162 | _displaymode &= ~LCD_ENTRYLEFT; |
Yar | 0:824096cc05af | 163 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 164 | } |
Yar | 0:824096cc05af | 165 | |
Yar | 0:824096cc05af | 166 | // This will 'right justify' text from the cursor |
Yar | 0:824096cc05af | 167 | void LiquidCrystal_I2C::autoscroll(void) { |
Yar | 0:824096cc05af | 168 | _displaymode |= LCD_ENTRYSHIFTINCREMENT; |
Yar | 0:824096cc05af | 169 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 170 | } |
Yar | 0:824096cc05af | 171 | |
Yar | 0:824096cc05af | 172 | // This will 'left justify' text from the cursor |
Yar | 0:824096cc05af | 173 | void LiquidCrystal_I2C::noAutoscroll(void) { |
Yar | 0:824096cc05af | 174 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; |
Yar | 0:824096cc05af | 175 | command(LCD_ENTRYMODESET | _displaymode); |
Yar | 0:824096cc05af | 176 | } |
Yar | 0:824096cc05af | 177 | |
Yar | 0:824096cc05af | 178 | // Allows us to fill the first 8 CGRAM locations |
Yar | 0:824096cc05af | 179 | // with custom characters |
Yar | 0:824096cc05af | 180 | void LiquidCrystal_I2C::createChar(unsigned char location, unsigned char charmap[]) { |
Yar | 0:824096cc05af | 181 | location &= 0x7; // we only have 8 locations 0-7 |
Yar | 0:824096cc05af | 182 | command(LCD_SETCGRAMADDR | (location << 3)); |
Yar | 0:824096cc05af | 183 | for (int i=0; i<8; i++) { |
Yar | 0:824096cc05af | 184 | write(charmap[i]); |
Yar | 0:824096cc05af | 185 | } |
Yar | 0:824096cc05af | 186 | } |
Yar | 0:824096cc05af | 187 | |
Yar | 0:824096cc05af | 188 | // Turn the (optional) backlight off/on |
Yar | 0:824096cc05af | 189 | void LiquidCrystal_I2C::noBacklight(void) { |
Yar | 0:824096cc05af | 190 | _backlightval=LCD_NOBACKLIGHT; |
Yar | 0:824096cc05af | 191 | expanderWrite(0); |
Yar | 0:824096cc05af | 192 | } |
Yar | 0:824096cc05af | 193 | |
Yar | 0:824096cc05af | 194 | void LiquidCrystal_I2C::backlight(void) { |
Yar | 0:824096cc05af | 195 | _backlightval=LCD_BACKLIGHT; |
Yar | 0:824096cc05af | 196 | expanderWrite(0); |
Yar | 0:824096cc05af | 197 | } |
Yar | 0:824096cc05af | 198 | bool LiquidCrystal_I2C::getBacklight() { |
Yar | 0:824096cc05af | 199 | return _backlightval == LCD_BACKLIGHT; |
Yar | 0:824096cc05af | 200 | } |
Yar | 0:824096cc05af | 201 | |
Yar | 0:824096cc05af | 202 | |
Yar | 0:824096cc05af | 203 | /*********** mid level commands, for sending data/cmds */ |
Yar | 0:824096cc05af | 204 | |
Yar | 0:824096cc05af | 205 | inline void LiquidCrystal_I2C::command(unsigned char value) { |
Yar | 0:824096cc05af | 206 | send(value, 0); |
Yar | 0:824096cc05af | 207 | } |
Yar | 0:824096cc05af | 208 | |
Yar | 0:824096cc05af | 209 | inline int LiquidCrystal_I2C::write(unsigned char value) { |
Yar | 0:824096cc05af | 210 | send(value, Rs); |
Yar | 0:824096cc05af | 211 | return 1; |
Yar | 0:824096cc05af | 212 | } |
Yar | 0:824096cc05af | 213 | |
Yar | 0:824096cc05af | 214 | |
Yar | 0:824096cc05af | 215 | /************ low level data pushing commands **********/ |
Yar | 0:824096cc05af | 216 | |
Yar | 0:824096cc05af | 217 | // write either command or data |
Yar | 0:824096cc05af | 218 | void LiquidCrystal_I2C::send(unsigned char value, unsigned char mode) { |
Yar | 0:824096cc05af | 219 | unsigned char highnib=value&0xf0; |
Yar | 0:824096cc05af | 220 | unsigned char lownib=(value<<4)&0xf0; |
Yar | 0:824096cc05af | 221 | write4bits((highnib)|mode); |
Yar | 0:824096cc05af | 222 | write4bits((lownib)|mode); |
Yar | 0:824096cc05af | 223 | } |
Yar | 0:824096cc05af | 224 | |
Yar | 0:824096cc05af | 225 | void LiquidCrystal_I2C::write4bits(unsigned char value) { |
Yar | 0:824096cc05af | 226 | expanderWrite(value); |
Yar | 0:824096cc05af | 227 | pulseEnable(value); |
Yar | 0:824096cc05af | 228 | } |
Yar | 0:824096cc05af | 229 | |
Yar | 0:824096cc05af | 230 | void LiquidCrystal_I2C::expanderWrite(unsigned char _data){ |
Yar | 0:824096cc05af | 231 | char data_write[2]; |
Yar | 0:824096cc05af | 232 | data_write[0] = _data | _backlightval; |
Yar | 0:824096cc05af | 233 | //Wire.beginTransmission(_addr); |
Yar | 0:824096cc05af | 234 | //Wire.write((int)(_data) | _backlightval); |
Yar | 0:824096cc05af | 235 | //Wire.endTransmission(); |
Yar | 0:824096cc05af | 236 | _i2c.write(_addr, data_write, 1, 0); |
Yar | 0:824096cc05af | 237 | _i2c.stop(); |
Yar | 0:824096cc05af | 238 | } |
Yar | 0:824096cc05af | 239 | |
Yar | 0:824096cc05af | 240 | void LiquidCrystal_I2C::pulseEnable(unsigned char _data){ |
Yar | 0:824096cc05af | 241 | expanderWrite(_data | En); // En high |
Yar | 0:824096cc05af | 242 | wait_us(1); // enable pulse must be >450ns |
Yar | 0:824096cc05af | 243 | |
Yar | 0:824096cc05af | 244 | expanderWrite(_data & ~En); // En low |
Yar | 0:824096cc05af | 245 | wait_us(50); // commands need > 37us to settle |
Yar | 0:824096cc05af | 246 | } |
Yar | 0:824096cc05af | 247 | |
Yar | 0:824096cc05af | 248 | void LiquidCrystal_I2C::load_custom_character(unsigned char char_num, unsigned char *rows){ |
Yar | 0:824096cc05af | 249 | createChar(char_num, rows); |
Yar | 0:824096cc05af | 250 | } |
Yar | 0:824096cc05af | 251 | |
Yar | 0:824096cc05af | 252 | void LiquidCrystal_I2C::setBacklight(unsigned char new_val){ |
Yar | 0:824096cc05af | 253 | if (new_val) { |
Yar | 0:824096cc05af | 254 | backlight(); // turn backlight on |
Yar | 0:824096cc05af | 255 | } else { |
Yar | 0:824096cc05af | 256 | noBacklight(); // turn backlight off |
Yar | 0:824096cc05af | 257 | } |
Yar | 0:824096cc05af | 258 | } |
Yar | 0:824096cc05af | 259 | |
Yar | 0:824096cc05af | 260 | void LiquidCrystal_I2C::printstr(const char c[]){ |
Yar | 0:824096cc05af | 261 | //This function is not identical to the function used for "real" I2C displays |
Yar | 0:824096cc05af | 262 | //it's here so the user sketch doesn't have to be changed |
Yar | 0:824096cc05af | 263 | //print(c); |
Yar | 0:824096cc05af | 264 | } |
Yar | 0:824096cc05af | 265 | |
Yar | 0:824096cc05af | 266 | int LiquidCrystal_I2C::print(const char* text) { |
Yar | 0:824096cc05af | 267 | |
Yar | 0:824096cc05af | 268 | while (*text !=0) { |
Yar | 0:824096cc05af | 269 | //_putc(*text); |
Yar | 0:824096cc05af | 270 | send(*text, Rs); |
Yar | 0:824096cc05af | 271 | text++; |
Yar | 0:824096cc05af | 272 | } |
Yar | 0:824096cc05af | 273 | return 0; |
Yar | 0:824096cc05af | 274 | } |
Yar | 0:824096cc05af | 275 | |
Yar | 0:824096cc05af | 276 | /* |
Yar | 0:824096cc05af | 277 | void lcd_dat(unsigned char p) |
Yar | 0:824096cc05af | 278 | { |
Yar | 0:824096cc05af | 279 | PORTC |= (1 << RS)|(1 << EN); // RS = 1, EN = 1 (начало записи команды в LCD) |
Yar | 0:824096cc05af | 280 | PORTD = p; // Вывод команды на шину DB0-7 LCD |
Yar | 0:824096cc05af | 281 | _delay_us(100); // Длительность сигнала EN |
Yar | 0:824096cc05af | 282 | PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) |
Yar | 0:824096cc05af | 283 | _delay_us(100); // Пауза для выполнения команды |
Yar | 0:824096cc05af | 284 | } |
Yar | 0:824096cc05af | 285 | */ |