В данной статье приведены примеры программной реализации обмена данными микроконтроллера PIC16F628A с HD44780, KS0066 -совместимым знакосинтезирующим ЖКИ (для схемы из статьи "Подключение знакосинтезирующего ЖКИ к контроллеру (PIC16F628A)".
Приведенные примеры предполагают использование ЖКИ 16х2 и четырехбитного интерфейса. Кроме этого, в статье приводятся примеры программирования собственного символа в CGRAM и вывода его на ЖКИ (пример работы с пользовательским набором символов).
Поскольку в данных примерах мы будем пользоваться четырехбитным интерфейсом, то линии DB0…DB3 (RA6, RA2, RB7, RB3) — не используются (смело можете их отпаять и занять освободившиеся ножки контроллера чем-нибудь другим).
Как прошить в CGRAM пользовательский символ? Да очень просто. Разберемся — как устроена CGRAM:
Каждый символ 5х8 занимает в памяти CGRAM восемь байт (по одному байту на строку). Младшие 5 бит каждого байта определяют какие из пяти точек строки должны гореть, а какие нет. Старшие три бита — не используются.
CGRAM имеет размер 64 байта, поэтому для ее адресации используются шесть младших бит адреса (26=64). Три младших бита (из используемых) адресуют номер строки для текущего символа, а три старших бита (из используемых) адресуют номер символа знакогенератора. Взгляните на рисунок слева и вам все станет ясно.
Внимание! В родной документации на KS0066U допущены ошибки: 1) почему-то биты, указывающие номер символа всегда равны нулю; 2) не верно описана команда function set в примерах инициализации. В доке на HD44780 все нормально.
Как узнать, что контроллер ЖКИ освободился? Нужно просто выставить на линии RS низкий уровень (RS=0), на линии R/W высокий (R/W=1), тогда при включении передачи (E=1) контроллер ЖКИ выставит на линии DB7 свое состояние (если используется четырехбитный интерфейс, то только в старшем принятом полубайте). Если DB7=1, то ЖКИ занят (BUSY), если DB7=0, то ЖКИ свободен и готов к приему следующей посылки.
Следует учитывать, что проверка начинает работать не сразу, а после нескольких команд инициализации (у всех по разному), поэтому во время инициализации лучше не проверять состояние контроллера ЖКИ, а просто ждать положенное на выполнение команды время.
Подключение линий ЖКИ к портам контроллера:
E-RA0, RS-RA1, R/W-RA7, DB7-RB4, DB6-RB5, DB5-RB2, DB4-RB6
Передача данных по четырехбитному интерфейсу работает следующим образом: сначала передается старший полубайт сообщения, а затем младший (чтение аналогично). Например, если вы хотите записать в DDRAM байт 0011 0101, то это будет выглядеть так:
movlw .3 ; .3=0011 - старший полубайт movwf M_byte ; записываем это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7..DB4 в соответствии ; со значениями, записанными в M_byte bsf PortA, 1 ; RS=1 bcf PortA, 7 ; R/W=0 call zapis ; процедура, которая на 2 мкс выставляет "1" на линии E movlw .5 ; .5=0101 - младший полубайт movwf M_byte ; записываем это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7..DB4 в соответствии ; со значениями, записанными в M_byte call zapis ; еще раз устанавливать уровни на линиях RS и R/W ; нет необходимости, они не изменились (RS=0, R/W=0) |
Единственное исключение — первая команда инициализации (FUNCTION SET). Для четырехбитного интерфейса при передаче первой команды инициализации надо сначала два раза передать старший полубайт, а потом младший полубайт. Например для инициализации четырехбитного интерфейса, двухстрочного ЖКИ, размер символа 5х8 (00101000):
movlw .2 ; DB7...DB4= 0010 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7..DB4 в соответствии ; со значениями, записанными в M_byte bcf PortA, 1 ; RS=0 bcf PortA, 7 ; RW=0 call zapis ; передача в ЖКИ call zapis ; передаем старший полубайт второй раз movlw .8 ; DB7...DB4=1000 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7..DB4 в соответствии ; со значениями, записанными в M_byte call zapis ; выставляем E=1 на 2мкс (передача в ЖКИ) |
Пример программирования символа в CGRAM (загрузим в CGRAM символ, как на рисунке выше):
;*** 01 010 000 - set CGRAM - установ.адрес CGRAM на 1-ю строку символа №2 ;*** адрес устанавливается один раз, после записи/чтения по этому адресу ;*** указатель (как и в случае с DDRAM) автом-чески сдвинется вправо/влево, ;*** в зависимости от того, что указано при инициализации movlw .5 ; DB7...DB4=0101 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 bcf PortA,1 ; RS=0 bcf PortA,7 ; R/W=0 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .0 ; DB7...DB4=0000 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >39 мкс ********************** call pause1 ;*** Запись восьми байт, определяющих символ, в CGRAM ;*** 1) 0001 1111 2) 0000 0100 3) 0001 1111 4) 0000 0000 ;*** 5) 0001 1101 6) 0001 0010 7) 0001 1111 8) 0000 0000 ;*** Пишем первый байт ****************** bsf PortA,1 ; RS=1, R/W уже установлен в ноль movlw .1 ; DB7...DB4=0001 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .15 ; DB7...DB4=1111 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем второй байт ****************** movlw .0 ; DB7...DB4=0000 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .4 ; DB7...DB4=0100 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем третий байт ****************** movlw .1 ; DB7...DB4=0001 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .15 ; DB7...DB4=1111 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем четвертый байт *************** movlw .0 ; DB7...DB4=0000 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .0 ; DB7...DB4=0000 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем пятый байт ******************* movlw .1 ; DB7...DB4=0001 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .13 ; DB7...DB4=1101 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем шестой байт ****************** movlw .1 ; DB7...DB4=0001 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .2 ; DB7...DB4=0010 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем седьмой байт ***************** movlw .1 ; DB7...DB4=0001 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .15 ; DB7...DB4=1111 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 ;*** Пишем восьмой байт ***************** movlw .0 ; DB7...DB4=0000 - старший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) movlw .0 ; DB7...DB4=0000 - младший полубайт movwf M_byte ; записать это значение в переменную для передачи call in_port ; процедура, которая устанавливает уровни на выходах МК, ; подключенных к линиям DB7...DB4 call zapis ; на 2 мкс выставляем "1" на линии E (запись в ЖКИ) ;*** Пауза >43 мкс ********************** call pause1 |
Всё, теперь этот запрограммированный в CGRAM символ можно вывести на ЖКИ, записав в DDRAM символ под номером 2. Вот пример вывода такого самостоятельно запрограммированного символа на четвертую позицию первой строки ЖКИ:
;*** Set DDRAM ADDRESS 1000 0011 (4-я позиция первой строки ЖКИ) bcf PortA, 1 ; RS=0 bcf PortA, 7 ; R/W=0 movlw .8 ; 1000 - старший полубайт movwf M_byte call in_port call zapis movlw .3 ; 0011 - младший полубайт movwf M_byte call in_port call zapis ;*** Пауза >39 мкс *** call pause1 ;*** Вывод символа (для записи в RAM надо установить RS=1, R/W=0) ;*** Пишем символ под номером 2 (0000 0010) bsf PortA,1 ; RS=1, R/W уже сброшен в 0, его не трогаем movlw .0 ; 0000 movwf M_byte call in_port call zapis movlw .2 ; 0010 movwf M_byte call in_port call zapis ;*** Пауза >43 мкс *** call pause1 |
Как выглядят процедуры zapis, in_port, pause1 можно посмотреть в статье про реализацию связи по восьмибитному интерфейсу. Надеюсь, что теперь, вы без труда сможете переделать их под четырехбитный интерфейс.