16. Подключаем ЖКИ к МК



Автор: WildCatПодключение ЖКИ к микроконтроллеру в Bascom AVR

Bascom поддерживает два типа жидкокристаллических дисплеев - знакосинтезирующие и графические. В рамках этой главы мы рассмотрим методы работы со знакосинтезирующими индикаторами, как более простыми. Они имеют встроенную таблицу символов, а значит, вам не придется рисовать каждый знак самому.
Большинство дисплеев имеют встроенный контроллер Hitachi HD44780 или совместимый (который стал стандартом де-факто в промышленности). Если вы сомневаетесь, что ваш ЖКИ имеет такой контроллер, то в 95% случаев вы ошибаетесь. Так что если в ваших лапках находится непонятное устройство, присмотритесь к маркировке платы/чипов. Если там есть цифры 44780, то это то, что нужно.

Подробно про протокол вы можете почитать на http://ru.wikipedia.org/wiki/HD44780 и по связанным со статьей ссылкам.
В Bascom есть настройки по умолчанию для подключения ЖКИ. Давайте посмотрим их. Нажмем Options / Compiler / LCD:



К счастью, там уже предустановлен размер индикатора 16*2. Это самый распространенный тип, который может отображать две строки текста по 16 символов в каждой.
ЖКИ на базе HD44780 имеют 8 линий данных, но допускается управление в "экономичном" режиме, используя только 4 старших разряда шины. Это позволяет сэкономить лапки контроллера. Такой четырехбитный режим уже установлен по умолчанию. Естественно, в этом режиме байт передается за два прохода. Поэтому если вам нужно управлять дисплеем максимально быстро (что бывает исключительно редко), вам нужно использовать режим управления по шине данных, 8 бит.

Data mode - режим передачи данных - по умолчанию установлен в Pin. Это значит, что вы можете назначить любые лапки контроллера для управления ЖКИ. Таким образом, вы можете максимально удобно настроить компилятор, иногда это необходимо из-за схемотехнических ограничений. Режим Bus - шина - организует классическое подключение по топологии шины данных, когда много устройств подключены к одной шине, и нужно посылать адрес устройства, чтобы отозвалось только нужное. В этом случае вам нужно выставить значения LCD-address и RS-address.

При подключении Pin вы определяете, какие выводы ЖКИ куда подключены. Пин Enable используется, чтобы ЖКИ знал направление данных (запись/чтение). Пока на выводе Enable низкий уровень, ЖКИ не реагирует на команды на линиях данных, и их можно использовать для других целей. Информация с линий данных считывается, когда на выводе RS находится низкий уровень. Этот вывод используется, чтобы ЖКИ знал, что передается по линиям данных - символ или команда.

У ЖКИ есть еще вывод R/W, используя который, можно сообщить дисплею, собираемся ли мы считать с него данные, или записать их в него. Bascom предполагает, что на этом выводе всегда низкий уровень, так что индикатор всегда в режиме приема данных. Однако, чтобы проверить, готов ли он принимать данные, нужно считать флаг занятости "Busy". Для этого нужно было бы отправить команду проверки, переключить индикатор в режим передачи данных и считать состояние флага. Но поскольку мы не можем этого сделать, Bascom выжидает некое количество циклов после каждой передачи данных. Их количество определяется тактовой частотой процессора. Это еще одна причина, по которой нужно грамотно указывать частоту установленного кварцевого резонатора с помощью директивы $crystal.

Как и в случае с типом контроллера и частотой кварца, все настройки портов для ЖКИ также можно делать прямо в коде:

Config lcd = 16*2
Config lcdpin = PIN, DB4 = PORTB.1,DB5=PORTB.2,DB6=PORTB.3,DB7=PORTB.4,E=PORTB.5,RS=PORTB.6
Config lcdmode = PORT
ЖКИ подключен к контроллеру по такой схеме:



У стандартного знакосинтезирующего индикатора 14 выводов. Вывод 1 - земля. Вывод 5 - R/W - также подключен к земле. Вывод 2 - напряжение питания, подключен к +5 вольт. Некоторые ЖКИ не будут работать с источниками питания, у которых выходное напряжение поднимается медленно. Это обычно описывается в даташите.
Вывод 3 - регулировка контрастности. По идее, его достаточно подключить просто к земле. Но в большинстве случаев дисплей просто станет темным и будет невозможным разобрать хоть что-то. Поэтому подключать вывод регулировки нужно через резистор до 10 кОм. Мне, как правило, хватало несколько сот ом.
Выводы 4, 6, 11-14 подключены к контроллеру согласно схеме. Выводы 7-10 не подключены.
Если вам достался ЖКИ с подсветкой, то вначале контактной гребенки будут выводы 15 и 16 для подключения её питания. Питать её можно от того же источника, что и сам ЖКИ, но иногда требуется ограничительный резисто в несколько сот ом. Иногда выводы подсветки не выведены на общую шину, тогда они находятся непосредственно справа или слева от ЖК матрицы.

Накатаем первую программу для работы с ЖКИ:
lcd.bas
$regfile = "2313def.dat"
$crystal = 4000000
$sim

Dim Count as Integer
Count = 0

Do
  Cls
  Lcd "Hello! " ; Count
  Count = Count + 1
  Wait 1
Loop
End
Скомпилируем программу, но на этот раз не будем прошивать чип, а запустим симулятор (о нём читаем в отдельной главе).
Щелкнем на первой ячейке в таблице переменных и введем "Count". Затем щелкнем на кнопке "LCD", чтобы посмотреть эмуляцию аппаратной обвязки. Щелкнем на "Step into Code" (F8), чтобы перемещаться по строкам. После строки "Lcd "Hello! " ; Count", на экране появится следующее:



Нажмем кнопку "Run" (F5) и посмотрим на ЖКИ.
Команда Cls в цикле инициализирует и очищает дисплей. Инициализация очень важна, поэтому всегда ставьте эту команду перед началом работы с индикатором, иначе вы можете получить доступ только к первой строке двухстрочного индикатора. Также, при сбросе контроллера не происходит сброса ЖКИ, что тоже не даст нормально работать.
Теперь обкатаем программу в бою. Удаляем из кода директиву $sim, заново компилируем и загружаем прошивку в чип.

Знакогенератор в ЖКИ

Стандартный набор символов ЖКИ с поддержкой кириллицы выглядит так:



Нестандартные символы из набора можно выводить на индикатор, указывая их десятичный код:
Lcd Chr(253)
'Выводим символ параграфа (0xFDh в десятичной системе будет 253)
Управление курсором

В Bascom есть несколько команд для управления курсором. Вы можете включать/выключать его, а также использовать мигание:
Cursor on, blink
Cursor on, noblink
Cursor off
Также можно указать точное положение курсора:
Locate linenumber, characternumber
Locate 1, 6
Lcd "Count"
Этот код переместит курсор на шестое знакоместо первой строки. Слово "Count" будет выведено начиная с этой позиции.
Команда Home поместит курсор в начальное положение - первый символ первой строки, т.е. Home делает то же, что и Locate 1, 1. Home upper делает то же самое. Но вот Home lower делает то же, что и Locate 2, 1, т.е. помещает курсор в начало самой нижней строки (второй в случае с двухстрочным дисплеем).
Shiftcursor left/right будет двигать курсор влево или вправо на одно знакоместо относительно текущего положения.
Shiftlcs left/right будет аналогично сдвигать всё содержимое на дисплее.
Рассмотрим это на примере (в симуляторе, если хотите опробовать на настоящем железе, уберите директиву $sim):
shifttext.bas
$regfile = "2313def.dat"
$crystal = 4000000
$sim

Dim Pos As Byte

Do

Cls
Upperline
Lcd "012345678901john"
Lowerline
Lcd "0123456789012ike"
For Pos = 0 To 16 Step 1
  Waitms 500
  Shiftlcd Left
Next Pos

Loop
End
Когда вы запустите эту программу, вы увидите, что текст на обеих линиях сдвигается влево. Было бы замечательно, если бы Bascom умел еще и сдвигать текст вверх/вниз со строки на строку.

Создаем собственные символы

Контроллеры HD44780 имеют дополнительное место для 8 собственных символов. Вы можете использовать это, чтобы:

- сделать индикатор уровня сигнала
- дурацкую анимацию, показывающую, что контроллер занят рассчетами или чем-то еще
- крутящуюся штуковину или танцующего человечка, чтобы показать, что контроллер все еще работает, или развлекать пользователя

Вы можете создавать собственные символы в Bascom, используя специальный редактор (Tools / LCD Designer).
Наберем (на этот раз ручками или копипастом) такую вот программку:
$regfile = "2313def.dat"
$crystal = 4000000
$sim
Config Portd = Output
Dim Star As Byte

Cursor Off








Cls

Do
  For Star = 0 To 5 Step 1
    Portd = 255
    Waitms 100
    Portd = 0
    Waitms 100
    Locate 1 , 16
    Lcd Chr(star)
  Next Star
Loop

End
Поместим курсор на вторую пустую строку после слов "Cursor Off". Нажмем Tools / LCD Designer:



Щелкнем на маленьком белом квадратике, и он станет черным. Щелкнем снова - и он побелеет. Нарисуем таким образом крестик:



Нажмем "OK". На том месте, где мы предусмотрительно оставили курсор, появится такая строка:
Deflcdchar ?,32,4,4,31,4,4,32,32' replace ? with number (0-7) 
Заменим "?" на цифру "0" и удалим комментарий:
Deflcdchar 0,32,4,4,31,4,4,32,32
Поместим курсор на следующую свободную строку и повторим все действия, нарисовав на этот раз такую загогулину:



Снова нажмем "OK", снова появится строка:
Deflcdchar ?,32,4,4,31,4,4,32,32' replace ? with number (0-7)
Делаем все то же самое, только заменяем на этот раз вопросик цифрой "1":
Deflcdchar 1,32,4,4,31,4,4,32,32
Повторим этот процесс еще четыре раза (нужно поднапрячь воображение), пока не получим примерно такую программу:
star.bas
$regfile = "2313def.dat"
$crystal = 4000000
$sim
Config Portd = Output
Dim Star As Byte

Cursor Off

Deflcdchar 0 , 32 , 4 , 4 , 31 , 4 , 4 , 32 , 32
Deflcdchar 1 , 32 , 2 , 20 , 14 , 5 , 8 , 32 , 32
Deflcdchar 2 , 32 , 2 , 26 , 4 , 11 , 8 , 32 , 32
Deflcdchar 3 , 32 , 17 , 10 , 4 , 10 , 17 , 32 , 32
Deflcdchar 4 , 32 , 8 , 11 , 4 , 26 , 2 , 32 , 32
Deflcdchar 5 , 32 , 8 , 5 , 14 , 20 , 2 , 32 , 32

Cls

Do
  For Star = 0 To 5 Step 1
    Portd = 255
    Waitms 100
    Portd = 0
    Waitms 100
    Locate 1 , 16
    Lcd Chr(star)
  Next Star
Loop

End
Скомпилируем и засимулируем. На выходе получаем шусто вращающуюся звездочку на последнем знакоместе первой строки:



Как вариант, можно сделать прыгающего человечка только из двух кадров:
(jman.bas)



Или индикатор уровня:
(mbar.bas)



Форматирование вывода на ЖКИ

Представим, что у нас есть некая целочисленная переменная loglevel, которая меняет значения от -90 до +10 (типа регулятор громкости в усилителе). То, как она будет выведена на ЖКИ, зависит от её значения:
Loglevel = -2
Lcd Loglevel

Loglevel = 34
Lcd Loglevel

Loglevel = 7
Lcd Loglevel


Как мы видим, все обстоит ужасно: в зависимости от значения, меняется положение цифр. Для меняющегося значения это делает чтение затрудненным. Разумное решение - зарезервировать определенное число знакомест под вывод и выравнивать значение по краю. Для этого пригодится уже знакомая нам команда Format:
lcdformat.bas
$regfile = "2313def.dat"
$crystal = 4000000
$sim
Dim Loglevel As Integer
Dim Loglevelstr As String * 5
Dim Loglevelstrformat As String * 5

Cls

Loglevel = -2
Loglevelstr = Str(loglevel)
Loglevelstrformat = Format(loglevelstr , "+00")
Lcd Loglevelstrformat ; " dBm"

End
В результате мы получим вот такой равномерный удобоваримый вывод, который не стыдно показать людям:




При использовании примеров из этой главы не забывайте, что в коде прописана директива $sim. Если вы хотите испытывать код на реальном контроллере и ЖКИ, не забывайте убирать её перед компиляцией!

Кириллица в HD44780

Одна из главных проблем, с который могут столкнуться русскоязычные пользователи - нестандартная кодировка кириллических символов. То есть если вы отправите в ЖКИ обычную строку с русскими символами, вместо них на экран будут выведены абраказябры. Связано это с тем, что для экономии места в памяти контроллера тупоголовые разработчики вместо увеличения объема (можно было просто занять свободные ячейки) решили оставить лишь по одной ячейке для символов со сходным начертанием. Так например, буква O или P выглядят одинаково как в кириллице, так и латинице. Неумные инженеры подумали, что так они неистово сократят объем используемой памяти, но сократили лишь функциональность дисплея. И теперь при необходимости вывести русские символы, каждый раз возникает неприятная неприятность в виде несовместимости таблиц HD44780 и ASCII. Выхода есть два, у обоих свои плюсы и минусы:

1. Написать подпрограмму для контроллера, которая на лету будет декодировать ASCII коды и выводить уже правильные символы на ЖКИ. Удобна тем, что позволяет передавать любые строки без опасения, что они будут выведены впоследствии неправильно. Но этот способ требует лишних ресурсов на перекодировку, а также нужно постоянно хранить в памяти таблицу символов.
2. Использовать утилиту для ПК, которая сама переконвертирует нужные строки в нужный формат, которые сразу подставляются в код для вывода. Удобно тем, что не занимает память контроллера, работает быстро и вообще не требует ресурсов для перекодировки. Но минус в том, что в коде программы нужные строки уже не разобрать. Вывод символов в этом фиксированный, то есть выводить можно только заранее выбранный набор строк. При использовании ввода, например, с RS-232, русские символы будут отображены некорректно.

О наличии подпрограмм для первого случая мне известно, но я не встречал ни одной библиотеки или функции на Basom, которая бы выполняла это. Если вы встречали что-то подобное, убедительная просьба прислать это мне.

Для второго случая есть множество программ. Я не поленился и тоже создал одну. Она автоматически заменяет все русские символы в текстовом файле на их аналоги для HD44780. Скачать программу + исходники (78 КБ).



DECADALAB ALFA