В этом разделе мы подробно рассмотрим, как подключить жидкокристаллический индикатор к МК 68HC12. Мы начнем с краткого обзора принципа действия ЖК индикаторов. Далее изучим реальный однострочный символьный индикатор на 16 знакомест со встроенным контроллером управления. Рассмотрим, как выполнить аппаратное подключение этого индикатора к МК, а затем приведем пример программы управления.
5.6.1. Краткие сведения о жидкокристаллических индикаторах
Жидкокристаллический индикатор — почти идеальное устройство отображения информации. Этот тип индикаторов использует для своей работы те же напряжения, что и микроконтроллеры, но при этом потребляет энергию на несколько порядков меньшую, чем светодиодные индикаторы. Именно поэтому жидкокристаллические (далее ЖК) индикаторы нашли чрезвычайно широкое применение в переносных устройствах с автономным питанием. В электронных часах, калькуляторах и стационарных телефонах принято использовать монохромные ЖК индикаторы, в то время как современные мобильные телефоны, фотоаппараты и видеокамеры немыслимы без малогабаритного цветного ЖК-дисплея. По способу отображения информации ЖК индикаторы также подразделяются на цифро-буквенные и графические.
Для понимания технологических особенностей создания современных ЖК индикаторов и дисплеев следует коротко остановиться на основных свойствах жидких кристаллов. Жидкие кристаллы представляют собой почти прозрачные субстанции, проявляющие одновременно свойства кристалла и жидкости. Есть две главные особенности жидких кристаллов, благодаря которым возможно создание на их основе устройств отображения информации: способность молекул жидких кристаллов переориентироваться во внешнем электрическом поле и изменять поляризацию светового потока, проходящего через их слои.
Основой ЖК индикатора являются две параллельные стеклянные пластины с нанесенными на них поляризационными пленками. Различают верхний и нижний поляризаторы, сориентированные перпендикулярно друг другу. На стеклянные пластины в тех местах, где в дальнейшем будет формироваться изображение, наносится прозрачная металлическая окисная пленка, которая в дальнейшем служит электродами. На внутреннюю поверхность стекол и электроды наносятся полимерные выравнивающие слои, которые затем полируются, что способствует появлению на их поверхности, соприкасающейся с жидкими кристаллами, микроскопических продольных канавок. Пространство между выравнивающими слоями заполняют жидкокристаллическим веществом. В результате молекулы жидких кристаллов выстраиваются в направлении полировки полимерного слоя. Направления полировки верхнего и нижнего слоев полимера перпендикулярны (подобно ориентации поляризаторов). Это нужно для предварительного "скручивания" слоев молекул жидких кристаллов между стеклами на 90°. Когда напряжение на управляющие электроды не подано, поток света, пройдя через нижний поляризатор, двигается через слои жидких кристаллов, которые плавно меняют его поляризацию, поворачивая её на угол 90°. В результате поток света после выхода из ЖК материала беспрепятственно проходит через верхний поляризатор (сориентированный перпендикулярно нижнему) и попадает к наблюдателю. Никакого формирования изображения не происходит. При подаче напряжения на электроды между ними создается электрическое поле, что вызывает переориентацию молекул жидких кристаллов. Молекулы стремятся выстроиться вдоль силовых линий поля в направлении от одного электрода к другому. Вследствие этого пропадает эффект «скручивания» поляризованного света, под электродом возникает область тени, повторяющая его контуры. Создается изображение, формируемое светлой фоновой областью и темной областью под включенным электродом. Путем варьирования контуров площади, занимаемой электродом, можно формировать самые различные изображения: буквы, цифры, иконки и пр. Так создаются символьные ЖКИ. А при создании массива электродов (ортогональной матрицы) можно получить графический ЖКИ с разрешением, определяемым количеством задействованных электродов
Большинство современных ЖК индикаторов и дисплеев управляются от микроконтроллеров, которые располагаются на обратной стороне индикатора. Микроконтроллер преобразует цифровые коды, содержащие информацию об отображаемом объекте, в последовательность импульсов напряжения для электродов индикатора. В постоянной памяти этого МК записаны образы символов, которые могут отображаться индикатором (функция знакогенератора). В оперативной памяти МК размещаются коды тех символов, которые высвечиваются на экране индикатора в текущий момент времени. Поэтому, когда Вы производите подключение ЖК индикатора к МК, Вы фактически устанавливаете связь между двумя микропроцессорными системами.
В следующем параграфе мы рассмотрим цифро-буквенный ЖК индикатор с управлением от стандартного контроллера AND671GST с параллельным интерфейсом обмена. Мы также приведем пример программного кода для управления этим индикатором.
5.6.2. Сопряжение МК с символьным ЖК индикатором
AND671GST — однострочный цифро-буквенный дисплей на 16 знакомест. Для управления такими дисплеями используются интегральные схемы контроллеров HD44100H или HD44780. Контроллер с сопутствующими элементами размещается на печатной плате, которая помешается за индикатором и образует с ним единую конструкцию. На плате контроллера смонтирован разъем на 14 контактов. На разъем выведены сигналы стандартизованного параллельного интерфейса для сопряжения символьных ЖК индикаторов с микропроцессорными системами. Назначение сигналов этого интерфейса, имена линий и соответствующие им номера контактов разъема приведены на рис. 5.12,a.
Номер вывода Обозначение Функция 1 GND Общий вывод источника питания 2 VDD Напряжение питания контроллера 5,0 В 3 V0 Напряжение питания ЖК матрицы 4 RS Выбор регистра контроллера: 0 — регистр управления, 1 — регистр данных 5 R/W Выбор режима обмена чтение/запись: 0 — запись, 1 — чтение 6 E Разрешение обмена 7 DB0 Двунаправленная магистраль данных контроллера ЖК индикатора 8 DB1 9 DB2 10 DB3 11 DB4 12 DB5 13 DB6 14 DB7
а) Описание выводов контроллера ЖК индикатора
б) Схема подключения ЖК индикатора к МК
в) Временные диаграммы обмена в режиме записи
Рис. 5.12. Цифро-буквенный ЖК индикатор
Схема подключения индикатора к МК семейства 68HC12 представлена на рис. 5.12,б. Обмен данными в параллельном однобайтовом формате производится через порт PORT P. В нашем примере мы будем только записывать данные в контроллер индикатора, поэтому порт может быть однонаправленным. В реальных задачах иногда приходится читать информацию из памяти контроллера управления дисплеем, тогда следует использовать двунаправленный порт. Для управления режимами обмена информацией с контроллером используются два дополнительных сигнала: E — разрешение обмена, и RS — выбор регистра для обмена. Эти две линии подключены к линиям другого порта вывода МК. Третий сигнал управления обменом — линия выбора направления обмена (чтение или запись) подключена к общему выводу, поскольку в примере мы будем использовать только режим записи.
Три контакта разъема индикатора предназначены для подключения двух источников напряжения: VDD— напряжение питания цифровой части (схемы управления индикатора), VO— напряжение смещения электродов. Последнее называют напряжением управления контрастностью индикатора. Вывод VOподключен к средней точке потенциометра, поэтому напряжение VOможет изменяться от 0 до 5,0 В, обеспечивая таким образом выбор наилучшего режима отображения.
Временные диаграммы обмена. Различают два типа данных, которые может передать МК контроллеру индикатора: команды управления и данные, т.е. коды символов для отображения. В режиме чтения МК может получить от контроллера управления дисплеем слово-состояние и данные из внутреннего ОЗУ символов. В нашем примере мы не будем пользоваться режимом чтения.
Временные диаграммы одного цикла записи в контроллер дисплея приведены на рис. 5.12,в. Приведенные на рисунке длительности временных интервалов определяются конкретным типом выбранного индикатора, поэтому могут достаточно существенно различаться. Об этом следует помнить при использовании ранее написанного и отлаженного программного кода для управления индикатором в последующих разработках. Если очередной индикатор требует больших времен установления по сравнению с предыдущим, то программный код может оказаться неработоспособным.
В соответствии с приведенными временными диаграммами (рис. 5.12,в) должна сгенерировать следующую последовательность сигналов на выходах портов МК:
• Линия RS должна быть установлена в соответствии с типом передаваемых данных: 1 — запись данных, 0 — запись команды;
• С задержкой в 140 нс относительно сигнала RS должна быть установлена в 1 линия разрешения обмена E;
• Длительность импульса на линии E не должна быть менее 450 нс;
• Байт данных должен быть выставлен на линии DB0…DB7 не позднее, чем за 195 нс до спадающего фронта сигнала E. Это время называют временем предустановки данных относительно сигнала разрешения E;
• Данные на линиях DB0…DB7 должны оставаться неизменными в течение не менее 10 нс после перехода сигнала E в неактивное (логический 0) состояние. Это время называют временем сохранения данных относительно сигнала E;
• Период сигнала E не должен быть менее 1000 нс.
Основываясь на требованиях временной диаграммы обмена, следующий алгоритм должен быть реализован микроконтроллером для выполнения одного цикла записи в контроллер дисплея:
1. Установить линию RS в 1 или в 0 (1 — для записи кода символа, 0 — для записи кода команды управления дисплеем);
2. Установить активный уровень на линии разрешения E (логическая 1);
3. Выдать на порт PORT P байт данных (код символа или команда управления);
4. Перевести линию E в неактивное состояние (логический 0).
В процессе создания на основе этого алгоритма программы управления следует учесть все перечисленные ранее задержки между сигналами.
Программа управления ЖК индикатором. Структура программы управления символьным ЖК индикатором представлена на рис. 5.13,а. Программа включает коллекцию функций, каждая из которых выполняет законченное смысловое действие. Разбиение задачи на отдельные функции — искусство разработчика. От выбранного набора функций и способов передачи параметров между ними зависит число возможных ошибок при последующем использовании этих функций в прикладной программе и компактность файла исполняемых кодов.
а) Набор функций управления
б) Блок-схема алгоритма инициализации
Рис. 5.13. Программное обеспечение для управления цифро-буквенным ЖК индикатором
Блок-схема функции инициализации дисплея представлена на рис. 5.13,б. Она реализует алгоритм начальной установки дисплея, который разработан в соответствии с техническими рекомендациями производителя.
Ниже приведен текст программы на Си для всех функций рис. 5.13,а.
/*------------------------------------------------------------------*/
/*filename: lcd.c */
/*содержит программный код для шести функций управления ЖК дисплеем */
/*------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Функция initialize_lcd производит начальную установку режимов дисплея */
/*-----------------------------------------------------------------------*/
void initialize_lcd(void) {
delay_5ms();
delay_5ms();
delay_5ms(); //задержка 15 мс
putcommands(0x38); //команда установки формата интерфейса обмена
delay_5ms();
putcommands(0x38);
delay_l00us();
putcommands(0x38);
putcommands(0x38) ;
putcommands(0x0C);
putcommands(0x01); //очистить дисплей
putcommands(0x06); //установить режим ввода с автоматическим
//увеличением адреса
//символа на 1
putcommands(0x0E); //включить дисплей, режим курсора мигающий
putcommands(0x02); //установить курсор на первое знакоместо
}
/*---------------------------------------------------------------------*/
/* Функция putchars производит запись одного кода символа в контроллер */
/*дисплея */
/*---------------------------------------------------------------------*/
void putchars(unsigned char с) {
DDRP = 0xFF; //установить порт PORT P на вывод
DDRDLC = DDRDLC | 0x0C; //установить разряды 2 и 3 порта PORT DLC на
//вывод
PORTP = с; //Выдать в порт PORT P код символа с
PORTDLC = PORTDLC | 0x08; //установить линию RS в 1
PORTDLC = PORTDLC | 0x04; //установить линию E в 1
PORTDLC = 0; //установить E и RS в 0
delay_5ms(); //задержка 5 мс
}
/*-----------------------------------------------------------------------*/
/*Функция putcommands производит запись одного кода команды в контроллер */
/*дисплея */
/*-----------------------------------------------------------------------*/
void putcommands(unsigned char d) {
DDRP = 0xFF; //установить порт PORT P на вывод
DDRDLC = DDRDLC|0x0C; //установить разряды 2 и 3 порта PORT DLC на
//вывод
PORTDLC = PORTDLC & 0xF7; //установить линию RS в 0
PORTP = d; //Выдать в порт PORT P код команды d
PORTDLC = PORTDLC | 0x04; //установить линию E в 1
PORTDLC = 0; //установить E и RS в 0
delay_5ms(); //задержка 5 мс
}
/*-----------------------------------------------------------------*/
/*Функция lcdprint производит запись строки символов в ОЗУ дисплея */
/*-----------------------------------------------------------------*/
void lcdprint(char *string) {
putcommands(0x02); //команда установки адреса на начало строки
while(*(string) != '\0') //вывести последовательно кода символов
{ //из памяти МК
putchars(*string);
string++;
}
}
/*-------------------------------------------*/
/* Функция delay_5ms формирует задержку 5 мс */
/*-------------------------------------------*/
void delay_5ms(void) {
int i;
for(i=0; i<50; i++) {
delay_l00us();
}
}
/*-----------------------------------------------------*/
/* Функция void delay_100us формирует задержку 100 мкс */
/*Частота системной шины равна 8 МГц */
/*-----------------------------------------------------*/
void delay_100us(void) {
int i;
for(i=0; i<50; i++) {
asm("nop"); //команда nop занимает 2 цикла
}
}
/*-----------------------------------------------------*/
5.6.3 Сопряжение МК с графическим ЖК дисплеем
В этом разделе мы рассмотрим типовой графический ЖК дисплей. Следуя логике предыдущего параграфа, мы сначала обсудим информационную модель графического дисплея, затем изучим электрические характеристики и временные диаграммы обмена встроенного контроллера управления этим дисплеем, в завершении — элементы программы для передачи данных из МК в контроллер дисплея. В конце параграфа мы предложим Вам набор полезных для обслуживания графического дисплея функций. При рассмотрении мы будем использовать конкретную модель дисплея AND1391ST. Однако полученные знания Вы сможете легко применить к другим распространенным моделям дисплеев. В главе 7 мы предложим Вам подробный полностью завершенный пример с графическим дисплеем (разд. 7.).
Информационная модель. AND1391ST — ЖК дисплей с разрешающей способностью экрана 128×128 пикселов. Встроенный контроллер управления обеспечивает работу дисплея как в символьном, так и в графическом режиме отображения. Возможно также сочетание этих двух режимов работы при выводе одной и той же картинки. При использовании символьного режима поле экрана дисплея делится на 16 строк по 16 символов в каждой строке (рис. 5.14). Для отображения каждого символа предоставляется поле знакоместа размером 8×8 точек, как показано на рис. 5.15. В качестве дополнительного может быть использован режим символьного отображения, при котором поле экрана дисплея делится на 16 строк по 21 символу в строке. В этом случае каждое знакоместо будет состоять из 6×8 точек. Размер знакоместа задается уровнем сигнала на входе FS контроллера дисплея. Набор кодов для формирования образа каждого символа (знакогенератор) хранится в постоянной памяти контроллера дисплея.
Рис. 5.14. Информационная модель графического ЖК дисплея в символьном режиме
Контроллер дисплея воспроизводит на экране образы символов, коды которых хранятся в ячейках оперативной памяти контроллера. Каждому знакоместу на экране дисплея поставлена в соответствие ячейка ОЗУ с определенным адресом. В процессе инициализации контроллера дисплея МК записывает адрес начала ОЗУ экрана. На рис. 5.14 этот адрес равен $1000. Все остальные адреса для ячеек символов вычисляются посредством указанных на рис. 5.14 кодов смещения. В процессе инициализации также указывается число символов в строке. В нашем примере мы используем режим отображения с 16 символами в строке. При этом размер знакоместа для символа (8×8) уже выбран на аппаратном уровне: вход FS контроллера присоединен к общему выводу источника питания.
старший полубайт младший полубайт 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 ! " # $ % & ' ( ) * + , - . / 1 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 2 @ A B C D E F G H I J K L M N O 3 P Q R S T U V W X Y Z [ \ ] ^ _ 4 ` a b c d e f g h i j k l m n o 5 p q r s t u v w x y z { | } ~
Рис. 5.15. Таблица кодов символов для графического ЖК дисплея
Схема подключения дисплея AND1391ST к МК семейства 68HC12 представлена на рис. 5.16, а. Наименование и краткое описание выводов контроллера управления дисплеем AND1391ST приведены в таблице рис. 5.16, б.
а) Схема подключения ЖК дисплея к МК
Номер вывода Обозначение Функция 1 FGND Вывод корпуса 2 GND Общий вывод источника питания 3 VDD Напряжение питания контроллера 5.0 В 4 VEE Напряжение питания ЖК матрицы –14 В ± 3 В 5 WR Линия управления «запись» 6 RD Линия управления «чтение» 7 CE Линия управления «разрешение обмена» 8 C/D Выбор режима обмена: 0 — чтение/запись данных, 1 — чтение регистра состояния/запись команды 9 NC Не подсоединен 10 RESET Начальная установка контроллера 11 DB0 Двунаправленная магистраль данных контроллера ЖК индикатора 12 DB1 13 DB2 14 DB3 15 DB4 16 DB5 17 DB6 18 DB7 19 FS Выбор размера символа 20 NC Не подсоединен
б) Описание выводов контроллера графического ЖК дисплея
Рис. 5.16. Сопряжение графического ЖК дисплея с МК
Проанализировав записи в табл. 5.16, б, Вы увидите, что графический дисплей требует для своей работы двуполярного источника питания. Положительное напряжение питания обеспечивает работу контроллера управления, в то время как отрицательное напряжение необходимо для регулирования контрастности получаемого на дисплее изображения.
В нашем примере мы использовали линии портов PORTP и PORTDLC для обмена данными между МК и дисплеем. Двунаправленная магистраль данных контроллера дисплея D[7…0] подключена к линиям PORTP[7…0] двунаправленного порта PORTP (рис. 5.16, а). В отличие от предыдущего примера, обмен данными между МК и контроллером дисплея происходит в двух направлениях. Поэтому в процессе взаимодействия с дисплеем МК многократно перепрограммирует регистр направления передачи DDRP, изменяя режим работы линий порта PORTP (ввод или вывод).
Для управления режимами обмена информацией с контроллером используются четыре дополнительных сигнала, которые формируются МК на линиях PORTDLC[3…0] порта PORTDLC (рис. 5.16, а). Назначение и краткое описание сигналов управления дисплеем приведено в таблице рис. 5.16, б. Там же показаны комбинации управляющих сигналов, которые следует использовать при обмене с дисплеем различными типами данных.
Рис. 5.17. Временные диаграммы обмена контроллера графического ЖК дисплея
Временные диаграммы обмена. Временные диаграммы обмена с контроллером управления графическим ЖК дисплеем приведены на рис. 5.17. Они аналогичны рассмотренным ранее диаграммам обмена с контроллером цифро-буквенного индикатора. Так же, как и в предыдущем случае, мы будем генерировать сигналы управления в соответствие с приведенной временной диаграммой, последовательно переключая линии порта PORTDLC в программе управления дисплеем.
Набор функций управления графическим ЖК дисплеем. Мы предлагаем Вашему вниманию набор функций на Си, которые могут быть использованы в других программах для эффективного управления графическим ЖК дисплеем. Для каждой функции приведено описание и исходный текст программы на Си. На рис. 5.18 показана структура программного обеспечения для управления графическим дисплеем, в которой отражены полный набор функций управления и их взаимосвязь. В одном из самостоятельных заданий к этой главе мы попросим Вас разработать блок-схемы алгоритмов для реализации каждой из перечисленных функций управления.
Рис. 5.18. Структура программного обеспечения графического ЖК дисплея
//---------------------------------------------------------------------
//filename: 2D_LCD.c содержит программный код для 14 функций управления
//графическим ЖК дисплеем
//---------------------------------------------------------------------
//Схема подключения дисплея AND1391ST к МК 68HC12
// PORTDLC[3] C/D
// PORTDLC[2] CE
// PORTDLC[1] RD
// PORTDLC[0] WR
// PORTP[7…0] D[7…0]
// вывод RESET дисплея AND1391ST через резистор 4,7 кОм к источнику питания
// вывод FS дисплея AND1391ST к общему выводу источника питания
// ------------------------------------------------------------------------
// Функция initialize_lcd производит начальную установку режимов
//графического дисплея
// ------------------------------------------------------------------------
void initialize_lcd(void) {
char temp = 0x00;
PORTDLC = 0xFF; //установить 1 на всех выходах порта: запрет всех
//действий с дисплеем
PORTDLC = PORTDLC & 0xEF; //сброс экрана, RESET=0
delay(2000); //задержка 2 мс
PORTDLC = 0x7F; //установить вывод RESET в 1
write(); //установить WR=0
command(0x80); //установить режим работы текстовый
data(0x00); //слово управления
data(0х10); //слово управления
command(0х40); //установить адрес начала текста
data(0х10); // слово управления
data(0x00); // слово управления
command(0х41); // установить область текста: 16 знаков
command(0x94); //выключить дисплей, курсор мигает
command(0хА7); //установить курсор 8×8 точек
data(0x01); // слово управления
data(0х01); // слово управления
command(0х21) ; //установить позицию курсора
}
// ----------------------------------------------------------------------------
// Функция read конфигурирует линии порта PORTP для ввода данных от контроллера
// дисплея.
// ----------------------------------------------------------------------------
void read() {
DDRP = 0х00; //порт PORTP на ввод
}
// ------------------------------------------------------------------------
// Функция Clearscreen производит очистку экрана дисплея посредством записи
//во все ячейки памяти буфера экрана кода символа " "
// ------------------------------------------------------------------------
void Clearscreen() {
int i,j;
Reset_cursor();
// выполнить для каждой строки (i), для каждого знакоместа в строке (j)
for(i=0; i<16; i++) for(j=0; j<16; j++) LCD_char(' ');
Reset_cursor();
}
// -------------------------------------------------------------------------
// Функция newline производит запись во все знакоместа одной код символа " "
// -------------------------------------------------------------------------
void newline() {
int i;
for(i=0; i<16; i++) LCD_char(' ');
}
// ------------------------------------------------------------------------
// Функция LCD_output производит преобразование кодов ASCII строки символов
//в коды табл. рис. 5.15 для отображения на дисплее и передает эту строку в
//ОЗУ буфера экрана дисплея
// ------------------------------------------------------------------------
void LCD_output(char s[]) {
int n = 0;
while (s[n] != '\0') {
LCD_char(s[n]);
++n;
}
}
// --------------------------------------------------------------------
// Функция delay формирует временную задержку длительностью в указанное
//число мкс
// --------------------------------------------------------------------
void delay(int usec) {
int i,j;
for(i=0; i
for(j=0; j < 7; j++) { }
}
}
// ------------------------------------------------------------------
// Функция write конфигурирует линии порта PORTP для вывода данных на
// дисплей
// ------------------------------------------------------------------
void write() {
DDRP = 0xFF; //Порт PORTP на вывод
}
// -------------------------------------------------------------------------
// Функция data производит запись одного символа в ОЗУ данных дисплея. Перед
// обменом с контроллером дисплея контролируется бит состояния, который
// свидетельствует о том, закончил контроллер выполнение предыдущей команды
// управления или нет. Затем на порт PORTP выставляется код символа и
// формируются необходимые сигналы управления
// -------------------------------------------------------------------------
void data(unsigned char n) {
status_wait();
PORTP = n;
PORTDLC = 0xFF;
PORTDLC = PORTDLC & 0xF7; //C/D в 0
PORTDLC = PORTDLC & 0xFE; //WR в 0
PORTDLC = PORTDLC & 0xFB;
enable();
disable();
}
// -------------------------------------------------------------------
// Функция command производит передачу команды управления в контроллер
// дисплея
// -------------------------------------------------------------------
void command(unsigned char n) {
status_wait();
PORTP = n;
PORTDLC = 0xFF;
PORTDLC = PORTDLC & 0xFE;
enable();
disable();
}
5.7. Управление электрическим двигателем