logo
HCS12 с применением языка С - royallib

5.6.2. Сопряжение мк с символьным жк индикатором

AND671GST — однострочный цифро-буквенный дисплей на 16 знакомест. Для управления такими дисплеями используются интегральные схемы контроллеров HD44100H или HD44780. Контроллер с сопутствующими элементами размещается на печатной плате, которая помешается за индикатором и образует с ним единую конструкцию. На плате контроллера смонтирован разъем на 14 контактов. На разъем выведены сигналы стандартизованного параллельного интерфейса для сопряжения символьных ЖК индикаторов с микропроцессорными системами. Назначение сигналов этого интерфейса, имена линий и соответствующие им номера контактов разъема приведены на рис. 5.12,a.

а) Описание выводов контроллера ЖК индикатора

б) Схема подключения ЖК индикатора к МК

в) Временные диаграммы обмена в режиме записи

Рис. 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 цикла

 }

}

/*-----------------------------------------------------*/