From: Ivan Stefanov Date: Tue, 15 Mar 2022 20:11:32 +0000 (+0200) Subject: Upload LCD examples without using a library X-Git-Url: https://kolegite.com/gitweb/?a=commitdiff_plain;h=21ad1006a821a28dce90d2db534ab270c575f7fa;p=vmks.git Upload LCD examples without using a library --- diff --git a/Datasheets/LCD_16x2_example_datasheet_ADM1602K-NSW-FBS-3.3v.pdf b/Datasheets/LCD_16x2_example_datasheet_ADM1602K-NSW-FBS-3.3v.pdf new file mode 100644 index 0000000..81ad817 Binary files /dev/null and b/Datasheets/LCD_16x2_example_datasheet_ADM1602K-NSW-FBS-3.3v.pdf differ diff --git a/Examples/LCD_without_library/LCD_without_library.ino b/Examples/LCD_without_library/LCD_without_library.ino new file mode 100644 index 0000000..ed8c9e8 --- /dev/null +++ b/Examples/LCD_without_library/LCD_without_library.ino @@ -0,0 +1,126 @@ +#define RS 12 +#define EN 11 +#define D4 5 +#define D5 4 +#define D6 3 +#define D7 2 + +#define COLS 16 +#define ROWS 2 + +void lcd_cmd(uint8_t _data, bool _type); +void lcd_init(void); +void lcd_set_cursor(uint8_t col, uint8_t row); +void lcd_show_char(char chr); +void lcd_show_text(char *text, uint8_t len); +void lcd_show_text_vmks(void); + +void setup() { + // Initialize LCD screen and IF GPIO + lcd_init(); + + // Center the text on the second line => Move cursor to + // (second line offset + half the line size - half the text size) + // (0x40 + 16/2 - 4/2) = (0x40 + 8 - 2) = (0x40 + 6) = 0x46 + // Line 1 => 0x00 to 0x27 + // Line 2 => 0x40 to 0x67 + //lcd_cmd(B1100, 0); lcd_cmd(B0110, 0); // manually set DDRAM to cursor position = 0x46 = B 0100 0110 + lcd_set_cursor(6, 2); // the same but using the function + + // Show text + //lcd_show_text_vmks(); // Show hardcoded text "VMKS" + //lcd_show_char('T'); lcd_show_char('U'); lcd_show_char('E'); lcd_show_char('S'); + lcd_show_text("VMKS", 4); // This is actually String object converting to char array but works for the demo +} + +void loop() { + delay(5000); + lcd_cmd(B0000, 0); lcd_cmd(B0001, 0); delayMicroseconds(1530); // clear display - set all characters to space(' ') and return home + lcd_set_cursor(6, 1); + lcd_show_text_vmks(); + lcd_set_cursor(6, 2); + lcd_show_char('T'); lcd_show_char('U'); lcd_show_char('E'); lcd_show_char('S'); + while (1) {}; +} + +void lcd_init(void) { + // Set IF GPIO mode + pinMode(RS, OUTPUT); + pinMode(EN, OUTPUT); + pinMode(D4, OUTPUT); + pinMode(D5, OUTPUT); + pinMode(D6, OUTPUT); + pinMode(D7, OUTPUT); + + // LCD Power-On Reset (POR) initialization wait + delay(40); + + // Initialize controller HD44780 + lcd_cmd(B0010, 0); // lcd_cmd(B1000, 0); delayMicroseconds(39); // Function set => 4-bit data bus mode, 1-line, 5x8 dots + lcd_cmd(B0010, 0); lcd_cmd(B1000, 0); delayMicroseconds(39); // Function set => 4-bit data bus mode, 2-line, 5x8 dots + lcd_cmd(B0000, 0); lcd_cmd(B0001, 0); delayMicroseconds(1530); // clear display - set all characters to space(' ') and return home + lcd_cmd(B0000, 0); lcd_cmd(B1100, 0); delayMicroseconds(39); // turn display on + lcd_cmd(B0000, 0); lcd_cmd(B0010, 0); delayMicroseconds(1530); // return home - move cursor to begining of first line + lcd_cmd(B0000, 0); lcd_cmd(B0110, 0); delayMicroseconds(39); // entry mode set = left-justified, left-to-right, no shift text +} + +// There is no parameter validation +// COL and ROW start from 1 +void lcd_set_cursor(uint8_t col, uint8_t row) { + uint8_t row_offset[2] = {0x00, 0x40}; + uint8_t pos = (col) + row_offset[row - 1]; + pos = (pos & 0x7F) | 0x80; // Add cursor position change command code + uint8_t upper = (pos & 0xF0) >> 4; + uint8_t lower = (pos & 0x0F) >> 0; + lcd_cmd(upper, 0); lcd_cmd(lower, 0); +} + +// Send ASCII char +void lcd_show_char(char chr) { + uint8_t upper = ((uint8_t)chr & 0xF0) >> 4; + uint8_t lower = ((uint8_t)chr & 0x0F) >> 0; + + lcd_cmd(upper, 1); lcd_cmd(lower, 1); +} + +// Send ASCII text +void lcd_show_text(char *text, uint8_t len) { + for (uint8_t cnt = 0; cnt < len; cnt++) { + lcd_show_char(text[cnt]); + } +} + +// Send hardcoded ASCII text "VMKS" +void lcd_show_text_vmks(void) { + lcd_cmd(B0101, 1); lcd_cmd(B0110, 1); // V = 0x56 = B 0101 0110 + lcd_cmd(B0100, 1); lcd_cmd(B1101, 1); // M = 0x4D = B 0100 1101 + lcd_cmd(B0100, 1); lcd_cmd(B1011, 1); // K = 0x4B = B 0100 1011 + lcd_cmd(B0101, 1); lcd_cmd(B0011, 1); // S = 0x53 = B 0101 0011 +} + +// Data = 4-bit data to send (use lower 4 bits) +// Type 0 = Instruction || Type 1 = Data +// example delays are only to show the idea - they really should be in [ns] but there is no such function +void lcd_cmd(uint8_t _data, bool _type) { + // Set RS + digitalWrite(RS, _type); + + // Set Data value + digitalWrite(D4, (_data & 0x01)); + digitalWrite(D5, (_data & 0x02)); + digitalWrite(D6, (_data & 0x04)); + digitalWrite(D7, (_data & 0x08)); + + // Time to select the register + delayMicroseconds(120); + // Data setup time = 60~90ns after the above delay + // In this example data is already set before that + + // Pulse Enable + digitalWrite(EN, HIGH); + delayMicroseconds(320); // Enable pulse duration + digitalWrite(EN, LOW); + + // Wait + delayMicroseconds(30); // Data hold time +} diff --git a/Examples/LCD_without_library/LCD_without_library.png b/Examples/LCD_without_library/LCD_without_library.png new file mode 100644 index 0000000..9d12da2 Binary files /dev/null and b/Examples/LCD_without_library/LCD_without_library.png differ diff --git a/Examples/LCD_without_library/tinkercad_link.txt b/Examples/LCD_without_library/tinkercad_link.txt new file mode 100644 index 0000000..aa8b791 --- /dev/null +++ b/Examples/LCD_without_library/tinkercad_link.txt @@ -0,0 +1 @@ + https://www.tinkercad.com/things/9LSofZh54nf \ No newline at end of file diff --git a/Examples/LCD_without_library_simple/LCD_without_library_simple.ino b/Examples/LCD_without_library_simple/LCD_without_library_simple.ino new file mode 100644 index 0000000..93dcd97 --- /dev/null +++ b/Examples/LCD_without_library_simple/LCD_without_library_simple.ino @@ -0,0 +1,73 @@ +#define RS 12 +#define EN 11 +#define D4 5 +#define D5 4 +#define D6 3 +#define D7 2 + +#define COLS 16 +#define ROWS 2 + +void setup() { + // Initialize LCD screen and IF GPIO + lcd_init(); + + // Show hardcoded text "VMKS" + lcd_show_text_vmks(); +} + +void loop() { + // put your main code here, to run repeatedly: +} + +void lcd_init() { + // Set IF GPIO mode + pinMode(RS, OUTPUT); + pinMode(EN, OUTPUT); + pinMode(D4, OUTPUT); + pinMode(D5, OUTPUT); + pinMode(D6, OUTPUT); + pinMode(D7, OUTPUT); + + // LCD Power-On Reset (POR) initialization wait + delay(40); + + // Initialize controller HD44780 + lcd_cmd(B0010, 0); // Function set => 4-bit data bus mode, 1-line, 5x8 dots + lcd_cmd(B0000, 0); lcd_cmd(B0001, 0); // clear display - set all characters to space(' ') and return cursor to begining of first row (return home) + lcd_cmd(B0000, 0); lcd_cmd(B1100, 0); // turn display on +} + +// Send ASCII text "VMKS" +void lcd_show_text_vmks() { + lcd_cmd(B0101, 1); lcd_cmd(B0110, 1); // V = 0x56 = B 0101 0110 + lcd_cmd(B0100, 1); lcd_cmd(B1101, 1); // M = 0x4D = B 0100 1101 + lcd_cmd(B0100, 1); lcd_cmd(B1011, 1); // K = 0x4B = B 0100 1011 + lcd_cmd(B0101, 1); lcd_cmd(B0011, 1); // S = 0x53 = B 0101 0011 +} + +// Data = 4-bit data to send (use lower 4 bits) +// Type 0 = Instruction || Type 1 = Data +void lcd_cmd(uint8_t _data, bool _type) { + // Set RS + digitalWrite(RS, _type); + + // Set Data value + digitalWrite(D4, (_data & 0x01)); + digitalWrite(D5, (_data & 0x02)); + digitalWrite(D6, (_data & 0x04)); + digitalWrite(D7, (_data & 0x08)); + + // Time to select the register + delayMicroseconds(120); + // Data setup time = 60~90ns after the above delay + // In this example data is already set before that + + // Pulse Enable + digitalWrite(EN, HIGH); + delayMicroseconds(320); // Enable pulse duration + digitalWrite(EN, LOW); + + // Wait + delayMicroseconds(30); // Data hold time +} diff --git a/Examples/LCD_without_library_simple/LCD_without_library_simple.png b/Examples/LCD_without_library_simple/LCD_without_library_simple.png new file mode 100644 index 0000000..9d12da2 Binary files /dev/null and b/Examples/LCD_without_library_simple/LCD_without_library_simple.png differ diff --git a/Examples/LCD_without_library_simple/tinkercad_link.txt b/Examples/LCD_without_library_simple/tinkercad_link.txt new file mode 100644 index 0000000..1afe472 --- /dev/null +++ b/Examples/LCD_without_library_simple/tinkercad_link.txt @@ -0,0 +1 @@ + https://www.tinkercad.com/things/enhJJzIeHyr \ No newline at end of file diff --git a/Lesson_Plans/Lesson_20.md b/Lesson_Plans/Lesson_20.md index ba96571..c6d46a2 100644 --- a/Lesson_Plans/Lesson_20.md +++ b/Lesson_Plans/Lesson_20.md @@ -38,9 +38,14 @@ [Пример за използване с микропроцесор 6502 на асемблер](https://www.youtube.com/watch?v=FY3zTUaykVo) [Допълнително обяснение как работи този екран(https://www.engineersgarage.com/making-custom-characters-on-16x2-lcd/) - [Картинки за различните видове дисплей с типовете им](https://gitlab.com/tues-embedded/vmks/-/tree/master/Useful%20Pictures/LCD/Types) +[Проста примерна програма за управление на LCD с HD44780 без библиотека](https://gitlab.com/tues-embedded/vmks/-/tree/master/Examples/LCD_without_library_simple) +[По-пълна примерна програма за управление на LCD с HD44780 без библиотека](https://gitlab.com/tues-embedded/vmks/-/tree/master/Examples/LCD_without_library) +[Примерна документация на LCD 16x2 модул](https://gitlab.com/tues-embedded/vmks/-/tree/master/Datasheets/LCD_16x2_example_datasheet_ADM1602K-NSW-FBS-3.3v.pdf) + +Кодът на стандартната библиотека LiquidCrystal на Arduino може да намерите в директория `C:\Users\[username]\Documents\Arduino\libraries\LiquidCrystal\src` под Windows (за друга ОС потърсете в интернет къде са библиотеките). + ----- Кодиране на символ - пример с буквата `h`, като активните пиксели са `1`: diff --git a/Other Useful Files/LCD_without_library_notes.txt b/Other Useful Files/LCD_without_library_notes.txt new file mode 100644 index 0000000..2faf93d --- /dev/null +++ b/Other Useful Files/LCD_without_library_notes.txt @@ -0,0 +1,52 @@ +lcd.begin(COLS,ROWS,LCD_5x8DOTS) + +VMKS + +V = 0x56 = B 0101 0110 +M = 0x4D = B 0100 1101 +K = 0x4B = B 0100 1011 +S = 0x53 = B 0101 0011 + +Steps to send command: +0. Set RS +1. Set Data value +2. Wait >=100ns +3. Set E high +4. Wait >=300ns (can alse use this time to set Data value) +5. Set E low +6. Wait >=10ns +7. Can change Data and repeat + +Steps to show text - from YouTube video: +1. Set 4-bit mode and 1-line +2. Clear display +3. Return home +4. Turn display on +5. Send text in ASCII + +================================================== + +Steps to initialise the screen - from the library: +1. Set 4-bit 2-line 5x8-dot mode +2. Turn display-on, cursor-off, blinking-off +3. Clear display +4. Set autoincrement left-to-right, left-justified + +// When the display powers up, it is configured as follows: +// +// 1. Display clear +// 2. Function set: +// DL = 1; 8-bit interface data +// N = 0; 1-line display +// F = 0; 5x8 dot character font +// 3. Display on/off control: +// D = 0; Display off +// C = 0; Cursor off +// B = 0; Blinking off +// 4. Entry mode set: +// I/D = 1; Increment by 1 +// S = 0; No shift +// +// Note, however, that resetting the Arduino doesn't reset the LCD, so we +// can't assume that its in that state when a sketch starts (and the +// LiquidCrystal constructor is called).