From 07159e941b8aa17bc0280dfbab54248bc6331cb9 Mon Sep 17 00:00:00 2001 From: Ivan Stefanov Date: Sat, 19 Mar 2022 16:20:32 +0200 Subject: [PATCH] Upload Lesson 21 plan and fix LCD programs withut library The two LCD examples without library needed some delays to be added to match the real world speed of the display controller which apparently is much slower than what is writen in the documentation. --- .../LCD_without_library.ino | 34 +++++++-------- .../LCD_without_library_simple.ino | 24 ++++++----- Lesson_Plans/Lesson_21.md | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 Lesson_Plans/Lesson_21.md diff --git a/Examples/LCD_without_library/LCD_without_library.ino b/Examples/LCD_without_library/LCD_without_library.ino index ed8c9e8..b704090 100644 --- a/Examples/LCD_without_library/LCD_without_library.ino +++ b/Examples/LCD_without_library/LCD_without_library.ino @@ -35,7 +35,7 @@ void setup() { 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_cmd(B0000, 0); lcd_cmd(B0001, 0); delayMicroseconds(5*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); @@ -56,12 +56,11 @@ void lcd_init(void) { 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 + lcd_cmd(B0010, 0); delayMicroseconds(5*39); // Function set => 4-bit data bus mode, 1-line, 5x8 dots + lcd_cmd(B0010, 0); lcd_cmd(B1000, 0); delayMicroseconds(5*39); // Function set => 4-bit data bus mode, 2-line, 5x8 dots + lcd_cmd(B0000, 0); lcd_cmd(B0110, 0); delayMicroseconds(5*39); // entry mode set = left-justified, left-to-right, no shift text + lcd_cmd(B0000, 0); lcd_cmd(B0001, 0); delayMicroseconds(5*1530); // clear display - set all characters to space(' ') and return home + lcd_cmd(B0000, 0); lcd_cmd(B1100, 0); delayMicroseconds(5*39); // turn display on } // There is no parameter validation @@ -72,7 +71,7 @@ void lcd_set_cursor(uint8_t col, uint8_t row) { 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); + lcd_cmd(upper, 0); lcd_cmd(lower, 0); delayMicroseconds(5*39); // set DDRAM address } // Send ASCII char @@ -80,7 +79,7 @@ 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); + lcd_cmd(upper, 1); lcd_cmd(lower, 1); delayMicroseconds(5*43); // write data to DDRAM } // Send ASCII text @@ -92,15 +91,16 @@ void lcd_show_text(char *text, uint8_t len) { // 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 + lcd_cmd(B0101, 1); lcd_cmd(B0110, 1); delayMicroseconds(5*43); // write data to DDRAM // V = 0x56 = B 0101 0110 + lcd_cmd(B0100, 1); lcd_cmd(B1101, 1); delayMicroseconds(5*43); // write data to DDRAM // M = 0x4D = B 0100 1101 + lcd_cmd(B0100, 1); lcd_cmd(B1011, 1); delayMicroseconds(5*43); // write data to DDRAM // K = 0x4B = B 0100 1011 + lcd_cmd(B0101, 1); lcd_cmd(B0011, 1); delayMicroseconds(5*43); // write data to DDRAM // 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 +// Delay values are show just as example and are +// minimum requiered values in [ns] multiplied by 2 void lcd_cmd(uint8_t _data, bool _type) { // Set RS digitalWrite(RS, _type); @@ -112,15 +112,15 @@ void lcd_cmd(uint8_t _data, bool _type) { digitalWrite(D7, (_data & 0x08)); // Time to select the register - delayMicroseconds(120); + delayMicroseconds(2*100); // tsu // 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 + delayMicroseconds(2*300); // tw - Enable pulse duration digitalWrite(EN, LOW); // Wait - delayMicroseconds(30); // Data hold time + delayMicroseconds(2*10); // tc/th1/th2 - Data hold time } diff --git a/Examples/LCD_without_library_simple/LCD_without_library_simple.ino b/Examples/LCD_without_library_simple/LCD_without_library_simple.ino index 93dcd97..1227a1e 100644 --- a/Examples/LCD_without_library_simple/LCD_without_library_simple.ino +++ b/Examples/LCD_without_library_simple/LCD_without_library_simple.ino @@ -33,21 +33,25 @@ void lcd_init() { 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 + lcd_cmd(B0010, 0); delayMicroseconds(5*39); // Function set => 4-bit data bus mode, 1-line, 5x8 dots + lcd_cmd(B0010, 0); lcd_cmd(B1000, 0); delayMicroseconds(5*39); // Function set => 4-bit data bus mode, 2-line, 5x8 dots + lcd_cmd(B0000, 0); lcd_cmd(B0110, 0); delayMicroseconds(5*39); // entry mode set = left-justified, left-to-right, no shift text + lcd_cmd(B0000, 0); lcd_cmd(B0001, 0); delayMicroseconds(5*1530); // 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); delayMicroseconds(5*39); // 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 + lcd_cmd(B0101, 1); lcd_cmd(B0110, 1); delayMicroseconds(5*43); // write data to DDRAM // V = 0x56 = B 0101 0110 + lcd_cmd(B0100, 1); lcd_cmd(B1101, 1); delayMicroseconds(5*43); // write data to DDRAM // M = 0x4D = B 0100 1101 + lcd_cmd(B0100, 1); lcd_cmd(B1011, 1); delayMicroseconds(5*43); // write data to DDRAM // K = 0x4B = B 0100 1011 + lcd_cmd(B0101, 1); lcd_cmd(B0011, 1); delayMicroseconds(5*43); // write data to DDRAM // S = 0x53 = B 0101 0011 } // Data = 4-bit data to send (use lower 4 bits) // Type 0 = Instruction || Type 1 = Data +// Delay values are show just as example and are +// minimum requiered values in [ns] multiplied by 2 void lcd_cmd(uint8_t _data, bool _type) { // Set RS digitalWrite(RS, _type); @@ -59,15 +63,15 @@ void lcd_cmd(uint8_t _data, bool _type) { digitalWrite(D7, (_data & 0x08)); // Time to select the register - delayMicroseconds(120); + delayMicroseconds(2*100); // tsu // 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 + delayMicroseconds(2*300); // tw - Enable pulse duration digitalWrite(EN, LOW); // Wait - delayMicroseconds(30); // Data hold time + delayMicroseconds(2*10); // tc/th1/th2 - Data hold time } diff --git a/Lesson_Plans/Lesson_21.md b/Lesson_Plans/Lesson_21.md new file mode 100644 index 0000000..2300d3b --- /dev/null +++ b/Lesson_Plans/Lesson_21.md @@ -0,0 +1,41 @@ +# --- Тема 21 --- + +Дата на провеждане 18.3.2022 + +Теми: Управление и използване на Течно-Кристален Екран (LCD) + +## План на часа +- Кратък преговор на вътрешната структура и начин на работа на драйвера [HD44780](https://gitlab.com/tues-embedded/vmks/-/blob/master/Datasheets/HD44780.pdf) +- Обяснение за цифрови интерфейси -> какво са setup time и hold time +- Как се подават данни през интерфейса от микроконтролера + 1. Алгоритъм на предаване + 2. Електрически параметри на сигналите + * амплитудни дадени са в [документацията на драйвера HD44780](https://gitlab.com/tues-embedded/vmks/-/blob/master/Datasheets/HD44780.pdf) + * времеви - дадени са в [документацията на LCD 16x2 модула](https://gitlab.com/tues-embedded/vmks/-/tree/master/Datasheets/LCD_16x2_example_datasheet_ADM1602K-NSW-FBS-3.3v.pdf) +- Създаване на програма за управление на дисплея без библиотека → общо взето [тази](https://gitlab.com/tues-embedded/vmks/-/tree/master/Examples/LCD_without_library_simple) от примерните програми който са в GitLab +- Как се инициализира драйвера и дисплея (има го добре обяснено във видеоклипа от първия линк в "Допълнително") + 1. Избира се 4-битов режим + 2. Задава се режим на въвеждане + 3. Изчиства се екрана и курсорът се връща в началото + 4. Разрешава се работата на екрана + 5. Изпращат се символите за показване ... +- Демонстрация на готовата програма (за съжаление не особенно успешно поради това, че бях тествал само на симулация в TinkerCAD) + +Проблемите описани в бележките са коригирани в двата примера в GitLab, като и двата примера(линкове по надолу в секция допълнително) имат коментари кой ред за какво е и изчакванията са зададени като няколко пъти минималната стойност от документацията за да се вижда ясно коя минимална стойност каква е и съответно от къде е взета от таблицата с командите. + +Бележки: +- Трябва да има 40ms изчакване в началото на програмата за да се инициализира драйвера след подаване на захранването +- Трябва да не се забравя да се зададе режимът на изводите на микроконтролера да е ИЗХОДЕН (както аз забравих в края на часа с 12А клас :)) +- Освен изчакванията между различните сигнали трябва да се сложат и изчаквания след подаването на всяка команда(в документацията пише коя команда колко време се "очаква" да отнеме за изпълнение). Оказа се, че явно реалните модули реагират доста по-бавно от времената указани в документацията и това беше причината програмата да не тръгна в края на часа с 12Б клас, тъй като примерът който бях подготвил да правим ви казах че се изпълнява достатъчно бавно да задоволи изчакванията указани в документацията, но на практика трябва да се изчаква повече за да работи(след часа останах да тествам и го намерих написано в някой от коментарите в кода на стандартната библиотека LiquidCrystal и като сложих допълнително тези изчаквания програмата тръгна - за това е важно да си тествате програмите и на реален хардуер а не само на симулации, тъй като те не винаги симулират пълното поведение на хардуера, а само основните му финкции). + +----- + +### Допълнително: + +[Как работи екрана и пример без използване на библиотека и въобще без микроконтролер](https://www.youtube.com/watch?v=cXpeTxC3_A4) ← това правихме общо взето в часа, но с ардуиното вместо с бутони + +[Проста примерна програма за управление на 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 (за друга ОС потърсете в интернет къде са библиотеките). \ No newline at end of file -- 2.39.5