Печать

Подключение LCD(HD44780) по 4-х разрядной шине. Русификация LCD

Автор: AntonChip Опубликовано . Опубликовано в Программирование на Си

Рейтинг:   / 18
ПлохоОтлично 

Для активизации четырехбитового режима надо программно сформировать сигналы управления согласно временным диаграммам на рис.1. По структуре они совпадают с диаграммой 8-ми разрядной шины за исключением удвоенного числа импульсов "Е". Линии связи проходят через старшие разряды шины данных DB4-DB7, младшие DB0-DB3 остаются не задействованными.

Рис.1

Достоинство режима - малое число проводников, упрощение топологии печатной платы, экономия линий портов МК. Недостаток - пониженная скорость передачи данных в ЖКИ, так как приходится информацию передавать двумя порциями (нибблами или тетрадами) по 4 бита в каждой. Однако, учитывая обязательные задержки времени в программе и физическую инерционность "жидких кристаллов", снижение скорости почти не чувствуется.

Принцип работы 4-х разрядной шины рассмотрим на примере тестовой программы для нашего LCD. На дисплей будут с секундными паузами выводиться цифры десятичного адреса знакоместа 0-255 и графические образы содержащихся в них символов.

Рис. 2

Как известно, каждый LCD имеет встроенный знакогенератор, представляющий собой область ПЗУ объемом более 8 Кб, которая прошивается на заводе-изготовителе. Традиционно первая половина ПЗУ с адресами 00-7Fh содержит начертания цифр, знаков препинания, а также заглавных и строчных букв латинского алфавита. Все как в IBM PC. Вторая половина "отдана на откуп" национальным алфавитам. В связи с этим HD44780 имеет модификации исполнения с тремя основными вариантами зашивки знакогенератора:

латиница и европейские языки (European standard font или Euro)
латиница и японские иероглифы (Japanese standard font или Japan)
латиница и кириллица (Custom font или Russian, рис.2)

Не все из ячеек знакогенератора заполнены. При обращении к "пустым" ячейкам на экране будет выведена произвольная информация, чаще всего состоящая из засвеченных точек. Первые 8 символов с адресами 0х00-0х07 отмечены "звездочкой". При желании они могут быть самостоятельно запрограммированы пользователем.

Какой знакогенератор имеется в конкретном LCD, должно быть указано в его условном обозначении или в технических параметрах, хотя на практике приходится верить честному слову продавца. Другой подход воочию увидеть на экране LCD все возможные начертания символов. Напишем, откомпилируем программу и запрограммируем контроллер, после чего в верхней строке экрана LCD будут с секундными паузами будут выводиться цифры десятичного адреса знакоместа 0-255 и графические образы содержащихся в них символов. Если графика и очередность появления символов соответствует рис.2, значит, LCD в порядке.

Далее собираем схему согласно рис.3, ее отличие только в том что шина данных подключена по 4-х проводной линии, т.е. DB4-DB7 подключены, а DB0-DB3 остаются не задействованными. Вывод R/W дисплея подключен на минус, т.к. дисплей у нас является приемником данных.

Подключение по 4-х проводной шине

Код программы проверки знакогенератора LCD приведен ниже.

// Программа проверки знакогенератора LCD

#include <avr/io.h>
#include <util/delay.h>

#define RS PC0 
#define EN PC2

// Функция записи команды в ЖКИ
void lcd_com(unsigned char p)
{
PORTC &= ~(1 << RS); // RS = 0 (запись команд)
PORTC |= (1 << EN);  // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // Выделяем старший нибл
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // Выделяем младший нибл
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}

// Функция записи данных в ЖКИ
void lcd_dat(unsigned char p)
{
PORTC |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // Выделяем старший нибл
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // Выделяем младший нибл
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}

// Функция инициализации ЖКИ
void lcd_init(void)
{
DDRC |= (1 << PC2)|(1 << PC0); // PC1, PC0 - выходы
PORTC = 0x00;
DDRD = 0xFF; // порт D - выход
PORTD = 0x00;

_delay_ms(50); // Ожидание готовности ЖК-модуля

// Конфигурирование четырехразрядного режима
PORTD |= (1 << PD5);
PORTD &= ~(1 << PD4);

// Активизация четырехразрядного режима
PORTC |= (1 << EN);
PORTC &= ~(1 << EN);
_delay_ms(5); 

lcd_com(0x28); // Шина 4 бит, LCD - 2 строки
lcd_com(0x08); // Полное выключение дисплея
lcd_com(0x01); // Очистка дисплея
_delay_us(100);
lcd_com(0x06); // Сдвиг курсора вправо
_delay_ms(10);
lcd_com(0x0C); // Включение дисплея, курсор не видим
}

// Основная программа
int main (void)
{
unsigned char znak = 0; // определяем переменную

lcd_init(); // Инициализация дисплея

while (1)
{
lcd_com(0x80); // Вывод в верхнюю левую позицию 1 строки
lcd_dat(znak/100 + '0'); // Выделяем сотни
lcd_dat((znak/10)%10 + '0'); // Выделяем десятки 
lcd_dat(znak%10 + '0'); // Выделяем единицы
lcd_dat('='); // Выводим знак равенства
lcd_dat(znak); // Выводим содержимое знакогенератора
_delay_ms(100); // Тут можно поменять задержку вывода символов
znak++; // Следующий символ знакогенератора
}
}

Комментарии  

+1 #21 Gren 01.03.2015 19:11
Сначала СПАСИБО!!!!! Всё просто и понятно объяснено)
Подскажите, пожалуста, как заюзать вторую строчку монитора))
Сообщить модератору
-1 #22 AntonChip 02.03.2015 21:12
Цитирую Gren:
Сначала СПАСИБО!!!!! Всё просто и понятно объяснено)
Подскажите, пожалуста, как заюзать вторую строчку монитора))

Командой lcd_com(0xC0);
вторая строка первый справа
Сообщить модератору
0 #23 Gren 04.03.2015 17:33
Спасибо,а вот еще вопрос) написал прогу,прошил настройки в мк ЖКИ, поигрался, надоело)))) написал вторую прогу, прошил)) ВОПРОС: нужно стирать этот МК ЖКИ от старой ппрошивки( первая прога) перед записью в него второй проги?
Сообщить модератору
0 #24 AntonChip 04.03.2015 20:18
Цитирую Gren:
Спасибо,а вот еще вопрос) написал прогу,прошил настройки в мк ЖКИ, поигрался, надоело)))) написал вторую прогу, прошил)) ВОПРОС: нужно стирать этот МК ЖКИ от старой ппрошивки( первая прога) перед записью в него второй проги?

Обычно при записи новой прошивки автоматически стирается старая, а так стирать конечно надо
Сообщить модератору
0 #25 Kybernetic 02.04.2015 20:07
:-) Четко написано. Спасибо!
Сообщить модератору
0 #26 Doublman 22.09.2015 12:14
Отличная публикация, просмотрел все содержимое своих дисплеев.
Можно ли и как командно регулировать контраст и яркость символов? Резисторами уже не получается.
Сообщить модератору
0 #27 Doublman 22.09.2015 12:20
Цитирую Gren:
ВОПРОС: нужно стирать этот МК ЖКИ от старой ппрошивки( первая прога) перед записью в него второй проги?

Практически все IDE проводят верификацию после программировани я и если прошивка не совпадает содержимым *.hex будет ERROR.
Сообщить модератору
0 #28 dmitr 10.12.2015 16:39
При выполнении команды:
lcd_com(0x28);

После загрузки старшего ниббла лсд сразу переходит в режим 4 бита, поэтому эту команду следует повторить, иначе работать не будет или работать будет неверно!
Сообщить модератору
0 #29 Великий Уравнитель 11.02.2016 21:28
Подскажите название трека, который играет на фоне.
Сообщить модератору
-1 #30 AntonChip 11.02.2016 23:08
Цитирую Великий Уравнитель:
Подскажите название трека, который играет на фоне.

Placebo, Pure Morning
Сообщить модератору
0 #31 Yuriy1 03.03.2016 21:14
У меня на горит только нижняя строчка в виде кубиков, подскажите что делать?
Сообщить модератору
0 #32 Yuriy1 03.03.2016 22:15
дисплей QAPASS 1602А. Может там другой метод инициализации
Сообщить модератору
0 #33 Doublman 03.03.2016 22:30
Схема простая до безобразия, проверяйте монтаж. Подстроечником R2 в цепи V0 попытайтесь выловить контрастность. Весь танец с бубном.
В правильности пошивки МК уверены?
Сообщить модератору
0 #34 Yuriy1 04.03.2016 07:40
все собрано на макетке и прошито правильно. Или дохлые или проходит инициализация 1602, у меня и две штуки, оба одинаково себя ведут
Сообщить модератору
0 #35 Yuriy1 04.03.2016 07:45
хотел написать -> не проходит инициализация
Сообщить модератору
0 #36 mastech 17.05.2016 01:51
как работает эта часть кода?
lcd_dat(znak/100 + '0'); // Выделяем сотни
lcd_dat((znak/10)%10 + '0'); // Выделяем десятки
lcd_dat(znak%10 + '0'); // Выделяем единицы
Сообщить модератору
0 #37 AntonChip 17.05.2016 15:06
Цитирую mastech:
как работает эта часть кода?
lcd_dat(znak/100 + '0'); // Выделяем сотни
lcd_dat((znak/10)%10 + '0'); // Выделяем десятки
lcd_dat(znak%10 + '0'); // Выделяем единицы

переменная znak меняется от 0 до 255, сначала переменную делим на 100, тем самым выделяя первый разряд и выводим этот разряд на дисплей
дальше, выделяем второй разряд, делим на 10 и делим на 10 с остатком, выводим на экран
дальше, выделяем третий разряд, переменную делим с на 10 с остатком, выводим на экран
Сообщить модератору

Рекомендуем посмотреть