Подключение и использование дисплея на базе HD44780.

Что является неотъемлемой частью большого количества электронных девайсов? Конечно, средства индикации и графического вывода данных. Пользователю всегда удобнее и приятнее когда результат работы «умной коробочки» можно увидеть визуально. Поэтому сегодня мы подключим к STM32 дисплей для вывода текста и цифр. Героем наших экспериментов станет довольно-таки популярный дисплей WH1602 от Winstar’а. Вот кстати в комментариях появилось важное уточнение, что методика в принципе одинакова для всех дисплеев на базе HD44780. Спасибо JekaKey за важное дополнение!

Для начала дисплей надо собственно подключить к контроллеру. Скачиваем даташит и ищем распиновку WH1602. Вот смотрите:

Подключение дисплея на базе HD44780

Как вы уже поняли, WH1602 имеет 16 выводов. Рассмотрим каждый в отдельности…

  • Пины Vss, Vdd и K нужно подключать к земле и к питанию, то есть прямо так, как указано в таблице, тут без сюрпризов и даже нечего обсуждать 🙂
  • Вывод под номером 3 служит для регулировки контрастности – если подадим туда +5В, то не увидим абсолютно ничего, а если закоротим вывод на землю, то будем любоваться двумя рядами черных квадратов… Естественно, это нас не устраивает, поэтому туда надо повесить потенциометр (резистор с переменным сопротивлением)  для регулировки контрастности. Самая лучшая видимость символов обеспечивается напряжением 0.5-0.7 В на этом выводе дисплея.
  • Пин RS – это уже вывод, которым мы сами будем управлять при помощи микроконтроллера. Низкий уровень напряжения (0) на этом выводе означает, что сейчас последует команда, высокий уровень (1) – значит сейчас будут данные для записи в память дисплея.
  • Пин R/W – тут понятно, либо мы читаем данные (флаг занятости дисплея, например), в этом случае на этом выводе 1, либо записываем команду/данные в дисплей, тогда тут у нас 0.
  • DB7 – DB0 – шина данных, и этим все сказано!
  • Пин E – так называемый Enable signal. Нужен он вот для чего. Чтобы работать с дисплеем – записывать данные или подавать команду – нам надо выдать на этот вывод положительный импульс. То есть, процедура будет выглядеть следующим образом:
    • На пины RS, R/W, DB7 – DB0 – нужные сигналы, соответствующие нашей команде.
    • Подаем высокий уровень на вывод E.
    • Ждемс (по даташиту – не менее 150 нс)
    • Подаем на вывод E низкий уровень.
  • На ножку A/Vee надо сунуть 4.2 В для питания подсветки дисплея.

Вот так вот происходит общение с дисплеем.

С подключением WH1602 разобрались, но прежде, чем переходить к примеру, рассмотрим какие вообще команды понимает наш дисплей. Для этого лезем в даташит и находим интересную таблицу:

Команды дисплея WH1602

Тут описаны все команды и сигналы, которые должны быть на соответствующих выводах WH1602 для каждой конкретной команды. Вот хотим мы, например, очистить дисплей, смотрим в таблицу, и вот она нужная команда – Clear Display!

Подаем на выводы RS, R/W, DB7, DB6, DB5, DB4, DB3, DB2, DB1 нули, а на ножку DB0 –  единицу. Готово, что дальше? Верно, единицу на пин E, затем ожидаем некоторое время и снова опускаем E в ноль. Все,  дисплей очищен 🙂 Только перед выполнением следующей команды необходимо выдержать паузу, указанную в даташите для каждой команды. Более эффективным будет опрос флага занятости, как только он сбросился в 0 – можно работать дальше. Для чтения этого флага тоже есть специальная команда, так что и с этим все понятно. Идем дальше…

А, собственно, с теорией все, можно уже что-нибудь попробовать написать. Я для облегчения работы с дисплеем сделал небольшую библиотеку для дисплея WH1602 (она подходит и для других дисплеев на базе HD44780), сейчас посмотрим, как ее можно использовать. Для начала скачиваем:

Получаем в свое распоряжение 2 файла, MT_WH1602.c и MT_WH1602.h. Отрываем второй, тут нам надо произвести выбор выводов и используемого контроллера.

Дисплей у меня, кстати, подключен так:

  • RS – PC2
  • R/W – PB10
  • E – PB14
  • DB7 – PD2
  • DB6 – PC12
  • DB5 – PA8
  • DB4 – PA10
  • DB3 – PA15
  • DB2 – PD11
  • DB1 – PA3
  • DB0 – PA5

Открываем файл MT_WH1602.h:

/***************************************************************************************/
// Choose your platform
/***************************************************************************************/
#define STM32F10x                                                (0)
#define STM32F4xx                                                (1)

#define PLATFORM                                                 (STM32F4xx)

Тут нам надо выбрать STM32F4xx или STM32F10x мы будем использовать. То есть либо пишем:

#define PLATFORM                                                 (STM32F4xx)

либо:

#define PLATFORM                                                 (STM32F10x)

Далее выбираем выводы микроконтроллера, к которым у нас подключен дисплей. Только сначала зададим, какие порты у нас задействованы. Вот при моем подключении используются GPIOA, GPIOB, GPIOC и GPIOD, пишем:

// Configure which GPIO are in use

// If GPIOA is in use set this constant TRUE
#define GPIOA_IS_IN_USE                                          (TRUE)

// If GPIOB is in use set this constant TRUE
#define GPIOB_IS_IN_USE                                          (TRUE)

// If GPIOC is in use set this constant TRUE
#define GPIOC_IS_IN_USE                                          (TRUE)

// If GPIOD is in use set this constant TRUE
#define GPIOD_IS_IN_USE                                          (TRUE)

// If GPIOE is in use set this constant TRUE
#define GPIOE_IS_IN_USE                                          (FALSE)

Осталось выбрать ножки. Например, RS у меня на выводе PC2, значит:

// Select which pins are connected to the WH1602 module

// Set RS port
#define MT_WH1602_RS_PORT                                        (GPIOC)

// Set RS pin
#define MT_WH1602_RS_PIN                                         (GPIO_Pin_2)

Аналогично для других ножек микроконтроллера.

С настройкой покончили, продолжаем! Для вызова команд, приведенных в начале статьи в файле MT_WH1602.c содержатся следующие функции (их имена соответствуют названиям команд):

void MT_WH1602_ClearDisplay(void);
void MT_WH1602_ReturnHome(void);
void MT_WH1602_EntryModeSet (bool IDaddress, bool shift);
void MT_WH1602_DisplayOnOff (bool Dbit, bool Cbit, bool Bbit);
void MT_WH1602_CursorOrDisplayShift (bool SCbit, bool RLbit);
void MT_WH1602_FunctionSet (bool DLbit, bool Nbit, bool Fbit);
void MT_WH1602_SetCGRAMAddress (uint8_t address);
void MT_WH1602_SetDDRAMAddress (uint8_t address);
bool MT_WH1602_ReadBusy(void);
void MT_WH1602_WriteData(uint8_t data);

Для некоторых команд нам нужно передать в функцию параметры, вот, например:

void MT_WH1602_DisplayOnOff (bool Dbit, bool Cbit, bool Bbit);

Смотрим в таблицу команд:

Команды дисплея WH1602.

Видим, что командой Display ON/OFF не только включать/выключать дисплей, но также активировать/деактивировать курсор и мигание курсора. В даташите эти биты команды обозначены как D,C и B, их то мы и передаем в качестве параметров в функцию. Если нам нужно включить дисплей и курсор, но отключить мигание курсора, вызываем команду следующим образом:

MT_WH1602_DisplayOnOff(1, 1, 0);

В общем, все просто 🙂

Итак, создаем новый проект, добавляем библиотеку, создаем пустой .c файл и начинаем заполнять его кодом:

/***************************************************************************************/
// Подключаем файл библиотеки
#include "MT_WH1602.h"


/***************************************************************************************/
int main(void)
{
	// Вызываем функцию инициализации, без этого никуда =)
	MT_WH1602_Init();
	// Теперь надо произвести начальную конфигурацию дисплея, 
	// документация и интернет рекомендуют делать так ;)

	MT_WH1602_FunctionSet(1, 0, 0);
	MT_WH1602_Delay(1000);
	
	MT_WH1602_FunctionSet(1, 0, 0);
	MT_WH1602_Delay(1000);
	
	MT_WH1602_FunctionSet(1, 0, 0);
	MT_WH1602_Delay(1000);
	
	MT_WH1602_FunctionSet(1, 1, 1);
	MT_WH1602_Delay(1000); 
	
	MT_WH1602_DisplayOnOff(1, 0, 0);
	MT_WH1602_Delay(1000);
	
	MT_WH1602_ClearDisplay();
	MT_WH1602_Delay(2000);

	// Я тут значения задержки для примера взял первые пришедшие в голову :) 
	// Вообще нужно проверять флаг занятости дисплея
	// Давайте теперь выведем что-нибудь на дисплей, например название нашего сайта 

	MT_WH1602_WriteData(0x6D);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x69);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x63);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x72);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x6F);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x74);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x65);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x63);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x68);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x6E);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x69);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x63);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x73);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x2E);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x72);
	MT_WH1602_Delay(100);
	
	MT_WH1602_WriteData(0x75);
	MT_WH1602_Delay(100);

	while(1)
	{
		__NOP();
	}
}


/***************************************************************************************/

Готово, проверяем:

Работа с дисплеем на базе HD44780

Как видите, все работает правильно!

Кстати я как то упустил из виду вопрос о том, что же писать в дисплей, чтобы вывести тот или иной символ. Вот табличка из даташита:

Символы WH1602

Так вот, чтобы определить какое значение записать в память дисплея, нужно для конкретного символа взять числа, написанные сверху и слева в этой таблице. Например, символ “А”. Смотрим – этому символу соответствует колонка 0100 (0х4) и строка 0001 (0х1). Получается, что для вывода символа “А” нужно записать в дисплей значение 0х41.

Вот теперь вроде все! Мы успешно осуществили подключение дисплея на базе HD44780, так что до скорых встреч в новых статьях!

P. S. Я при работе с библиотекой не тестировал функцию чтения флага занятости, так что, если вдруг что-то будет работать не так, как надо, пишите, будем разбираться 🙂

Поделиться!

Подписаться
Уведомление о
guest
61 Комментарий
старее
новее большинство голосов
Inline Feedbacks
View all comments
JekaKey
JekaKey
7 лет назад

Добавлю, что описанная методика работы подходит почти для всех символьных дисплеев на основе hitachi HD44780, коих кроме winstar просто масса, в том числе с поддержкой русских символов из коробки (МЭЛТ например). Еще можно описать, что для ввода информации можно использовать не только шину 8 бит, но и 4 бита.

German
German
7 лет назад

Можете привести пример для 4-х битной шины? Не могу разобраться, перепробовал кучу библиотек а дисплей так и не запускается.

Александр
Александр
7 лет назад

Спасибо за библиотеку! Избавили от кучи рутинной работы. Правда при ее использовании у меня возникли некоторые проблемы. При компиляции Keil выдал ошибку, что тип bool ему не известен. Решилось путем добавления строк:

// Declarations and definitions
//*********************************************************
typedef signed char bool;
#define TRUE 1
#define FALSE 0

в заголовочный файл MT_WH1602.h.

P.S. В статье в коде программы пропущена закрывающаяся фигурная скобка в конце =)

Антон
Антон
6 лет назад

Задержку нужно увеличить, иначе отображать начинает с третьего символа. Я поставил MT_WH1602_ClearDisplay();
MT_WH1602_Delay(3000);
и всё работает.
Компилил в CooCox. Менял только ноги микрухи на свои, остальное всё отсюда.
Спасибо за библиотеку!

Алексей
Алексей
6 лет назад

Здравствуйте.
Подскажите как заполнить вторую строчку текстом ?

Алексей
Алексей
6 лет назад

Напишите пожалуйста команду а то так и не разобрался.

Антон
Антон
6 лет назад

MT_WH1602_SetDDRAMAddress(0x40);
MT_WH1602_Delay(40);
MT_WH1602_WriteData(simvol);

где simvol в любой форме (bin, dec, hex) символ который хотим высветить (согласно даташиту). И судя по адресу (0x40) запишется символ во вторую строчку самым первым.

P.S. Про инициализацию дисплея не забываем 🙂 Код в статье немного избыточный. Мне хватало:

int main(void)
{
while(1)
{
// Вызываем функцию инициализации дисплея
MT_WH1602_Init();

MT_WH1602_FunctionSet(1, 1, 1);
MT_WH1602_Delay(39);
MT_WH1602_DisplayOnOff(1, 0, 0);
MT_WH1602_Delay(39);
// MT_WH1602_ClearDisplay(); // Необязательно
MT_WH1602_Delay(1530); // При условии, что delay правильно настроен в микросекундах
__NOP();
}

max0131
max0131
6 лет назад

В функции MT_WH1602_ReadBusy()
необходимо в конце поставить GPIO_ResetBits(MT_WH1602_RW_PORT, MT_WH1602_RW_PIN);
Иначе после вызова дисплей постоянно в режиме записи.

max0131
max0131
6 лет назад

Также, четырех битный режим не работает. Для этого между посылками полу-байта нужно поставить MT_WH1602_DataReadWrite();
К сожалению, свой вариант дать не могу, т.к. уже заточил под свой проект.

max0131
max0131
6 лет назад

У меня контроллер и дисплей питаются отдельно. По этому без MT_WH1602_ClearDisplay(); при перезапуске контроллера остается мусор от предыдущей работы.

LEV
LEV
6 лет назад

У меня при компиляции пишет:

MainCode\Main\Main.c(28): warning: #188-D: enumerated type mixed with another type

и подобных 15 строк… Это нормально?
Ну и пока на дисплее пустота 🙁 Возможно напряжение питния низкое 2,6В?

LEV
LEV
6 лет назад

Питание ЖКИ имею ввиду

LEV
LEV
6 лет назад

Исправил. Заработало!!!
Спасибо)

Dmitriy
Dmitriy
6 лет назад

На дисплее есть анод и катод, что к ним нужно подключать?

Dmitriy
Dmitriy
6 лет назад

Извините, это уже наверное оффтоп, но все таки спрошу, так как в электронике я не силен (программирование больше). На сколько я знаю на плате stm32f4discovery нет 4.2в, это напряжение как то надо получать из 5в?(Как?) или это должно быть отдельное питание?

Dmitriy
Dmitriy
6 лет назад

Aveal, Спасибо за ответ, буду пробовать!

Александр
6 лет назад

Использую qapass 1602а. Подключал (lcd/stm32f4discovery):
VSS – GND;
VDD – VDD;
V0 – переменный резистор ПП3-40 2К2С
RS – PC2;
RW – PB10;
E – PB14;
D0 – PA5;
D1 – PA3;
D2 – PD11;
D3 – PA15;
D4 – PA10;
D5 – PA8;
D6 – PC12;
D7 – PD2;
A – перемен. рез. – провод на пин 5V;
K – GND;
на VDD, V0, A – 4.72V
на RS, D0, D2, D4, D5, D6 – 2.98V
Также 15 ошибок как у LEV типа: User\src\main.c(19): warning: #188-D: enumerated type mixed with another type
MT_WH1602_FunctionSet(1, 1, 1);
Экран включен, но ничего не отображает.
В чем может быть ошибка?

Александр
6 лет назад

Разобрался. Экран запустился. Спасибо за библиотеку и статью)

Николай
Николай
5 лет назад

Столкнулся с такой проблемой индикатор
WH1602B PPL-CWVE# купил 2 шт подал питание очень сильно начала разогреваться микруха U3 потом отпала но индикатор работает только с самого начала тускловато (на 3 ножку 0,7V) там у меня резистор 10К. Возле U3 стоят конденцаторы С1иС2 через 1 минуту задымили. Я их тоже отпаял индикатор работает но как и в начале слабо видно символы. Микросхема SMD 8 выводов HTC по рыл интернет оказался (удвоитель напряжения) из 5V – 10V
ктото сталкивался с такой проблемой. Подключил второй индикатор сразу КЗ и U3 задымила отпала (второй индикатор работает но тускло).

Петрович
Петрович
5 лет назад

А что делать, если у меня Cortex- m0+? Переписать библиотеку?

Сергей
Сергей
5 лет назад

Предлагаю использовать ссылки на символы, чтобы коды символов не вводить.

MT_WH1602.h:
заменить extern void MT_WH1602_WriteData(uint8_t data)

на:

extern void MT_WH1602_WriteData(char charData);

и добавить функцию:

extern void MT_WH1602_WriteDataString(unsigned char *charDataString);

MT_WH1602.с:

объявить переменную:

int data;

добавить функцию:

void MT_WH1602_WriteDataString(unsigned char *charDataString)
{
while (*charDataString != 0)
{
MT_WH1602_Delay(100);
MT_WH1602_WriteData(*charDataString++);
}
}

заменить параметры в функции void MT_WH1602_WriteData(uint8_t data)

на:

void MT_WH1602_WriteData(char charData)

и добавить:
data = (int)charData;

Сергей
Сергей
5 лет назад

Ну и проверим:

MT_WH1602_SetDDRAMAddress(0x40);
MT_WH1602_Delay(100);
MT_WH1602_WriteDataString(“string test…”);
MT_WH1602_Delay(100);
MT_WH1602_SetDDRAMAddress(0x00);
MT_WH1602_Delay(100);
MT_WH1602_WriteData(‘t’);
MT_WH1602_Delay(100);
MT_WH1602_WriteData(‘e’);
MT_WH1602_Delay(100);
MT_WH1602_WriteData(‘s’);
MT_WH1602_Delay(100);
MT_WH1602_WriteData(‘t’);
MT_WH1602_Delay(100);

Алексей
Алексей
5 лет назад

При использовании приведенного в статье примера была проблема с Winstar овским дисплеем – просто на просто не инициализировался, всегда горела верхняя строка и ничего не выводилось. Вылечил вставкой задержки MT_WH1602_Delay(5000); перед функцией инициализации дисплея.

Egor
Egor
5 лет назад

У меня возникла такая проблема. Можете подсказать?
Символы по адресам xxxx xx00 — xxxx xx11 воспринимаются как xxxx xx01
Что это может быть?

Мой дисплей WEH001602AGPP5N00001
Плата stm32f103

hedin
hedin
5 лет назад

Добрый день! Не поделитесь, в каком даташите подробнее все описано, в т.ч. и откуда взята таблица символов? Дело в том, что все винстаровские даташиты одностраничные без таблицы и каких либо пояснений, что к чему…..

hedin
hedin
5 лет назад

О! То что надо, спасибо.

Doublman
Doublman
4 лет назад

Aveal, Спасибо за отличную статью. Делаю первые шаги в МП схемотехнике.
У меня два вопроса:
1. Все приведенные примеры верны только дл STM32? Для Atmega8 библиотеки “свои”?
2. Подскажите где можно скачать файлы WH1602h для PROTEUS 7?
Будете ли продолжать обзоры? очень доступно излагаете.

Doublman
Doublman
4 лет назад

Понял, разобрался и нашел нужное. С Протеусом то-же разобрался он там как LM016L прописался.
Спасибо.

Кирилл
Кирилл
4 лет назад

У меня дисплеи вообще ни как не реагирует =)
Не могу понять как у вас работает без V0, он управляет контрастностью ?

Кирилл
Кирилл
4 лет назад

Или вы просто забыли написать об этом? =)
V0 вроде можно к переменному резистору подключить и настраивать контрастность

Кирилл
Кирилл
4 лет назад

Не пробовали настроить на ввод с клавиатуры? просто вывод символов не интересно =)) хочется вводить с клавы и сразу видеть символы =)

Кирилл
Кирилл
4 лет назад

Не хочет дисплей включаться, для удобства подключения поменял ножки, из за этого не может ведь не работать?

Кирилл
Кирилл
4 лет назад

На словах всегда все просто =)) вам наверно это не сложно)) а вот я долго буду сидеть думать =D

Кирилл
Кирилл
4 лет назад

На дисплее еще есть контакты А, К это анод, катод светодиодной подсветки, без них же должен работать? Катод можно на землю воткнуть?

Кирилл
Кирилл
4 лет назад

Подсветка работает, текст не выводится теперь =) кручу верчу резистор ни какого результата (

Кирилл
Кирилл
4 лет назад

Проблема была в том что что я использовал многооборотный резистор =) поменял на однооборотный все норм, вот только вместо символов просто белые квадратики, в чем может быть проблема? =)

Кирилл
Кирилл
4 лет назад

С этим вопросом тоже разобрался =)
Какая то ерунда: на плате несколько ножек GND( земля ) подключил к другой ножке и все заработало, только без первого символа “m”, тестером прозвонил ножки, все в порядке, что за магия понять не могу =)

Шишкебаб
Шишкебаб
Reply to  Кирилл
3 лет назад

Дружище спасибо! От души!!! Весь вечер маялся. Уже думал, что панелька мертвая. Всего-то нужно было на соседнюю землю переключить, чертовщина лукавая.

Кирилл
Кирилл
4 лет назад

Врятли в этом проблема, текст как будто сдвинут влево ( последняя клетка свободна )

Игорь
Игорь
4 лет назад

Не могли бы выложить рабочие проекты для кейла, по каждой статье.

Vladislav
2 лет назад

Вот моя современная библиотека для этих древних LCD.
Адаптированная для использования с STM32 CubeMX.
https://www.dropbox.com/s/uhcbwx8dvdgemx2/LCD_CubeMX.rar?dl=0
Поддерживаются ВСЕ известные алфавитно-цифровые LCD-дисплеи на базе контроллеров HD44780 (SPLC780 и др.):
— 8×1
— 8×2
— 12×2
— 16×1 (обе разновидности)
— 16×2
— 16×4
— 20×2
— 20×4
— 24×2
— 40×2
— 40×4

Если линк недоступен здесь, то просто направьте запрос на 67vladk@gmail.com.

Последняя версия – v1.2.

Сергей
Сергей
1 год назад

Валялся на работе дисплейчик REC001602CGPP5N00000
Вот что получилось, как всегда спасибо Aveal:
https://vk.com/videos-49961251?z=video57033099_456239075%2Fclub49961251%2Fpl_-49961251_-2

Sergey
Sergey
Reply to  Сергей
1 год назад

https://vk.com/videos-49961251?z=video-49961251_456239017%2Fclub49961251%2Fpl_-49961251_-2
Вот новая ссылка. У меня как всегда проблемы с соцсетями ))

Присоединяйтесь!

Profile Profile Profile Profile Profile
Vkontakte
Twitter

Язык сайта

Август 2020
Пн Вт Ср Чт Пт Сб Вс
 12
3456789
10111213141516
17181920212223
24252627282930
31  

© 2013-2020 MicroTechnics.ru