Подключение и работа с дисплеем WH1602.

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

Подключение WH1602.

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

Подключение WH1602

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

Пины Vss, Vdd и K нужно подключать к земле и к питанию, то есть прямо так, как указано в таблице, тут без сюрпризов и даже нечего обсуждать )

Вывод под номером 3 служит для регулировки контрастности – если подадим туда +5В, то не увидим абсолютно ничего, а если закоротим вывод на землю, то будем любоваться двумя рядами черных квадратов 😉 Естественно, это нас не устраивает, поэтому туда надо повесить потенциометр (резистор с переменным сопротивлением)  для регулировки контрастности. Самая лучшая видимость символов обеспечивается напряжением 0.5-0.7 В на этом выводе дисплея.

Пин RS – это уже вывод, которым мы сами будем управлять при помощи микроконтроллера. Низкий уровень напряжения (0) на этом выводе означает, что сейчас последует команда, высокий уровень (1) – значит сейчас будут данные для записи в память дисплея.

Пин R/W – тут понятно, либо мы читаем данные (флаг занятости дисплея, например), в этом случае на этом выводе 1, либо записываем команду/данные в дисплей, тогда тут у нас 0.

DB7 – DB0 – шина данных, и этим все сказано )

Пин E – так называемый Enable signal. Нужен он вот для чего. Чтобы работать с дисплеем — записывать данные или подавать команду – нам надо выдать на этот вывод положительный импульс. То есть, процедура будет выглядеть следующим образом:

  1. На пины RS, R/W, DB7 – DB0 – нужные сигналы, соответствующие нашей команде.
  2. Подаем единицу на вывод E.
  3. Ждемс (по даташиту – не менее 150 нс)
  4. Подаем на вывод E низкий уровень (0).

На ножку A/Vee надо сунуть 4.2 В для питания подсветки дисплея.

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

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

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

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

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

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

Библиотека MT_WH1602

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

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

Короче, создаем новый проект, добавляем библиотеку для работы с дисплеем WH1602, создаем пустой .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();
    }
}
 
 
 
/*******************************************************************/

Готово, проверяем )
Дисплей WH1602
Как видите, все работает правильно )

Кстати я как то упустил из виду вопрос о том, что же писать в дисплей, чтобы вывести тот или иной символ. Вот табличка из даташита:
Символы WH1602
Так вот, чтобы определить какое значение записать в память дисплея, нужно для конкретного символа взять числа, написанные сверху и слева в этой таблице. Например, символ «А». Смотрим — этому символу соответствует колонка 0100 (0х4) и строка 0001 (0х1). Получается, что для вывода символа «А» нужно записать в дисплей значение 0х41.

Вот теперь вроде все =) Разобрались мы с подключением и работой дисплея WH1602, так что до скорого!

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

Понравилась статья? Поделись с друзьями!

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

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

    • Постараюсь через пару дней сделать, если дисплей откопаю какой-нибудь дома подходящий )

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

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

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

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

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

    • Через команду установки адреса перейти на вторую строку и потом уже обычной командой на запись подавать данные

    • Команда — Set DDRAM address, в таблице команд внизу, а адреса такие, если мне не изменяет память:
      16 символов первой строки — адреса от 0x00 до 0x0F, 16 символов второй строки — адреса от 0x40 — до 0x4F. То есть если надо записать второй символ второй строки, то выставляем адрес 0x41 и пишем данные

  5. 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();
    }

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

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

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

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

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

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

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

    • Ну можно потенциометр подключить (один контакт на землю, второй на 5 Вольт). Тогда с потенциометра можно снимать любые значения от 0 до 5 и регулировать яркость подсветки

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

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

    • Да там из всей периферии только gpio используются, если и придется что-то менять, то не сильно.

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

    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;

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

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

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

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

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

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

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

    • Да, конечно, контроллеры абсолютно разные, регистры разные, среды разработки разные.

      По Протеусу не скажу — не пользуюсь им..

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

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

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

    • Да вроде не забыл — » Естественно, это нас не устраивает, поэтому туда надо повесить потенциометр (резистор с переменным сопротивлением) для регулировки контрастности.» =)

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

    • Ну все просто на самом деле ) Пишешь для ПК программу, которая перехватывает нажатия клавиш и отправляет контроллеру (USART, USB….). Контроллер принимает и отображает на дисплей.

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

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

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

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

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

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

    • Может задержка перед первой буквой маленькая, но скорее всего с электрическим контактом проблема.

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

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *