Работаем с LCD дисплеем на основе микроконтроллера — HD44780 (ч.1)
ЖК дисплей на основе микроконтроллера HD44780 является наиболее часто используемым в электроники. Вы можете его встретить в кофейных автоматах, часах, копирах, принтерах, роутерах и т.п. Также данный дисплей используется в LCD шилдах для Arduino.
ЖК дисплей представляет из себя модуль, состоящий из микроконтроллера HD44780 разработанный фирмой Hitachi и непосредственно самим ЖК дисплеем. Микроконтроллер принимает команды и обрисовывает соответствующие символы на ЖК дисплее.
Существует огромное количество разновидностей данного ЖК модуля, он может быть 1,2, 4 –ех строчный с различным числом символов на строке, с подсветкой или без, с различным цветом подсветки и т.п. Объединяет их всех наличие микроконтроллера HD44780, зная команды которого позволит нам без проблем использовать в своих проектах ту или иную модификацию.
Предисловие
Для работы с дисплеями на основе HD44780 создано большое количество библиотек как на ассемблере так и на СИ, также для Arduino существует своя библиотека «LiquidCrystal».
Для изучения я решил не использовать наработки, а поработать с ним на «низком уровне», подергать его ножки самим, тем самым я получу представление о его работе. Полученные навыки позволят мне самому написать библиотеку если в этом будет необходимость.
Где взять первоисточник информации?
Если вы захотите сами разобраться как работать с LCD дисплеем на HD44780 и вникнуть глубже, то в этом вам поможет даташит на микроконтроллер HD44780, которые легко найти в интернете (но если вам лень, вы можете скачать с сайта).
Изучение я разобью на два этапа
1. Сначалая я приведу матчасть по работе с LCD на HD44780, этому посвящён данный пост
2. Далее, в следующем посте, я буду использовать модель дисплея LMO16L в Proteus. (LMO16L это один из типичный дисплеев на HD44780)
- на данном этапе я отработаю протокол взаимодействия с дисплеем используя PATTERN GENERATOR.
- после того, как отработаю протокол, я напишу прошивку для Arduino, попробую её на той же модели LMO16L и испытаю на реальном Arduino с подключенным LCD шилдом. Если дисплей будет работать также как и на модели, можно считать что мы умеем работать с ЖК дисплеем.
- для закрепления, я напишу прошивку на ассемблере для Atmega8 и испробую её на LMO16L
В данном посте я расскажу:
- как подключить дисплей
- как происходит обмен информацией
- какие бывают команды
- и как его инициализировать
P.S. разделы кликабельны, при нажатие вы спускаетесь к соответствующему разделу
Как подключить дисплей?
Все дисплеи на основе HD44780 имеет схожую распиновку
Где
- GND – земля (иногда пишут Vss)
- Vcc – напряжение питания +5В (иногда пишут Vdd)
- Vo – напряжение контрастности от 0В до +5В, данный вывод надо подключить к потенциометру, для регулировки
- RS –вывод с помощью которого, дисплей определяет что в него поступает данные или команды
- RW – вывод с помощью которого, дисплей определяет передавать или получать данные
- E – линия синхронизации
- D0 – D7 – шина команд/данных
- LED + , LED — – выводы для питания подсветки
Дисплей может работать в 2-ух режимах:
- в 8-и разрядном (т.е. когда, для обмена информацией используются контакты от D0 до D7), данные пересылаются за один такт
- в 4-ех разрядном (для обмена используются только контакты D4 – D7), в этом случае данные пересылаются за 2-а такта, сначала старшие 4-е бита, потом младшие 4-е бита.
Мы будем экономить выводы микроконтроллера и подключим наш дисплей для работы в 4-ех разрядном режиме.
В качестве примера я показал подключение дисплея к ATmega8, хотя, можно использовать любой другой микроконтроллер. Выводы D4-D7, RS, E подключаются к любому цифровому порту микроконтроллера. Вывод RW мы использовать не будем, т.к. нам нет практической нужды принимать данные из ЖК (это обычная практика), наша задача — только передавать. По этому, свободные выводы RW, D0 – D3 посадим на землю.
Заметьте что Ve (управление контрастностью) подключается через реостат (можно через делитель напряжения), вполне уверен, что вы проигнорируете и подключите его или к 5В или к земле. Сразу скажу, что тогда, на экране вы ничего не увидите, т.к. при минимальной или максимальной контрастности дисплей не способен вывести что ни будь различимое.
Как происходит обмен информаций с ЖК?
Мы будем говорить о 4-ех разрядном режиме ЖК, поэтому для работы нам потребуется минимум 6 линий микроконтроллера.
Итак общение с ЖК происходит с помощью управляющих выводов:
RS – логическая единица ЖК принимает данные, логический ноль ЖК принимает команды;
С помощью линий данных:
D4 – D7 — разряды идут от младшего к старшему
И с помощью вывода стобирующих импульсов:
E
ЖК принимает информацию с помощью D4-D7, которая может быть данными (ASCII код выводимого символа) если на RS логическая единица или командой (очистить экран, перенести курсор и т.п.) если на RS логический ноль. О том, какие бывают команды я расскажу позже, сейчас сконцентрируем внимание на физическом уровне взаимодействия.
Обмен информацией происходит по байтно, т.к. мы говорим 4-ех разрядном режиме, то микроконтроллер выставляет на D4-D7 логические единицы и логические нули, которые соответствуют старшему передаваемому полубайту, далее на E формируется стробирующий импульс, по заднем фронту которого ЖК считывает данные.
Далее микроконтроллер заново выставляет на D4-D7 логические единицы и логические нули, которые соответствуют младшему передаваемому полубайту и опять на E формируется стробирующий импульс, по заднем фронту которого ЖК считывает данные. После некоторой временной паузы (зависит от команды) цикл передачи байта данных или команды повторяется, ничего сложного.
Если работать в 8-и разрядном режиме, то будут задействованы D0 – D7 и данные/команды будут передаваться за один такт, а не за два.
Какие бывают команды?
Команды ЖК на HD44780 можно разделить на две группы:
- команды настройки и записи в ЖК (9 команд)
- команды чтения из ЖК (2-е команды)
Т.к. мы не будем считывать с ЖК (вывод RW посадили на ноль), то, я рассмотрю команды для настройки и записи, которые для удобства я свел в таблицу и пронумеровал, весь список вы можете посмотреть в даташите на странице 191.
Каждая команда имеет свою длительность выполнения, это означает, что необходимо выдержать данный интервал времени перед подачей следующей команды или данных.
По порядку разберем, какая память есть в HD44780 и как работают команды…
Микроконтроллер HD44780 содержит следующую память:
- DDRAM;
- CGROM;
- CGRAM.
1. В DDRAM памяти содержится ASCII коды символов которые в данный момент отображаются на экране, еще её называют видеопамять. Для 16-и символьных 2-ух строчных дисплеев её размер составляет 80 байт, т.е. по 40 байт на каждую строку. Каждый символ занимает 1 байт. У вас может возникнуть вопрос, почему 40 байт, ведь символов на строке 16? Дело в том, что на дисплеи отображается только часть DDRAM, с 0х80 по 0х8F включительно для 1-ой строки и с 0хС0 по 0хСF включительно для 2-ой строки, остальную часть не видно.
Перенести черту видимости вправо или влево, можно с помощью команды №5. Для этого, нужно выставить S/C=1 и R/L в зависимости от направления, если вправо —R/L=1, если влево — R/L=0. Таким образом мы можем передвигать видимую часть по DDRAM, ширина её все равно останется равным 16-и символам для 1-й строки и 16-и символам для 2-й строки.
С помощью команды №5 передвигая видимую часть DDRAM, мы получаем эффект бегущей строки, например команда №5 была послана ЖК модулю 7 раз:
В дисплеи есть так называемый счетчик адреса или курсор, который начинает считать с 0x80 (в экране это левый верхний угол), при записи нового символа в DDRAM счетчик инкрементируется или декрементируется.
Помимо этого, с помощью команды №5 можно перемещать сам курсор, если выставить S/C=0 и R/L в зависимости от направления, если вправо —R/L=1, если влево — R/L=0.
Команда №1 служит для очистки памяти DDRAM, следовательно, всех текущих отображающихся символов и установки курсора в начальное положение, т.е. в верхний левый угол дисплея.
Команда №2 не очищает DDRAM, а только устанавливает курсор в начальное положение, т.е. в верхний левый угол дисплея.
Дисплей по умолчанию не знает, в какую сторону сдвигать курсор при записи, для этого существует команда №3. Если бит ID=1, то курсор после записи символа сдвигается вправо (инкрементируется), если ID=0 (декрементируется), то влево.
Например, пусть курсор установлен в начальное положение (в левый верхний угол), то, для случая, когда ID=1 – курсор смещается при записи вправо, буква за буквой выводится слева на право (это типичный случай).
Пусть курсор также установлен в начальное положение (в левый верхний угол), но ID=0 – курсор смещается при записи влево, буква за буквой выводиться справа налево, то, мы получим следующее:
Первый символ ‘s’ поместился на экране, а следующие уже вышли за него. Не знаю, зачем вам может понадобиться вывод символов справа налево, но в данном случае вам нужно устанавливать курсор заранее зная количество символов или в конец строки.
Установив бит S=1 в этой-же команде, вы разрешаете сдвигать экран при записи символов. Если курсор инкрементируется (т.е. пишем слева на право), то экран будет сдвигаться влево. Если пишем справа налево, то экран будет сдвигаться вправо. Запутались? =)
Например, если мы установим курсор в правый нижний угол (команда №5), далее в команде №3 установим ID=1 (пишем слева направо) и S=1 (разрешаем сдвигать экран при записи), то при записи s-engineer.ru мы получим следующий результат.
Текст выводился слева на право (как обычно) и сдвигался влево.
С помощью команды №4 мы можем включать и отключать отображение DDRAM памяти на дисплеи. Установив бит D=0, дисплей прекращает отображать символы, но в памяти DDRAM они остаются, при D=1 дисплей отображает содержимое DDRAM.
Бит С позволяет отобразить курсор, если С=1, то курсор в виде символа “_”, если С=0 курсор не виден.
Если установить бит В=1, то курсор будет мигать, если В=0 курсор не мигает.
Команда №6 используется при инициализации ЖК, если бит DL=1, то, дисплей использует с DB0 по DB7, а при DL=0, только 4-е вывода шины, т.е. с DB5 по DB7.
Бит N указывает сколько строк мы будем использовать (N=1 две строки, N=0 одну строку).
Разряд F позволяет указать размер шрифта, обычно используется 5х7 при F=1, но можно использовать и 5х10 при F=0 используя только одну строку (обычно, данный функционал не работает).
С помощью команды №8 можно указать в какую ячейку DDRAM мы будем записывать ASCII код символа. Она похожа на команду №5, т.к. в ней мы тоже управляем перемещением курсора, но только уже по адресам. Командой №8, мы можем использовать для своих нужд часть памяти DDRAM, которая не отображается на дисплеи.
Команда №9 переставляет собой просто данные. С её помощью производится запись ASCII кода символа в DDRAM память для его отображения на ЖК дисплеи. Для 4-ех разрядного режима, запись производится в два такта, сначала старший полубайт, потом младший полубайт.
Например, пошлем код 0x53, что соответствует знаку ‘S’.
2. В памяти CGROM храниться «битовое изображение» выводимых символов. См. таблицу ниже
Т.е. когда мы посылаем в DDRAM код 0x53, микроконтроллер HD44780 ищет ячейку 0x53 в CGROM и отрисовывает символ в соответствие с 1-и и 0-и данной ячейки.
(не всегда микроконтроллер содержит в CGROM кириллицу, там могут быть латинские или японские символы)
3. Память CGRAM является частью CGROM. Главное её свойство заключается в том, что мы можем записывать в неё свои символы. Для этого нужно воспользоваться командой №7, в которой мы указываем адрес ячейки и далее командой №9 отправить 8 байт под ряд с «битовым изображением символа»
Я решил создать символ состоящий из ‘s e’ по вертикали.
Далее, мы можем вывести данный символ, используя команду №9 зная его адрес ячейки.
Как инициализировать дисплей на HD44780?
Т.к. ЖК дисплей содержит микроконтроллер, следовательно его необходимо проинициализировать, т.е. привести в рабочее состояние.
Почитав множество форумов и блогов я понял, что вопрос инициализации не так прост, как кажется. Если слепо следовать даташиту, то результат не всегда бывает положительный.
Я вывел для себя универсальную последовательность команд для инициализации, я проверил её на модели ЖК дисплея LM016L в Proteus и на реальном ЖК дисплеи WH1602B (LCD шилд для Arduino).
Итак для успешной инициализации нам необходимо послать следующую последовательность команд и выдержать паузы:
(картинка кликабельна)
Вы могли заметить, что для первой команды 0x30 не нужно выдавать младший полубайт, это потому, что, дисплей сразу принимает данные в 8и битном режиме, а т.к. DB0-DB4 у нас посажены на ноль, мы не можем ими управлять, да это и не нужно.
Если кратко, то инициализация это последовательность команд
- Команда №6 — 0x30 – установить режим 8 бит
- Команда №6 — 0x28 – установить режим 4 бита
- Команда №4 — 0x08 – выключить дисплей
- Команда №1 — 0x01– сброс дисплея
- Команда №3 — 0x06– при записи, курсор сдвигать вправо
- Команда №4 — 0x0C – включить дисплей
Вам будет интересно:
Буду признателен если вы поделитесь данным постом
Супер, всё разложено по полочкам. Спасибо.
Спасибо вам!
Буду не против если кликните рекламку или сделайте пожертвование =)
Познавательно и разжевано. Но зачем было инвертировать ввод данных(запись с младшего байта, а не со старшего). Запутался, очень.
Спасибо, за отличную работу!
Мое уважение к тебе Admin.Спасибо!
Спасибо за такой труд. Я только делаю первые шаги в этом деле (программирование мк) и очень рад видеть подобные обьяснения в интернете. Очень тяжело начинать и помогают только такие подробные уроки. Сайт в закладках. Буду учиться. Рекламу буду кликать на каждой статье полезной)))) Спасибо…
Спасибо Владимир за хороший отзыв.
Насчет рекламы спасибо! ) Мне это сильно помогает =)