Работа с символьным жидкокристаллическим индикатором

Методическое указание к лабораторной работе на учебном стенде LESO1.

1 Цель работы

  1. Изучить схему подключения жидкокристаллического индикатора (ЖКИ) к микроконтроллеру.
  2. Изучить особенности работы символьного ЖКИ.
  3. Изучить особенность параллельной синхронной передачи данных.
  4. Научится выводить на ЖКИ информацию.

2 Предварительная подготовка к работе

  1. По конспекту лекций и рекомендуемой литературе изучить принцип работы символьного жидкокристаллического индикатора.
  2. По конспекту лекций и рекомендуемой литературе изучить принцип работы параллельных портов ввода-вывода микроконтроллера.
  3. Составить алгоритм работы программы, соответственно заданию.
  4. Составить программу на языке программирования С.

3 Краткие теоретические сведения

3.1 Устройство и принцип работы символьного жидкокристаллического индикатора

В настоящее время в микропроцессорных системах для отображения широко используют жидкокристаллические индикаторы (ЖКИ). Условно все ЖКИ можно разделить на две категории: символьные, или знакосинтезирующие, и графические. Графические индикаторы представляют собой матрицу из m строк и n столбцов, на пересечении которых находятся пиксели. Пиксель представляет собой неделимый объект прямоугольной или круглой формы, обладающий определённым цветом; пиксель – наименьшая единица растрового изображения. Если на определенный столбец и строку подать электрический сигнал, то пиксель на их пересечении изменит свой цвет. Подавая группу сигналов на столбцы и строки можно формировать по точкам произвольное графическое изображение. Так работает графический ЖКИ. В символьном же ЖКИ матрица пикселей разбита на подматрицы, каждая подматрица предназначена для формирования одного символа: цифры, буквы или знака препинания. Как правило, для формирования одного символа используют матрицу из восьми строк и пяти столбцов. Символьные индикаторы бывают одно-, двух- и четырехстрочными.

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

Внешний вид жидкокристаллического индикатора 21,6 КБ
Рисунок 1 – Внешний вид жидкокристаллического индикатора

В учебном стенде LESO1 использован двухстрочный восьмисимвольный ЖКИ. Структурная схема показана на рисунке 2.

Структурная схема ЖКИ 12,6 КБ
Рисунок 2 – Структурная схема ЖКИ

В состав контроллера ЖКИ входят три вида памяти: CGROM, CGRAM, DDRAM. Когда микроконтроллер передает в контроллер ЖКИ ASCII-коды символов, то они записываются в DDRAM (Display data RAM – ОЗУ ASCII-кодов отображаемых символов), такую память называют видеопамятью или видеобуфером. Видеобуфер в символьных индикаторах обычно содержит 80 ячеек памяти – больше, чем число знакомест дисплея. У двухстрочных индикаторов ячейки с адресами от 0x00 и до 0x27 отображаются на верхней строке дисплея, а ячейки с адресами 0x40 … 0x67 – на нижней строке. Смещая видимое окно дисплея относительно DDRAM, можно отображать на дисплее различные области видеопамяти. Сдвиг окна индикатора относительно видеобуфера для верхней и нижней строк происходит синхронно, как это показано на рисунке 3. Курсор будет виден на индикаторе только в том случае, если он попал в зону видимости дисплея (и если предварительно была подана команда отображать курсор).

Отображение символов из видеобуфера 7,6 КБ
Рисунок 3 – Отображение символов из видеобуфера

Матрицы начертания символов хранятся в памяти знакогенератора. Память знакогенератора включает в себя CGROM (Character generator ROM – ПЗУ знакогенератора), в которую на заводе-изготовителе загружены начертания символов таблицы ASCII. Содержимое CGROM изменить нельзя. Для того, чтобы пользователь смог самостоятельно задать начертание нужных ему символов, в знакогенераторе имеется специальное ОЗУ – CGRAM (Character generator RAM). Под ячейки CGRAM отведены первые (младшие) 16 адресов таблицы кодов.

Схема подключения ЖКИ к микроконтроллеру ADuC842 показана ниже на рисунке:

Схема подключения ЖКИ к микроконтроллеру 9,6 КБ
Рисунок 4 – Схема подключения ЖКИ к микроконтроллеру

Интерфейс подключения – параллельный. Для соединения индикатора с микроконтроллером используется 11 линий — восемь для передачи данных (D0 - D7) и три линии управления. Линия RS служит для сообщения контроллеру индикатора о том, что именно передается по шине: команда или данные (RS = 1 — данные, RS = 0 — команда). По линии Е передается строб-сигнал, сопровождающий запись или чтение данных: по переходу сигнала на линии E из 1 в 0 осуществляется запись данных во входной буфер микроконтроллера индикатора. Запись информации в ЖКИ происходит по спаду этого сигнала. Потенциал на управляющем выводе R/W (Read/Write) задает направление передачи информации, при R/W = 0 осуществляется запись в память индикатора, при R/W = 1 – чтение из нее. Еще три линии предназначены для подачи питающего напряжения (VDD, GND) и напряжения смещения, которое управляет контрастностью дисплея.

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

Диаграмма передачи информации контроллеру ЖКИ 8,7 КБ
Рисунок 5 – Диаграмма передачи информации контроллеру ЖКИ

 

Диаграмма чтения информации из контроллера ЖКИ 8,8 КБ
Рисунок 6 – Диаграмма чтения информации из контроллера ЖКИ

В таблице 1 приведены команды контроллера ЖКИ и время, необходимое для выполнения этих команд. Для того чтобы можно было определить, когда ЖКИ закончит свои внутренние операции, контроллер ЖКИ содержит специальный флаг занятости – BUSY-флаг (BF). Если контроллер занят выполнением внутренних операций, то BF установлен (BF = 1), если же контроллер готов принять следующую команду, то BF сброшен (BF = 0). Более простой способ организации обмена заключается в том, что управляющий микроконтроллер, зная, сколько времени требуется ЖКИ на обработку той или иной команды, после каждой передачи информации ждет соответствующее время.

Таблица 1 – Команды контроллера ЖКИ

Команда Код Описание Время исполнения команды
RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Очистка дисплея 0 0 0 0 0 0 0 0 0 1 Записывает код 0x20 (пробел) во все ячейки DDRAM, устанавливает счетчик адреса DDRAM в 0x00. 1,5 мс
Возврат в начальную позицию 0 0 0 0 0 0 0 0 1 х Устанавливает счетчик адреса DDRAM в 0x00 и возвращает курсор в начальную позицию. Содержимое DDRAM не изменяется. 1,5 мс
Режим ввода 0 0 0 0 0 0 0 1 L/R SH Задает направление перемещения курсора (L/R) и разрешает сдвиг сразу всех символов (SH). 38 мс
Включение-выключение дисплея 0 0 0 0 0 0 1 D C B Устанавливает/ отключает биты, отвечающие за включения дисплея (D), отображение курсора (C), мерцание курсора (B). 38 мкс
Сдвиг курсора или видимой области дисплея 0 0 0 0 0 1 D/C R/L x x Бит D/C определяет то, что будет перемещаться – видимая область дисплея или курсор (при D/C = 1 перемещается видимая область, при D/C = 0 – курсор), R/L задает направление перемещения. DDRAM не изменяется 38 мкс
Начальные установки 0 0 0 0 1 DL N F x x Определяет разрядность шины интерфейса (DL = 1 8-бит, DL = 0 4-бита), количества строк на дисплее (N = 1 – две строки, N = 0 – одна строка) и размера символов (F = 1 – 5×11 точек, F = 0 5×8 точек). 38 мкс
Установка адреса CGRAM 0 0 0 1 A5 A4 A3 A2 A1 A0 Установка счетчика адреса CGRAM 38 мкс
Установка адреса DDRAM 0 0 1 A6 A5 A4 A3 A2 A1 A0 Установка счетчика адреса DDRAM 38 мкс
Чтение BF и счетчика адреса 0 1 BF A6 A5 A4 A3 A2 A1 A0 Если BF = 1 то контроллер ЖКИ выполняет внутреннюю операцию. А6 - А0 – текущее значение адреса DDRAM. 0
Запись данных в RAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 Запись данных в ОЗУ (DDRAM или CGRAM) 38 мкс
Чтение данных из RAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 Чтение данных из ОЗУ (DDRAM или CGRAM) 38 мкс

Перед началом работы требуется произвести инициализацию ЖКИ согласно алгоритму, показанному на рисунке 7.

Алгоритм инициализации ЖКИ 25,3 КБ
Рисунок 7 – Алгоритм инициализации ЖКИ

 

Таблица символов знакогенератора 100 КБ
Рисунок 8 – Таблица символов знакогенератора

3.2 Рекомендации по программному управлению ЖКИ

Программу для работы с ЖКИ следует организовать в виде функций, выполняющих определенные действия, причем более сложные функции могут включать в себя простейшие. Простейшими могут быть такие подпрограммы, как функция, отправляющая команду контроллеру дисплея; функция, устанавливающая счетчик адреса; или функция, записывающая данные в DDRAM. В любом случае, общий алгоритм передачи информации контроллеру не изменится. Руководствуясь диаграммой передачи информации (рисунок 5), определим последовательность действий при передаче информации в ЖКИ следующим образом: устанавливаем требуемое значение RS, на линию R/W подаем логический ноль, затем на линию E выводим логическую единицу, после чего подаем на шину D значение передаваемого байта. Контроллер ЖКИ считает этот байт и состояние управляющих линий (RS, R/W) только после подачи на линию E логического ноля. При этом, если временные задержки, указные на диаграмме, меньше длительности машинного цикла, то ими можно пренебречь. Код программы, реализующей запись в память ЖКИ байта данных, показан ниже:

RS = 1;        // выбираем команды или данные
RW = 0;        // выбираем направление передачи
E = 1;
Data = symbol; // выводим байт данных на шину D
E = 0;         // переводим сигнал на линии E из 1 в 0
delay ();      /* ждем, пока контроллер выполняет внутренние операции*/

В приведенном участке программы подразумевается, что переменные RS, RW и E объявлены как sbit, а переменная Data – как sfr. Аналогично будет происходить передача любой команды контроллеру ЖКИ.

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

Для того, чтобы не загромождать основную программу алгоритм инициализации (рисунок 7) можно реализовать в виде отдельной подпрограммы. Временные задержки, указанные в алгоритме, следует задавать с помощью таймеров, как это делалось в лабораторной работе «Изучение таймеров микроконтроллера».

4 Задание к работе в лаборатории

SFR параллельных портов
SFR таймеров
SFR UART

4.1 Вывод символа на ЖКИ

  1. Разработайте алгоритм программы, выводящей на экран ЖКИ ваше имя в заданной строке. Режим работы ЖКИ и номер строки определяется согласно варианту задания (таблица 2).
  2. По принципиальной схеме учебного стенда LESO1 определите, к каким выводам микроконтроллера ADuC842 подключен ЖКИ. По таблице SFR определите адреса используемых портов ввода-вывода.
  3. Разработайте и введите текст программы в соответствии с созданным алгоритмом.
  4. Оттранслируйте программу, и исправьте синтаксические ошибки.
  5. Загрузите полученный *.hex файл в лабораторный стенд LESO1.
  6. Убедитесь, что на экране дисплея в заданной позиции появился требуемый символ.

4.2 Управление ЖКИ через последовательный порт персонального компьютера (дополнительно)

  1. Измените программу таким образом, что бы на экране ЖКИ выводилась информация, переданная с персонального компьютера через UART. Передача команды осуществляется через терминал nwFlash. Выбор источника синхронизации и скорости передачи данных осуществляется по усмотрению студента.
  2. Загрузите полученный *.hex файл в лабораторный стенд LESO1.
  3. Через терминал nwFlash передайте коды символов, убедитесь, что соответствующие символы выводятся на экране индикатора.

Таблица 2 – Варианты заданий

номер варианта номер строки режим курсора
1 первая выключен
2 вторая включен, мерцает
3 первая включен, не мерцает
4 вторая выключен
5 первая включен, мерцает
6 вторая включен, не мерцает
7 первая выключен
8 вторая включен, мерцает
9 первая включен, не мерцает
10 вторая выключен
11 первая включен, мерцает
12 вторая включен, не мерцает
13 первая выключен
14 вторая включен, мерцает
15 первая включен, не мерцает

5 Указания к составлению отчета

Отчет должен содержать:

  1. Цель работы.
  2. Принципиальную схему подключения ЖКИ к управляющему микроконтроллер.
  3. Структурную схему ЖКИ.
  4. Диаграммы передачи данных по параллельному интерфейсу.
  5. Расчет параметров таймера.
  6. Графическую схему алгоритма работы программы.
  7. Исходный текст программы.
  8. Содержимое файла листинга программного проекта.
  9. Выводы по выполненной лабораторной работе.

Схемы, а также отчет в целом, выполняются согласно нормам ЕСКД.

Комментарии:



Аватар пользователя XXX

Столкнулся с однйо проблемой что значения из массива не читаются.

Не буду копировать весь код приведу не большой отрывок:

int AA[5] = {1,0,0,0,1}; // Массив пикселей.
int S = 0; 
intilization();  // Инцилизация дисплея
cmd(0x01);   // отчистка дисплея
S = S + AA[0];  // 0 + 1 = 1
cmd(0x40);  // Установка адреса CGRAM
symbol(512+S); // Прибавляем биты 10 000
cmd(0x80);     // Установка адреса на 1 ячейку
symbol(0x00); // Вывод символа 
while(1);
по идее все правильно и должен загореться 1 пиксель на дисплее так как AA[0] = 1; 
но этого почему то не происходит. 
Если же вместо S = S + AA[0]; поставить просто то есть S = S + 1;  то все работает и пиксел загорается.
Прикрепленные файлы: 

Сразу бросается в глаза: функция symbol принимает на вход переменную типа char (если смотреть на реализацию в приложенном файле), а на вход при вызове подаете значение превышающее диапазон char.  Что за константа 512 и зачем она нужна?

Аватар пользователя XXX

Если изменить тип данных на int то особой разницы я не заметил. Функция symbol(512 + 1) работает без проблем. Еще одна маленькая странность. Константа 512 это есть 10 000 00000 то есть "Запись данных в RAM" к которой мы прибавляем 1 и получаем "10 000 00001"и закрашиваем 1 пиксель. А это самое "1" я не могу почему то взять из массива AA[0].  то есть вариант symbol(512+AA[0]); не хочет работать. Работает только если symbol(512+1);

Вы что пытаетесь сделать? Вывести символ из стандартной таблицы или определить новый символ?

1. Функция symbol ожидает переменную типа char, это восемь бит. Значение 512+1 -- это уже 9 значащих бит. Компилятор неявням образом производит преобразования типов, и следовательно, отбрасывает старшие биты у аргумента. В функцию попадает не 513d (1000000001b), как вы ожидали, а 1d (00000001b), а это просто запись в память RAM . Все таки, зачем вам эти 512?

2.  В подцепе библиотека работы с этим LCD и файл с примером использования. В примере задется символ градуса для вывода температуры. Правда, писалось это для leso6, а там стоит AVR микроконтроллер.

Прикрепленные файлы: 
Аватар пользователя XXX

Я пытаюсь нарисовать свой символ, но сталкиваюсь  с проблемой, что значения из массива не читаются или не передаются в функцию. Например: 

int AA[1] = {0x15};
symbol(AA[0]);

на экран ничего не выводится. А если в функцию написать просто symbol(0x15); то закрашиваются нужные пиксели (10101). Что я делаю не так? 

  1. 512 - это моя не внимательность :). Не заметил что первые 2 бита в таблице это есть RS и R/W. (1.0.D7.D6.D5.D4.D3.D2.D1.D0) поэтому и показалось чтьо нужно отправлять 10 бит
  2. Капчу ввожу раза с 20.

Массив следует объявить того же типа, что и входной параметр функции , а именно:

char AA[1] = {0x15};

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

А если не через массив передать значение, а через переменную? Тоже не работает?

P.S.: что бы не вводить капчу, лучше один раз зарегистрироваться. Капчи не будет и коменты появляются сразу, а не ждут одобрения.

Аватар пользователя XXX

Вообще изначально мне нужно было создать char массив[16][20]; Но столкнулся с проблемой что в Kell появилась ошибка "TEXT1.C(77): error C241: 'main': auto segment too large" . Я подумал.."Странно.. вроде же есть 62кб памяти." Немного по искав в интернете и немного методом "тыка" в настройках во вкладке Target в поле Memory Model изменил с Small: variables in DATA на Large: variables in XDATA. Вроде бы стало компилироваться. Но именно в этом режиме как раз не были видны значения массива. Например:

char a[1] = {0x15};

symbol(a[0]);

Далее еще покапавшись в интернете и глянув код DEMO прошивки увидел что некоторые переменные можно объявлять как char xdata. Вернув значение Memory Model на исходное и попытавшись обявить переменную как char xdata ничего собственно не изменилось. Значение из массива так же не были видны. Хотя такая запись как 

int xdata s = 0x15;

symbol(s);

спокойно работает и функция выводит 3 точки.

как мне создать этот гребаный массив 16х20....

 

Прикрепленные файлы: 

Блин, у меня железяки под рукой нет. А так, весьма заинтригован.

Ну что вы хотите от старичка Адука? У него только 256 байта general-purpose RAM (далее просто RAM), причем, нельзя что бы объект занимал разом более 128 байт, так как эта память состоит из двух сегментов по 128 б. Остается только "2 kBytes of internal XRAM". Но это особая память и в первую очередь она предназначена для работы с АЦП в режиме DMA. Но с ней можно работать и как с основной. По умолчанию у 8052 переменные хранятся в RAM (адреса с 00h - FFh), но возможно перенаправить стек в XRAM, но для этого в регистре CFG842 нужно установить 7-ой бит. Почитайте даташиту на ADUC842, страница 27, 28 и 44.

Жду продолжения!

P.S.: Может пора зарегистрироваться?

Ну а как же FLASH-ЭРПЗУ на 62КБ. ? Я не понимаю они есть или их нету? По даташиту трудно что то понять. Еще нашел книгу именно по серии 8051 https://yadi.sk/i/KtR4S8lm3RuD9Q Там вроде даже есть пример с использованием переменной XDATA. Но не с массивом. Одно значение переменной работает и у меня.

FLASH -- это память программа. В 8052 используется гарвардская архитктура. Память программ и память данных разделены. Попробуйте поиграться с регистром CFG842. Может получится.

Еще полезно посмотреть Разработка программной части осциллографа-приставки

Ну а тогда 4 Кб встроенной памяти данных, которые там имеются, как использовать?

Просто с помощью модификатора поместить туда переменную при объявлении не получится. Есть специальная процедура записи и чтения в эту память. Подробнее на странице 42 (и далее) даташиты на ADUC842. Это немножко не просто и если вы не знаете, зачем вам это нужно, то скорее всего вам это не нужно. Если будете разбираться, то я вам помогу.

Эксперименты с регистром CFG842 ник чему не привели? 

Орфографическая ошибка в тексте:
Чтобы сообщить об ошибке автору, нажмите кнопку "Отправить сообщение об ошибке". Вы также можете отправить свой комментарий.