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

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 контроллера присоединен к общему выводу источника питания.

Рис. 5.15. Таблица кодов символов для графического ЖК дисплея

Схема подключения дисплея AND1391ST к МК семейства 68HC12 представлена на рис. 5.16, а. Наименование и краткое описание выводов контроллера управления дисплеем AND1391ST приведены в таблице рис. 5.16, б.

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

б) Описание выводов контроллера графического ЖК дисплея

Рис. 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<usec; 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();

}