Avr как подключить дисплей

Обновлено: 07.07.2024

В этой статье приведен пример подключения LCD индикатора к микроконтроллеру AVR, а именно ATmega8. При выборе LCD cледует различать обычные многопозиционные LCD серии ИЖКЦ, модули на их основе с микросхемой HT1611 и алфавитно-символьные LCD с встроенным контроллером. Именно последние и относят к наиболее перспективным изделиям. В подтверждение тому множество фирм в мире, специализирующихся на выпуске подобной продукции. Крупнейшие из них находятся в Тайване, Китае, Японии, США.

Среди параметров, отличающих одни LCD от других, выделяется марка внутреннего контроллера. В дальнейшем будут рассматриваться только модели, совместимые с контроллером HD44780 (фирма Hitachi) и его аналогами, например, KS0066 (фирма Samsung), SED1278
(фирма Epson), ST7066 (фирма Sitronix). Таких изделий на отечественном рынке подавляющее большинство, да и в любительских конструкциях они стали стандартом "де-факто".

При покупке LCD надо поинтересоваться следующими моментами:

поддерживается ли система команд HD44780 ("Да");
имеется ли русификация знакогенератора с выводом больших и малых букв ("Да");
однополярное или двухполярное требуется питание ("Однополярное +5 В");
имеется ли подсветка (если "Да", то нужна светодиодная, а не электролюминесцентная);
сколько символов и строк отображается на экране LCD ("8x1",
"8x2", "16x1", "16x2", "20x2", "20x4" и т.д.).

Внутреннее устройство LCD

Контроллер синхронизируется внутренним RC-генератором G1, имеющим частоту 250 ±50 кГц. Напряжение подсветки подается через выводы А и К на светодиоды, которые освещают ЖК-панель с торца или обратной стороны корпуса. Светодиоды включены матрицей и соединены параллельно-последовательно. В связи с этим напряжение подсветки довольно высокое 4,0. 4,2 В.

Назначение и нумерация всех внешних выводов LCD унифицированы (рис.2). Это не зависит от количества строк и символов, будь то "8x1" или "16x2". Даже контакты светодиодной подсветки 15, 16 имеются на всех LCD, хотя при ее физическом отсутствии они будут просто "висеть в воздухе".

Небольшой нюанс. На печатной плате LCD порядок нумерации контактных площадок отличается от модели к модели. Например, встречаются следующие варианты: слева направо 1-16, справа налево 16-1, вперемежку 15, 16, 1-14. Подсказку следует искать визуально по отмаркированным цифрам на печатной плате. Контакты 15, 16 обычно дублируются еще одной парой контактов с маркировкой А и К соответственно. Электрически они соединены параллельно.

Конструктивно выводы могут располагаться сверху, снизу или на боковой стороне платы LCD. Это не суть важно, ведь соединяться с изделием они будут жгутом проводов длиной до 10 см. Крепление LCD производится винтами через 4 угловых отверстия.

Электрический интерфейс состоит из трех шин:

DB0-DB7 шина данных;
RS, R/W, E шина управления;
VCC, GND, Vo, A, K шина питания.

Внимание: перед подключением питания VCC и GND внимательно прочитайте описание на Ваш дисплей, т.к. контакты питания у некоторых дисплеев могут различаться.

Типовая схема подключения LCD к МК показана на рис.3. Именно она и будет использоваться для первой тестовой проверки LCD с выведением на экран знаменитой фразы "Hello, world!" ("Здравствуй, мир!"). Кнопка SB1 осуществляет начальный сброс. Переменным резистором R2 регулируют контрастность изображения. Его сопротивление непринципиально и может меняться от 5 до 20 кОм.

Рис. 3

Кстати, резистор R2 является первым элементом, который надо обязательно покрутить в разные стороны при начальном включении питания. Если LCD исправен, то в крайних положениях движка будут наблюдаться полное гашение и полная засветка экрана.

Отрегулировать R2 следует на перегибе характеристики, как правило, с потенциалом ближе к общему проводу, когда слабо видны все точки знакомест на LCD. Неправильная установка контрастности может привести к ложному выводу о дефекте индикатора, хотя все, что надо сделать, это покрутить движок резистора.

Управляющая программа хранится в МК DD1. Чтобы облегчить ее составление, здесь и в дальнейшем приняты некоторые упрощения.

Во-первых, LCD будет работать только на прием информации по всем 11 соединительным линиям шины данных и управления.

Во-вторых, экран LCD считается жестко привязанным к начальной позиции с фиксированными адресами знакомест.

В-третьих, при программировании будет использоваться ограниченный набор команд (желающие смогут в последствие расширить свои познания, изучив DATASHEET на HD44780.

Программное управление LCD

Поскольку внутри LCD находится свой собственный контроллер со своей разветвленной системой команд, то задача упрощается. Две такие мощные и интеллектуальные микросхемы, как HD44780 и ATmega8, смогут быстро между собой "договориться" на машинном языке. Труд программиста заключается в том, чтобы "объяснить" контроллерам правила общения и установить протокол соединения.

Таблица 3

В таблице (см. выше) показана расшифровка наиболее употребляемых команд, посылаемых от МК в LCD, а на рис.4 - показаны команды для перехода на определенное знакоместо верхней или нижней строки экрана. Время выполнения команд указано приблизительно. Оно определяется частотой внутреннего RC-генератора LCD, которая, в свою очередь, зависит от технологического разброса и температуры нагрева корпуса.

Рисунок 4

Различают команды прямого и косвенного действия. Первые из них занимают адреса 0x01-0x3F и не требуют передачи данных. За вторыми (диапазон выше 0x3F) обязательно следует передача одного или нескольких байтов информации. Для примера на рис.5 показаны временные диаграммы выполнения команды 0x80 "Установка курсора в первое знакоместо верхней строки экрана" и индикация в нем цифры "4" пересылкой кода данных 0x34.

Рисунок 5

Формировать диаграммы, показанные на рис.5, должен МК с учетом задержек из табл.3, необходимых контроллеру LCD на выполнение команд. Для повышения устойчивости работы экономить на задержках не надо. По крайней мере, при отладке программы они должны быть достаточно большими.

Каждое знакоместо на экране LCD имеет свой логический адрес. Представить его можно в виде регистра, куда заносится один байт информации. В зависимости от содержимого байта на экране появляется тот или иной символ. Распределение символов соответствует таблице знакогенератора, похожей на применяемые в шрифтах компьютера.

Далее показана Си-программа для тестовой проверки LCD по схеме, собранной на рис.3.

Функции "lcd_com" и "lcd_dat" формируют соответственно левую и правую половину временных диаграмм, показанных на рис.5.

Без процедуры инициализации ни один LCD работать не будет. Это самая важная часть листинга. Именно на процессе инициализации часто "спотыкаются" начинающие программисты. Дело в том, что в разных источниках приводятся разные варианты последовательностей команд инициализации и не все из них гарантированно будут работать с конкретным LCD.

Наиболее общая процедура инициализации приведена в DATASHEET на HD44780. Функция "lcd_init" в целом повторяет ее с тем отличием, что команда полного выключения дисплея 0х08 поставлена первой, чтобы при включении питания на экране не появлялся "мусор". Здесь нет ограничений против экспериментов, главный критерий - практика.

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

Сегодня мы начнём изучение жидкокристаллического индикатора символьного, который способен выводить определённые символы в две строки по 16 символов в каждую. Изучать мы данный индикатор будем с целью его подключения к микроконтроллеру AVR и управления им.

Выглядит индикатор, с которым мы будем работать вот таким вот образом

image00

То есть индикатор выполнен в виде модуля, в котором установлен контроллер HD44780, предназначенный для управления дисплеем. Также, как мы видим, в данном модуле существуют 16 контактов, которые я припаял самостоятельно и к которым мы и будем подсоединяться с контроллера с помощью проводов. Поставляется данный модуль без контактов. На их месте существуют контактные технологические отверстия. Скорее всего, сделано это для того, чтобы мы сами могли выбрать тип контактов, которые нам будут удобны для работы с данным модулем.

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

Например, модуль компании Winstar на 1 ножке имеет анод, а наш китайский дисплей, который стоит дешевле, в отличие от Winstar, на данной ножке имеет катод.

Поэтому будьте внимательны и читайте документацию на тот именно модуль, который будет у вас.

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

image01

Ну раз уж мы увидели надписи на ножках модуля, давайте тогда разберёмся, какая ножка для чего служит. Пойдём слева направо.

Также данную информацию мы видим в технической документации на дисплей

image02

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

image03

Например, первая команда Clear Display говорит сама за себя. Она очищает дисплей. Вообще за отображение на дисплее у нас отвечает оперативная память DDRAM, также существующая в контрроллере дисплея. Вот данную память как раз и очищает данная команда.

Остальных команд мы коснёмся несколько позднее.

Теперь идём дальше по технической документации. Дальше идёт объяснение каждой команды и назначение каждого бита, представленного в таблице. Мы можем заметить, что в таблице каждый используемый бит как-то называется.

image04

Также посмотрим организацию знакомест дисплея в памяти DDRAM. Это нам будет необходимо для написания функции позиционирования

image05

Как мы видим, вторая строка находится в области видиопамяти через некоторый пропуск после первой. Во-первых, существуют дисплеи разной размерности, например у меня ещё есть дисплей 20х4 на том же контроллере, поэтому и пропуск. Также существует определённая команда, которая передвигает видимую часть памяти, это может быть использовано для подготовки символов в невидимой области, а затем путём передвижения невидимую область мы делаем видимой. Нам это пока не требуется. Если потребуется, то мы обязательно с этим разберёмся, ну либо для какого-то красивого скроллинга дисплея также может это потребоваться.

Подобная документация существует также не только на дисплей, а ещё и на контроллер. Я её также в конце статьи обязательно приложу к страничке.

А теперь наконец-то проект.

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

Для протеуса проект мы скопируем как и раньше, переименовав его в Test09, и выбрав путь к прошивке нового проекта, чтобы нам заново не искать контроллер, резисторы и прочие вещи, а также не настраивать контроллер.

Вернемся в наш проект в студию. Верхнюю часть файла, где мы объявляем частоту и подключаем библиотеки, мы, в принципе можем всё-таки их прошлого кода скопировать

Скомпилируем код, чтобы у нас была хотя бы какая-то прошивка.

Напишем функцию port_ini(). Под все ножки модуля дисплея мы будем использовать порт D. Так как режим у нас 4-битный, то нам вполне хватит ножек, даже останутся

void port_ini ( void )

PORTD =0x00;

DDRD =0xFF;

Также давайте данную функцию вызовем в функции main()

port_ini (); //Инициализируем порты

Зайдём теперь в проект в протеус и найдем там дисплей в библиотеке компонентов

image06

Подключим его следующим образом

image07

Если мы запустим проект, то мы увидим всего лишь, что дисплей у нас просо будет светиться и всё.

Для начала оговорюсь сразу, что речь тут пойдет о LCD индикаторах на контроллере HD44780, который стал промышленным стандартом де-факто на рынке цифро-буквенных дисплеев. Продается везде где только можно, стоит недорого (8х2 мне обошелся порядка 150 рублей), а также под него написана куча кода. Я же, как обычно, решил изобрести велосипед и сварганить свою собственную тру-библиотеку для работы с этим типом индикаторов. Разумеется на ассемблере, а на чем же еще? ;)

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

Доступ к памяти.
Тут все просто. Мы командой выбираем в какую именно память и начиная с какого адреса будем писать. А потом просто шлем байты. Если указано, что записываем в DDRAM то на экран (или в скрытую область) полезут символы, если в CGRAM то байты полезут уже в память знакогенератора. Главное потом не забыть переключится обратно на область DDRAM

Система команд.
Система команд проста как мычание. О том, что передается команда контроллеру дисплея сообщит нога RS =0. Сама команда состоит из старшего бита, определяющего за что отвечает данная команда и битов параметров, указывающих контроллеру HD44780 как дальше жить.

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

Первым делом Инициализация дисплея без которой большая часть дисплеев на HD44780 просто откажется работать. Некоторые виды имеют дефолтные состояние (шина 8 бит, курсор в 0) и им только дисплей включить. Но все же ее лучше сделать, мало ли что там намудрил разработчик. Лишней не будет.

Задача: создать свой символ. С кодом 01 и вывести его на экран.
Считаем, что дисплей у нас уже инициализирован и готов к приему данных.

Так, с логикой разобрались, пора вкуривать в физику протокола общения. Код я приведу несколько позже, когда вылижу свою библиотеку и заоптимизирую до состояния идеала. Пока же дам алгоритм, а его уж на любом языке программирования реализовать можно. Хоть на ассемблере, хоть на Сях, да хоть на Васике :)

Алгоритм чтения/записи в LCD контроллер HD44780
Направление, а также команда/данные определяются ножками, а чтение и запись осуществляется по переходу строба (вывод Е) из 1 в 0

С четырех разрядной шиной все точно также, только там каждая операция чтения/записи делается за два дрыга строба.

  1. E=1
  2. Пауза
  3. Выставили в порт старшую тетраду
  4. E=0
  5. Пауза
  6. Е=1
  7. Пауза
  8. Выставили в порт младшую тетраду
  9. Е=0
  1. E=1
  2. Пауза
  3. Читаем из порта старшую тетраду
  4. Е=0
  5. Пауза
  6. Е=1
  7. Пауза
  8. Читаем из порта младшую тетраду
  9. Е=0

Ждите код :) Скоро будет :)
UPD:
А вот и код!

Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!

А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.

347 thoughts on “AVR. Учебный курс. Подключение к AVR LCD дисплея HD44780”

Однако познавательно! Как только появится свободное время, надо будет это все расковырять =) Как раз 8ю атмегу в ДИПе достану и панельу к ней. Надо будет спаять какую-нить полезную хреновину =) В любом случае спасибо автору. Он и на этот раз не подвел. Толковые вещи пишешь =)

Уважаемый автор! Спасибо за прекрасную статью.Прошёлся по ней несколько раз,но чем определяется видимая область-не нашёл или не понял.Пожалуйста поясните.Заранее благодарен. frolov.

Видимой областью же. Размером экрана и количеством знакомест на нем.

Это понятно,но с какого адреса начинается видимая область?Например,заносим информацию по адресу 0x20 8 знаков,затем ровно под ней по адресу 0x40 ещё 8 знаков(это по вашему рисунку).Потом включаю дисплей. Чтобы то,что я занёс было на экране нужно-ли вставать на адрес 0x20? А если я встану на адрес 0x10? Изменится видимая область? Если так,то с какой стороны от адреса она окажется с левой или правой,зависит-ли это от включенности инкремента или декремента. Извини DI HALT но я живу в маленьком городе,дисплея пока нет,заказал.Когда будет неизвестно,а код пишу,вот и возникают такие вопросы.Извини за назойливость.Спасибо.

Спасибо DI HALT! Чуть прояснилось.Ещё раз понял,что лучшая форма обучения-это самообучение.Как сказал Иртеньев
Всё накрылось медным тазом,
Но покуда тлеет разум
Ощущения конца
Всё же нету до конца.

Уважаемый Di Halt. Спросить не у кого,если не трудно ответь. Никогда не занимался с mega8.Может быть у неё есть какие-нибудь особенности.Я просто растерялся. Как будто с мегой32 когда включен jtag.Но в меге8 jtaga нет.В чём может быть причина. В симуляторе avr studio всё хорошо,а после прошивки ничего даже близкого нет. Посоветуй.

Телепаты в отпуске.

Уважаемый Di Halt. Поздравляю Вас с Праздником,правда как его правильно назвать-уже не знаю. Всю свою жизнь отдал оборонке, а названия увы.Прочитал Вашу статью про ЦАП. Ответьте пожалуйста как конфигурировать ноги МК к которым подключен R-2R? Ответьте. Если что неправильно спросил,то извините.

Как Push-Pull естественно.

Уважаемый Di Halt! Сегодня всё утро искал Push-Pul,но ничего конкретного не нашёл. Если не трудно,черкни пару строк на ассемблере для примера.Сложно,если вырос на минск-22, осваивать МК. Другой уровень абстракции. Спасибо.

DDR=1
PORT= нужный уровень

Уважаемый DI HALT! Ответь пожалуйста ещё на один вопрос. Управление 16 разрядным дисплеем такое же как и 8 разрядным?Спасибо.

WH0802A – двухстрочный символьный дисплей на 8 знакомест со встроенным управляющим контроллером KS0066.
Разбираем назначение выводов дисплея.

назначение выводов lcd

У некоторых дисплеев есть два дополнительных вывода – выводы подсветки +LED и –LED. Причем если выводы есть – это еще не означает что есть и подсветка. Как и наоборот. У моего дисплея подсветка есть, а выводов управления нет.

По умолчанию подсветка у дисплея WH0802A-YGH-CT отключена. Чтобы ее включить, нужно проделать парочку нехитрых манипуляций, а именно – установить две перемычки и впаять токоограничительный резистор (смотри на фотке RK, JF и RA соответственно).

WH0802A с обратной стороны

схема подключения lcd к микроконтроллеру

Это типовая схема включения символьных LCD. Схему управления подсветкой дисплея мы задействовать не будем, но я ее на всякий случай нарисовал. Контроллер символьного ЖК-дисплея, не обладает бесконечным быстродействием, поэтому между некоторыми операциями используются программные задержки. Первая нужна для удержания на некоторое время строб сигнала, вторая, для того чтобы контроллер успел записать данные или выполнить команду. Величины задержек всегда приводятся в описании на контроллер дисплея и нужно всегда выдерживать хотя бы их минимальное значение, в противном случае неизбежны сбои в работе контроллера.
Вообще у контроллера дисплея есть так называемый флаг занятости – BF. Если флаг в 1 – контроллер занят, если в 0 – свободен. Вместо второй программной задержки можно читать флаг занятости и проверять, когда контроллер дисплея освободится. Но поскольку мы хотим быстро получить первые результаты, с флагом занятости будем разбираться потом.
//функция записи команды
void LcdWriteCom( unsigned char data)
ClearBit(PORT_SIG, RS); // устанавливаем RS в 0
PORT_DATA = data; // выводим данные на шину
SetBit(PORT_SIG, EN); // устанавливаем Е в 1
_delay_us (2);
ClearBit(PORT_SIG, EN); // устанавливаем Е в 0
_delay_us(40); void LcdWriteData( unsigned char data)
SetBit(PORT_SIG, RS); //устанавливаем RS в 1
PORT_DATA = data; //выводим данные на шину
SetBit(PORT_SIG, EN); //устанавливаем Е в 1
_delay_us (2);

int main( void )
while (1);
return 0;
>

Здесь нет сложных мест, все должно быть понятно. Идем дальше.

Любой ЖК-дисплей перед использованием нужно инициализировать. Процесс инициализации обычно описан в datasheet`е на контроллер дисплея. Но даже если там и нет информации, последовательность, скорее всего, будет такая.

1. Подаем питание

2. Ждем >40 мс

3. Подаем команду Function set


DL – бит установки разрядности шины
0 – 4 разрядная шина, 1 – 8 разрядная шина

N – бит установки количества строк дисплея
0 – однострочный режим, 1 – двухстрочный режим

F – бит установки шрифта
0 – формат 5*8, 1 – формат 5*11

* - не важно что будет в этих битах

4. Подаем команду Display ON/OFF


D – бит включения/выключения дисплея
0 – дисплей выключен, 1 – дисплей включен

C – бит включения/выключения курсора
0 – курсор выключен, 1 – курсор включен

B – бит включения мерцания
0 – мерцающий курсор включен, 1 – мерцающий курсор выключен

5. Подаем команду Clear Display




6. Ждем > 1,5 ms

7. Подаем команду Entry Mode Set


I/D – порядок увеличения/уменьшения адреса DDRAM(ОЗУ данных дисплея)
0 – курсор движется влево, адрес уменьшается на 1, 1 – курсор движется вправо, адрес увеличивается на 1

SH – порядок сдвига всего дисплея
0 – сдвига нет, 1 – сдвиг происходит согласно сигналу I/D – если он 0 – дисплей сдвигается вправо, 1 – дисплей сдвигается влево

Читайте также: