Вы находитесь на странице: 1из 15

2-1/4.

"Учебно – тренировочный" вывод, в графический модуль MT-12864J-2YLG,


кода одного кадра ("железяка" и программа под нее). Объяснение работы
программы и показ того, что получилось.

На сей момент, "нарыто" вполне достаточно для того, чтобы "сваять" соответствующую
"железяку".
А вот и она, родимая, "нарисовалась":

Внимание!!!
Нумерация выводов других типов графических модулей "объемом" 128х64 точки
может значительно отличаться от нумерации выводов MT-12864J-2YLG.
Это относится, например, к такому же модулю, но с буквой "A".
Поэтому нужно иметь под рукой соответствующий даташит.
Так как применяется 3-й вариант инициализации графического модуля, то вывод RES
соединен с плюсом источника питания.
Так как используется только режим записи, то вывод R/W соединен с "корпусом".
Теперь о программе.
Я не стал разрисовывать ее блок-схему, а "встроил" ее в текст "нижележащей"
"заготовки".
В совокупности с ранее обозначенной последовательностью действий, должно
получиться именно то, что нужно (надеюсь на это):

;********************************************************************************
; 12864.asm "Заготовка" программы вывода на индикацию,
; в графический модуль МT-12864.., одного "кадра".
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru)
; Корабельников Евгений Александрович karabea@Lipetsk.ru
;********************************************************************************

1
; Автор: Милевский А.З. mazr@bk.ru
; Перевод с PIC16F877A на PIC16F873A и объяснение работы: Корабельников Е.А.
;********************************************************************************
; Используются операторы high и low.
;================================================================================
; Функции выводов порта С:
; RC0...RC7 - выводы данных.
; Функции выводов порта В:
; RB0 - Е2 ; управление правым (2-м) кристаллом,
; RB1 - Е1 ; управление левым (1-м) кристаллом,
; RB2 - E ; на этом выводе формируются стробирующие импульсы,
; RB3 - A0 ; управление режимами "команды/данные",
; остальные выводы порта В не используются.
; Выводы порта С не используются.
; Кварц 4000 Кгц (1 м.ц.= 1 мкс.).
; Используется PIC16F873A.
;================================================================================
LIST p=16F873A ; Задание типа микроконтроллера.
__CONFIG 3F31H ; Включено: XT-генератор, PWRT,
; Выключено: защита, WDT, сброс BOR,
; LVP, DEBUG.
;================================================================================
; Регистры специального назначения.
;================================================================================
PCLATH equ 0Ah ; Регистр PCLATH (используется при работе
; с PCH).
PCL equ 02h ; Регистр младшего байта счетчика команд.
Status equ 03h ; Регистр Status.
PortB equ 06h ; Регистр защелок порта B.
PortC equ 07h ; Регистр защелок порта C.
TrisB equ 06h ; Регистр выбора направлений работы
; выводов порта B (банк 1).
TrisC equ 07h ; Регистр выбора направлений работы
; выводов порта С (банк 1).
;================================================================================
; Регистры общего назачения.
;================================================================================
Temp equ 20h ; Регистр количества проходов.
Reg equ 21h ; Регистр выбора сценария вычисляемого
; перехода.
;================================================================================
; Присвоение битам названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
RP0 equ 5 ; Бит выбора банка.
E2 equ 0 ; Бит выбора 2-го кристалла.
E1 equ 1 ; Бит выбора 1-го кристалла.
E equ 2 ; Бит стробирования.
A0 equ 3 ; Бит выбора режима "команды/данные".
;================================================================================
org 0 ; Начать выполнение программы с 0-го адреса PC
goto START ; Переход в ПП START.
;********************************************************************************

;================================================================================
; Подпрограммы выбора страниц (1...8) кристалла.
;================================================================================
; ПП установки адреса 1-й страницы.
;------------------------------------
STRANICA_1 movlw b'10111000' ; Выбор адреса 1-й страницы.
movwf PortC ; Вывод команды выбора адреса страницы
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB ;
return ; Возврат по стеку в то место, откуда
2
; произошел вызов подпрограммы.
;------------------------------------
; ПП установки адреса 2-й страницы.
;------------------------------------
STRANICA_2 movlw b'10111001' ; Аналогично
;................................. ; (для 2-й страницы).
;------------------------------------
; ПП установки адреса 3-й страницы.
;------------------------------------
STRANICA_3 movlw b'10111010' ; Аналогично
;................................. ; (для 3-й страницы).
;------------------------------------
; ПП установки адреса 4-й страницы.
;------------------------------------
STRANICA_4 movlw b'10111011' ; Аналогично
;................................. ; (для 4-й страницы).
;------------------------------------
; ПП установки адреса 5-й страницы.
;------------------------------------
STRANICA_5 movlw b'10111100' ; Аналогично
;................................. ; (для 5-й страницы).
;------------------------------------
; ПП установки адреса 6-й страницы.
;------------------------------------
STRANICA_6 movlw b'10111101' ; Аналогично
;................................. ; (для 6-й страницы).
;------------------------------------
; ПП установки адреса 7-й страницы.
;------------------------------------
STRANICA_7 movlw b'10111110' ; Аналогично
;................................. ; (для 7-й страницы).
;------------------------------------
; ПП установки адреса 8-й страницы.
;------------------------------------
STRANICA_8 movlw b'10111111' ; Аналогично
;................................. ; (для 8-й страницы).

;================================================================================
; Подпрограмма записи данных.
;================================================================================
WRITE_D bsf PortB,A0 ; Установка признака записи данных {1}.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
bcf PortB,A0 ; Снятие признака записи данных {0}.
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.
;================================================================================
; Подпрограмма стробирования.
;================================================================================
STROB bsf PortB,E ; Формирование
bcf PortB,E ; стробирующего импульса.
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.
;================================================================================
; Подпрограмма установки первого (самого левого) столбца страницы (адрес 00h).
; С него начинается заполнение страницы.
;================================================================================
STOLB_1 movlw b'01000000' ; Выбор адреса 1-го столбца (00h).
movwf PortC ; Вывод команды выбора адреса столбца
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.

3
;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisB ; Все выводы портов В и С
clrf TrisC ; работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Инициализация графического модуля.
;================================================================================
bsf PortB,E1 ; Включение обеих
bsf PortB,E2 ; кристаллов.

movlw b'00111110' ; Инструкция "Display OFF"


movwf PortC ; (выключение дисплея).
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
movlw b'00111111' ; Инструкция "Display ON"
movwf PortC ; (включение дисплея).
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
;------------------------------------
; Задержка 16 мкс (с запасом в 6мкс.)
;------------------------------------
movlw .5 ;
movwf Temp ; Стандартный,
decfsz Temp,F ; 1-байтный
goto $-1 ; счетчик.
;-------------------------------------
; Установка 1-й (самой верхней) строки
; обеих кристаллов (адрес 00h).
;-------------------------------------
movlw b'11000000' ; Выбор адреса 1-й строки (00h).
; (инструкция "Display StartLine").
movwf PortC ; Вывод команды выбора адреса строки
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB

;################################################################################
; РАБОТА С ЛЕВЫМ (1-м) КРИСТАЛЛОМ.
;################################################################################
; Включение 1-го кристалла.
;-------------------------------------
bcf PortB,E2 ; Выключение 2-го кристалла.
;================================================================================
; Заполнение страниц 1-го кристалла.
;================================================================================
; Запись в 1-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
; Подготовительные операции.
;--------------------------------------
call STRANICA_1 ; Выбор 1-й страницы.
call STOLB_1 ; Выбор 1-го столбца страницы.
movlw .64 ; Назначение
movwf Temp ; числа проходов.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Циклическая ПП заполнения байтами данных столбцов страницы.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
WR_1 movf Temp,W ; Число проходов --> в W.
sublw .64 ; .64 - Temp = ... (результат --> в W).
movwf Reg ; В регистр Reg записывается номер текущего
; сценария вычисляемого перехода.
;-------------------------------------
4
; Отработка ПП, в состав которой
; входит вычисляемый переход.
;-------------------------------------
call TEXT_1 ; Переход в ПП TEXT_1.
;---> Возврат по стеку из ПП TEXT_1
;-------------------------------------
; Вывод на индикацию текущего байта
; данных ("лежит" в W).
;-------------------------------------
movwf PortC ; Установка на линиях DB7...DB0 числового
; значения текущего байта данных.
movlw high WRITE_D; Установка в PCH числового значения старшего
movwf PCLATH ; байта адреса (в PC) первой команды
; ПП WRITE_D (через W).
call WRITE_D ; Переход в ПП WRITE_D (с предустановленным
; значением PCH).
;---> Возврат по стеку из ПП WRITE_D
decfsz Temp,F ; Число проходов уменьшается на 1.
goto WR_1 ; Если результат не=0, то переход на
; обработку следующего байта данных.
; Если =0, то запись в 1-ю страницу
; заканчивается и программа исполняется
; далее.
;--------------------------------------------------------------------------------
; Запись во 2-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 2-й страницы).
;--------------------------------------------------------------------------------
; Запись в 3-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 3-й страницы).
;--------------------------------------------------------------------------------
; Запись в 4-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 4-й страницы).
;--------------------------------------------------------------------------------
; Запись в 5-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 5-й страницы).
;--------------------------------------------------------------------------------
; Запись в 6-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 6-й страницы).
;--------------------------------------------------------------------------------
; Запись в 7-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 7-й страницы).
;--------------------------------------------------------------------------------
; Запись в 8-ю страницу 1-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 8-й страницы).

;################################################################################
; РАБОТА С ПРАВЫМ (2-м) КРИСТАЛЛОМ.
;################################################################################
; Включение 2-го кристалла.
;-------------------------------------
bcf PortB,E1 ; Выключение 1-го кристалла.
bsf PortB,E2 ; Включение 2-го кристалла.
;================================================================================
; Заполнение страниц 2-го кристалла.
;================================================================================
; Запись в 1-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 1-й страницы).
;--------------------------------------------------------------------------------
5
; Запись во 2-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 2-й страницы).
;--------------------------------------------------------------------------------
; Запись в 3-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 3-й страницы).
;--------------------------------------------------------------------------------
; Запись в 4-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 4-й страницы).
;--------------------------------------------------------------------------------
; Запись в 5-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 5-й страницы).
;--------------------------------------------------------------------------------
; Запись в 6-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 6-й страницы).
;--------------------------------------------------------------------------------
; Запись в 7-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 7-й страницы).
;--------------------------------------------------------------------------------
; Запись в 8-ю страницу 2-го кристалла
;--------------------------------------------------------------------------------
;....................................... Аналогично (для 8-й страницы).
;================================================================================
; Окончание цикла вывода данных на индикацию.
;================================================================================
goto $ ; "Мертвяк".
;--------------------------------------------------------------------------------

;********************************************************************************
; Таблицы данных, предназначенных для записи.
;********************************************************************************
; КРИСТАЛЛ 1
;================================================================================
; Данные 1-й страницы 1-го кристалла.
;--------------------------------------------------------------------------------
TEXT_1 movlw high STR_1 ; Установка в PCH числового значения старшего
movwf PCLATH ; байта адреса (в PC) первой команды (retlw
; ...) табличного перехода
; (помечена меткой STR_1).
;--------------------------------------
; Анализ выхода или нет за пределы
; текущего блока памяти программ.
;--------------------------------------
movf Reg,W ; Номер сценария вычисляемого перехода --> W.
addlw low STR_1 ; Суммирование номера сценария и числового
; значения младшего байта адреса (в PC)
; ПП STR_1 (через W).
;---------------------------------------------
; Проверка на наличие или отсутствие переноса
; (PCH+1 или этого делать не нужно?).
;---------------------------------------------
btfsc Status,C ; Перенос был или нет?
incf PCLATH,F ; Если был, то PCLATH+1 (PCH+1=...).
movf Reg,W ; Если не был, то инкремента содержимого PCH
; не происходит и номер сценария вычисляемого
; перехода (в любом случае) копируется в W.
;--------------------------------------
; Табличный, вычисляемый переход.
;--------------------------------------
addwf PCL,F ; Приращение PCL на величину содержимого W.
STR_1 dt 0x00,0x00,0xFE,0x02,0x02,0xFE,0x00,0x00
6
dt 0x00,0x00,0xFC,0x24,0x24,0x18,0x00,0x00
dt 0x00,0x00,0x78,0x84,0x84,0x78,0x00,0x00
dt 0x00,0x00,0xFC,0x94,0x94,0x64,0x00,0x00
dt 0x00,0x00,0xF8,0x24,0x24,0xF8,0x00,0x00
dt 0x10,0x38,0x54,0x92,0x10,0x10,0x10,0x10
dt 0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81
dt 0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00
;--------------------------------------------------------------------------------
; Данные 2-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_2 ;................................. Аналогично (для 2-й страницы).
;--------------------------------------------------------------------------------
; Данные 3-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_3 ;................................. Аналогично (для 3-й страницы).
;--------------------------------------------------------------------------------
; Данные 4-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_4 ;................................. Аналогично (для 4-й страницы).
;--------------------------------------------------------------------------------
; Данные 5-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_5 ;................................. Аналогично (для 5-й страницы).
;--------------------------------------------------------------------------------
; Данные 6-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_6 ;................................. Аналогично (для 6-й страницы).
;--------------------------------------------------------------------------------
; Данные 7-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_7 ;................................. Аналогично (для 7-й страницы).
;--------------------------------------------------------------------------------
; Данные 8-й страницы 1-го кристалла
;--------------------------------------------------------------------------------
TEXT_8 ;................................. Аналогично (для 8-й страницы).

;================================================================================
; КРИСТАЛЛ 2
;================================================================================
; Данные 1-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_9 ;................................. Аналогично (для 1-й страницы).
;--------------------------------------------------------------------------------
; Данные 2-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_10 ;................................. Аналогично (для 2-й страницы).
;--------------------------------------------------------------------------------
; Данные 3-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_11 ;................................. Аналогично (для 3-й страницы).
;--------------------------------------------------------------------------------
; Данные 4-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_12 ;................................. Аналогично (для 4-й страницы).
;--------------------------------------------------------------------------------
; Данные 5-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_13 ;................................. Аналогично (для 5-й страницы).
;--------------------------------------------------------------------------------
; Данные 6-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_14 ;................................. Аналогично (для 6-й страницы).
;--------------------------------------------------------------------------------
; Данные 7-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_15 ;................................. Аналогично (для 7-й страницы).
7
;--------------------------------------------------------------------------------
; Данные 8-й страницы 2-го кристалла
;--------------------------------------------------------------------------------
TEXT_16 ;................................. Аналогично (для 8-й страницы).
;********************************************************************************
end ; Конец программы.

Зеленым цветом выделены подготовительные операции ПП START.


Фиолетовым цветом выделена процедура инициализации графического модуля.
Красным цветом выделена группа подпрограмм выбора страниц.
Темно – красным цветом выделена группа подпрограмм, "рулящих" заполнением
страниц.
Темно – синим цветом выделена группа подпрограмм табличных, вычисляемых
переходов, в комплексе с их "обслугой".
Серым цветом выделена подпрограмма записи данных.
Коричневым цветом выделена подпрограмма формирования стробирующего импульса.
Синим цветом выделена подпрограмма выбора 1-го столбца страницы.
Цветом хаки выделены комментарии.

Работа программы.

Подготовительные операции ПП START просты "до безобразия": только "оптовая"


настройка направлений работы выводов задействованных портов (на выход).
Все остальное - по умолчанию.

;================================================================================
; Подготовительные операции.
;================================================================================
START bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisB ; Все выводы портов В и С
clrf TrisC ; работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.

Далее исполняется процедура инициализации графического модуля (по 3-му варианту):

;================================================================================
; Инициализация графического модуля.
;================================================================================
bsf PortB,E1 ; Включение обеих
bsf PortB,E2 ; кристаллов.

movlw b'00111110' ; Инструкция "Display OFF"


movwf PortC ; (выключение дисплея).
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
movlw b'00111111' ; Инструкция "Display ON"
movwf PortC ; (включение дисплея).
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
;------------------------------------
; Задержка 16 мкс (с запасом в 6мкс.)
;------------------------------------
movlw .5 ;
movwf Temp ; Стандартный,
decfsz Temp,F ; 1-байтный
goto $-1 ; счетчик.
;-------------------------------------
; Установка 1-й (самой верхней) строки
; обеих кристаллов (адрес 00h).
;-------------------------------------
movlw b'11000000' ; Выбор адреса 1-й строки (00h)
; (инструкция "Display StartLine").
8
movwf PortC ; Вывод команды выбора адреса строки
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB

Сначала включаются оба кристалла.


А как же иначе? Иначе будет неполная инициализация всего дисплея.
Далее - то, о чем говорилось ранее:
- выключение дисплея / строб (инструкция "Display OFF"),
- включение дисплея / строб (инструкция "Display ON").
Между стробирующими перепадами, "запускающими в работу" инструкции "Display
OFF" и "Display ON", будет иметь место быть интервал времени больший, чем 1 мкс.
(см. "правила игры"). И это прекрасно.

За формирование стробирующего импульса "отвечает" ПП STROB:

;================================================================================
; Подпрограмма стробирования.
;================================================================================
STROB bsf PortB,E ; Формирование
bcf PortB,E ; стробирующего импульса.
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.

По-моему, тут и объяснять-то нечего ("мычание коровы").


Нужно только отметить то, что длительность стробирующего импульса равна 1 мкс., что
примерно в 2 раза больше "прожиточного минимума", и то, что эта ПП вызывается
чаще, чем любая из остальных ПП (стробом сопровождается любая инструкция).
Ну и океюшки.
Далее, для соблюдения "правил игры" (задержка не менее 10 мкс.), формируется
простенькая, фиксированная задержка величиной 16 мкс. (константа 5).
Можно сделать и 13 мкс. (константа 4).
После этого, исполняется инструкция "Display StartLine": выбор строки, с которой
начнется формирование картинки.
То есть, осуществляется "привязка" верхней "границы" картинки к верхней границе
дисплея.
Если задать другой адрес, то можно сместить вниз верхнюю "границу" картинки
(относительно верхней "границы" дисплея).
Но об этом - позднее.
Так как оба кристалла ранее были включены, то инструкция "Display StartLine"
исполняется в обеих кристаллах.
Вот и вся инициализация графического модуля.
Она проще, чем инициализация ЖК-модуля на основе HD44780.

Далее, вся эта "буйная демократия" заканчивается и начинается последовательная


работа с кристаллами.
Сначала - с первым.

;################################################################################
; РАБОТА С ЛЕВЫМ (1-м) КРИСТАЛЛОМ.
;################################################################################

Значит, нужно просто выключить 2-й кристалл (напоминаю, что оба кристалла были
включены).
;-------------------------------------
; Включение 1-го кристалла.
;-------------------------------------
bcf PortB,E2 ; Выключение 2-го кристалла.

Далее, происходит выбор 1-й страницы 1-го кристалла (call STRANICA_1).


9
;--------------------------------------
; Подготовительные операции.
;--------------------------------------
call STRANICA_1 ; Выбор 1-й страницы.

"За это дело отвечает" ПП STRANICA_1:

;------------------------------------
; ПП установки адреса 1-й страницы.
;------------------------------------
STRANICA_1 movlw b'10111000' ; Выбор адреса 1-й страницы.
movwf PortC ; Вывод команды выбора адреса страницы
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB ;
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.

В ней нет ничего выдающегося, кроме банального исполнения инструкции "Set Page".
Таких маленьких "подпрограммок" - 8 штук (по числу страниц одного кристалла).
По ходу заполнения, сначала 1-го кристалла, а затем и 2-го кристалла, они
последовательно вызываются и отрабатываются.
Разница между ними только в числовых значениях младших трех битов (адрес
страницы) байта команды, "транспортируемой" на линии DB7 … DB0.
Итак, 1-я страница выбрана.

Теперь нужно выбрать 1-й столбец этой страницы:

call STOLB_1 ; Выбор 1-го столбца страницы.

"За это дело отвечает" ПП STOLB_1:

;================================================================================
; Подпрограмма установки первого (самого левого) столбца страницы (адрес 00h).
; С него начинается заполнение страницы.
;================================================================================
STOLB_1 movlw b'01000000' ; Выбор адреса 1-го столбца (00h).
movwf PortC ; Вывод команды выбора адреса столбца
; на линии DB7...DB0.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.

В ней также нет ничего выдающегося, кроме исполнения инструкции "Set Adress".
А так как, в данном случае, заполнение любой страницы всегда начинается с ее 1-го
столбца, то и количество подпрограмм выбора столбца - ровно одна штука.
Итак, выбрана 1-я страница, а в ней выбран 1-й (самый левый) столбец.
Но это еще не вся подготовка к заполнению текущей страницы.
Если ее заполнять без чувства меры, то будет работа по кольцу, а если будет
"недобор", то страница заполнится не полностью.
Значит, нужно назначить количество проходов.
В одной странице - 64 байта. Заполнение - "сплошное".
Значит, получается это:

movlw .64 ; Назначение


movwf Temp ; числа проходов.

Подготовительные операции закончились.

10
Теперь можно входить в циклическую (см. число .64) подпрограмму заполнения
страницы байтами данных:

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Циклическая ПП заполнения байтами данных столбцов страницы.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
WR_1 movf Temp,W ; Число проходов --> в W.
sublw .64 ; .64 - Temp = ... (результат --> в W).
movwf Reg ; В регистр Reg записывается номер текущего
; сценария вычисляемого перехода.
;-------------------------------------
; Отработка ПП, в состав которой
; входит вычисляемый переход.
;-------------------------------------
call TEXT_1 ; Переход в ПП TEXT_1.
;---> Возврат по стеку из ПП TEXT_1
;-------------------------------------
; Вывод на индикацию текущего байта
; данных ("лежит" в W).
;-------------------------------------
movwf PortC ; Установка на линиях DB7...DB0 числового
; значения текущего байта данных.
movlw high WRITE_D; Установка в PCH числового значения старшего
movwf PCLATH ; байта адреса (в PC) первой команды
; ПП WRITE_D (через W).
call WRITE_D ; Переход в ПП WRITE_D (с предустановленным
; значением PCH).
;---> Возврат по стеку из ПП WRITE_D
decfsz Temp,F ; Число проходов уменьшается на 1.
goto WR_1 ; Если результат не=0, то переход на
; обработку следующего байта данных.
; Если =0, то запись в 1-ю страницу
; заканчивается и программа исполняется
; далее.
Она организована по стандартному принципу "постановки на счетчик" числа проходов,
о сути которого я рассказывал много раз.
А так как у меня, от такого количества повторений, "на языке образовался мозоль", то
Вы уж не обессудьте. Вдаваться в подробности не буду.
Номер текущего, исполняемого сценария табличного, вычисляемого перехода
определяется результатом вычитания, из константы .64, содержимого регистра Temp,
которое декрементируется в конце каждого цикла ПП WR_1.
Этот "номер" записывается в регистр Reg (movwf Reg).
Далее, имеет место быть условный переход в ПП TEXT_1 (вычисляемый переход
входит в ее состав).

Внимание!!! Важно.

В рассматриваемом случае, "объем" программы не превышает "объема" одной


страницы памяти программ ПИКа (менее, чем 2048 команд).
С учетом этого, а также и того, что команды call и goto имеют 11-разрядную
адресацию, в данном случае, можно "безбяково прыгнуть" на любую команду
программы ("исхитряться" не нужно).
Это Вы и видите.
Но если "объем" программы "зашкаливает" за 2048 команд и нужно, с первой
страницы памяти программ ПИКа "прыгнуть", например, на вторую (или
последующие) страницу памяти программ ПИКа, то будет "Гитлер капут".
Он заключается в том, что в этом случае, "прыжок" произойдет не с одной страницы
памяти программ ПИКа на другую, а по кольцу (в "границах" текущей страницы
памяти программ ПИКа).
Например, если "прыжок" осуществляется из 1-й страницы памяти программ на,
например, трехтысячную команду программы ("лежит" на 2-й странице памяти
программ ПИКа), то будет иметь место быть "прыжок" не на трехтысячную команду,
11
а на команду с номером 3000 – 2048 = 952.
Чтобы избежать этого "подлого подвоха", нужно, перед "прыжком"
(перед call TEXT_1), осуществить "плавающую" коррекцию содержимого PCH.
При этом, не нужно "забивать себе голову" содержимым PCH, ведь коррекция-то -
"плавающая".
В этом случае, "вышележащая" группа команд будет иметь вид:

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Циклическая ПП заполнения байтами данных столбцов страницы.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
WR_1 movf Temp,W ; Число проходов --> в W.
sublw .64 ; .64 - Temp = ... (результат --> в W).
movwf Reg ; В регистр Reg записывается номер текущего
; сценария вычисляемого перехода.
movlw high TEXT_1 ; "Плавающая" коррекция
movwf PCLATH ; содержимого PCH.
;-------------------------------------
; Отработка ПП, в состав которой
; входит вычисляемый переход.
;-------------------------------------
call TEXT_1 ; Переход в ПП TEXT_1.
;---> Возврат по стеку из ПП TEXT_1
;-------------------------------------
; Вывод на индикацию текущего байта
; данных ("лежит" в W).
;-------------------------------------
movwf PortC ; Установка на линиях DB7...DB0 числового
; значения текущего байта данных.
movlw high WRITE_D; Установка в PCH числового значения
movwf PCLATH ; старшего байта адреса (в PC) первой
; команды ПП WRITE_D (через W).
call WRITE_D ; Переход в ПП WRITE_D (с предустановленным
; значением PCH).
;---> Возврат по стеку из ПП WRITE_D
decfsz Temp,F ; Число проходов уменьшается на 1.
goto WR_1 ; Если результат не=0, то переход на
; обработку следующего байта данных.
; Если =0, то запись в 1-ю страницу
; заканчивается и программа исполняется
; далее.

Дополнительные команды выделены красным цветом.

После возврата по стеку из ПП TEXT_1, байт отработанного, текущего сценария


устанавливается на линиях DB7 … DB0:

movwf PortC ; Установка на линиях DB7...DB0 числового


; значения текущего байта данных.

Теперь нужно "прыгнуть" в ПП записи данных с названием WRITE_D (call WRITE_D).


Но при этом нужно учесть то, что возврат происходит из того блока памяти программ
ПИКа, который не является блоком памяти программ ПИКа, в котором "лежит" ПП
WRITE_D.
Если соответствующим образом не "подсуетиться", то этот "прыжок" (call WRITE_D)
приведет к ранее упомянутому, "прискорбному и гнусному изнасилованию" рабочей
точки программы все в том же "темном леске" (см. предыдущий подраздел).
Но эти "происки империализма" не пройдут, так как уже доподлинно известно, "где
именно собака порылась" ("на мякине уже не проведешь").
"Скуловоротный" ответ, на эти жалкие (с учетом "мякины") "происки", все тот же:

movlw high WRITE_D; Установка в PCH числового значения


movwf PCLATH ; старшего байта адреса (в PC) первой
12
; команды ПП WRITE_D (через W).
И все дела …
О возврате, из ПП WRITE_D, беспокоиться не нужно.
Он будет осуществлен именно туда, куда "положено" (в вершине стека лежит полный
адрес возврата).

О ПП записи данных:

;================================================================================
; Подпрограмма записи данных.
;================================================================================
WRITE_D bsf PortB,A0 ; Установка признака записи данных {1}.
call STROB ; Строб ("запуск в работу").
;---> Возврат по стеку из ПП STROB
bcf PortB,A0 ; Снятие признака записи данных {0}.
return ; Возврат по стеку в то место, откуда
; произошел вызов подпрограммы.

Сие есть незамысловатое исполнение инструкции "Write Data".


Короче, очередное "мычание коровы".
Даже обидно …
А с другой стороны, "все гениальное просто" (разработчикам à медаль и бутылка
водки).
После вывода текущего байта данных в текущий столбец страницы, происходит
декремент содержимого регистра Temp и переход на следующий цикл заполнения
байтами столбцов страницы.
И так - до конца отработки 64-го сценария текущего, вычисляемого перехода.
После этого, происходит выбор следующей страницы текущего кристалла и ее
заполнение байтами данных, начиная с 1-го ее столбца и до конца.
После заполнения всех 8-ми страниц 1-го кристалла, происходит переход на 2-й
кристалл:

;-------------------------------------
; Включение 2-го кристалла.
;-------------------------------------
bcf PortB,E1 ; Выключение 1-го кристалла.
bsf PortB,E2 ; Включение 2-го кристалла.

и … "на колу мочало, начинаем все сначала".


Примечание: в группе подпрограмм, работающих со 2-м кристаллом, я продолжил
нумерацию страниц (9 … 16).
Следует учесть то, что цифра 9 указывает на 1-ю страницу 2-го кристалла, цифра 10
указывает на 2-ю страницу 2-го кристалла и т.д.

Теперь о "технологии" табличного, вычисляемого перехода.

;********************************************************************************
; Таблицы данных, предназначенных для записи.
;********************************************************************************
; КРИСТАЛЛ 1
;================================================================================
; Данные 1-й страницы 1-го кристалла.
;--------------------------------------------------------------------------------
TEXT_1 movlw high STR_1 ; Установка в PCH числового значения старшего
movwf PCLATH ; байта адреса (в PC) первой команды (retlw
; ...) табличного перехода
; (помечена меткой STR_1).
;--------------------------------------
; Анализ выхода или нет за пределы
; текущего блока памяти программ.
;--------------------------------------

13
movf Reg,W ; Номер сценария вычисляемого перехода --> W.
addlw low STR_1 ; Суммирование номера сценария и числового
; значения младшего байта адреса (в PC)
; ПП STR_1 (через W).
;---------------------------------------------
; Проверка на наличие или отсутствие переноса
; (PCH+1 или этого делать не нужно?).
;---------------------------------------------
btfsc Status,C ; Перенос был или нет?
incf PCLATH,F ; Если был, то PCLATH+1 (PCH+1=...).
movf Reg,W ; Если не был, то инкремента содержимого PCH
; не происходит и номер сценария вычисляемого
; перехода (в любом случае) копируется в W.
;--------------------------------------
; Табличный, вычисляемый переход.
;--------------------------------------
addwf PCL,F ; Приращение PCL на величину содержимого W.
STR_1 dt 0x00,0x00,0xFE,0x02,0x02,0xFE,0x00,0x00
dt 0x00,0x00,0xFC,0x24,0x24,0x18,0x00,0x00
dt 0x00,0x00,0x78,0x84,0x84,0x78,0x00,0x00
dt 0x00,0x00,0xFC,0x94,0x94,0x64,0x00,0x00
dt 0x00,0x00,0xF8,0x24,0x24,0xF8,0x00,0x00
dt 0x10,0x38,0x54,0x92,0x10,0x10,0x10,0x10
dt 0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81
dt 0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00

Эта "технология" была "расписана" в предыдущем подразделе.


Коротко повторюсь.
Сначала, с целью обеспечения соответствия числового значения текущего, старшего
байта счетчика команд, числовому значению PCH первой команды (retlw …)
вычисляемого перехода (на нее указывает метка), производится "плавающая" коррекция
содержимого текущего PCH (через PCLATH):

TEXT_1 movlw high STR_1 ; Установка в PCH числового значения старшего


movwf PCLATH ; байта адреса (в PC) первой команды (retlw
; ...) табличного перехода
; (помечена меткой STR_1).

Далее, определяется, проходит или не проходит "граница" между блоками памяти


программ ПИКа через таблицу вычисляемого перехода:

;--------------------------------------
; Анализ выхода или нет за пределы
; текущего блока памяти программ.
;--------------------------------------
movf Reg,W ; Номер сценария вычисляемого перехода --> W.
addlw low STR_1 ; Суммирование номера сценария и числового
; значения младшего байта адреса (в PC)
; ПП STR_1 (через W).
;---------------------------------------------
; Проверка на наличие или отсутствие переноса
; (PCH+1 или этого делать не нужно?).
;---------------------------------------------
btfsc Status,C ; Перенос был или нет?
incf PCLATH,F ; Если был, то PCLATH+1 (PCH+1=...).
movf Reg,W ; Если не был, то инкремента содержимого PCH
; не происходит и номер сценария вычисляемого
; перехода (в любом случае) копируется в W.

Если не проходит, то команда инкремента содержимого регистра PCLATH обходится.


Если проходит, то при исполнении сценариев вычисляемого перехода, которые
располагаются выше этой "границы", происходит то же самое (обход инкремента), а
вот в случае отработки сценариев вычисляемого перехода, которые располагаются

14
ниже этой "границы", инкремент содержимого регистра PCH (посредством PCLATH)
производится.
Далее, имеет место быть стандартный, вычисляемый, табличный переход, с
использованием директивы DT (64 сценария), в котором нет абсолютно ничего нового:

;--------------------------------------
; Табличный, вычисляемый переход.
;--------------------------------------
addwf PCL,F ; Приращение PCL на величину содержимого W.
STR_1 dt 0x00,0x00,0xFE,0x02,0x02,0xFE,0x00,0x00
dt 0x00,0x00,0xFC,0x24,0x24,0x18,0x00,0x00
dt 0x00,0x00,0x78,0x84,0x84,0x78,0x00,0x00
dt 0x00,0x00,0xFC,0x94,0x94,0x64,0x00,0x00
dt 0x00,0x00,0xF8,0x24,0x24,0xF8,0x00,0x00
dt 0x10,0x38,0x54,0x92,0x10,0x10,0x10,0x10
dt 0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81
dt 0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00

Вы видите 1/16-ю часть того, что было "заготовлено" ранее (в подразделе 1/2).
Таблицы можно оформить не обязательно именно так.
Например, можно, в каждой строке, разместить не по 8 чисел, а по 16.
Или еще как-то. На суть не влияет.

И наконец, "финал" типа "сушите весла":

;================================================================================
; Окончание цикла вывода данных на индикацию.
;================================================================================
goto $ ; "Мертвяк".
;--------------------------------------------------------------------------------

А можно и goto START. На визуальное восприятие картинки не влияет.

Все это, конечно же, распрекрасно, но лучше всего убеждают не всяческие


"словоблудия", а реальная, "железячная" картинка.
А вот и она, родимая (с "атрибутами жизнедеятельности", в виде подпаянных
"проволочин"):
"Полноценная" программа под
эту "неземную красоту"
называется 12864_1.asm.
Естественно, что она
прилагается (не уважаю
"ежиков в тумане").
А заодно прилагается и то,
вокруг чего велись разговоры:
"заготовка" 12864.asm.
В комплексе со всем
остальным, это должно
обеспечить (надеюсь)
беспроблемный, детальный
"въезд" в тему (на уровне того,
что сказано).

"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

15