Top.Mail.Ru

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

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

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

Подключение дисплея на базе 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 для каждой конкретной команды. Вот хотим мы, например, очистить дисплей, смотрим в таблицу, и вот она нужная команда - Clear Display.

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

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

Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32.

Получаем в свое распоряжение 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

66 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
JekaKey
JekaKey
10 лет назад

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

German
German
10 лет назад

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

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

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

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

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

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

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

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

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

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

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

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

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

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
10 лет назад

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

max0131
max0131
10 лет назад

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

max0131
max0131
10 лет назад

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

LEV
LEV
10 лет назад

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

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

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

LEV
LEV
10 лет назад

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

LEV
LEV
10 лет назад

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

Dmitriy
Dmitriy
10 лет назад

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

Dmitriy
Dmitriy
10 лет назад

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

Dmitriy
Dmitriy
10 лет назад

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

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

Использую 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);
Экран включен, но ничего не отображает.
В чем может быть ошибка?

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

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

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

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

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

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

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

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

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;

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

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

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);

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

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

Egor
Egor
8 лет назад

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

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

hedin
hedin
8 лет назад

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

hedin
hedin
8 лет назад

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

Doublman
Doublman
8 лет назад

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

Doublman
Doublman
8 лет назад

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Шишкебаб
Шишкебаб
Ответ на комментарий  Кирилл
7 лет назад

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

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

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

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

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

Vladislav
6 лет назад

Вот моя современная библиотека для этих древних 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.

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

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

Sergey
Sergey
Ответ на комментарий  Сергей
5 лет назад

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

Даниил
Даниил
1 месяц назад

Здравствуйте, спасибо больше за проделанную работу. Если есть ещё кто-то на форуме через 10 лет, надеюсь ответят. Всё сделал по инструкции, но возникла такая проблема: при попытки "построения" проекта для отладки выдаёт 2 ошибки: жалуется на "неразрешённые включения", а именно
#include "stm32f4xx_rcc.h" и #include "stm32f4xx_gpio.h" прям так и пишет: Unresolved inclusion не знаю, ка с этим бороться, может просто поменять что-то нужно, какое-то название. Использую камень stm32F401ccu6. Очень надеюсь, что остался кто-то живой здесь.

Даниил
Даниил
Ответ на комментарий  Aveal
1 месяц назад

Жаль, спасибо за ответ)

Даниил
Даниил
Ответ на комментарий  Aveal
1 месяц назад

Спасибо)

66
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x