Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 16.06.2025
Просмотров: 3617
Скачиваний: 3
;На данный момент, регистры LED0 ... LED7 заполнены двоично-десятичными числами,
;которые необходимо вывести на индикацию (отобразить) в линейку из 8-ми
;7-сегментных индикаторов.
;На момент начала группы подпрограмм динамической индикации, все прерывания
;должны быть запрещены, все выводы порта В и первые 3 вывода порта А должны быть
;настроены на работу "на выход", работа должна происходить в нулевом банке.
;********************************************************************************
;Подготовка счетчика количества малых колец индикации Index к началу полного
;цикла динамической индикации.
;-------------------------------------------------------------------------------- |
|||||
clrf |
Index |
; |
Сброс |
в 0 содержимого |
счетчика |
; |
малых |
колец индикации |
Index. |
||
;-------------------------------------------------------------------------------- |
;Предварительная закладка количества больших колец индикации, которое нужно
;"пройти" за один полный цикл динамической индикации в регистр Count.
;-------------------------------------------------------------------------------- |
|||
movlw |
X |
; Запись константы |
X (количество больших |
; колец индикации, |
задается программистом), |
||
; в регистр W. |
|||
movwf |
Count |
; Копирование содержимого регистра W в |
|
; регистр счетчика |
количества больших колец |
||
; индикации Count. |
|||
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Использование косвенной адресации при работе с таблицей данных.
;================================================================================
;Подготовка к косвенной адресации: запись в регистр W адреса регистра младшего
;разряда линейки 7-сегментных индикаторов ("привязка" к 7-сегментному
;индикатору, с активации которого начинается полный цикл первого большого
;кольца индикации).
; |
-------------------------------------------------------------------------------- |
|||
CYCLE |
movlw |
LED0 |
; Запись в регистр W адреса регистра LED0. |
|
addwf |
Index,W |
; Увеличение адреса регистра LED0 на величину |
||
; числа, записанного в регистре счетчика |
||||
; количества малых колец индикации Index, |
||||
; c сохранением результата в регистре W. |
||||
;-------------------------------------------------------------------------------- |
||||
; Косвенная |
адресация. |
|||
;-------------------------------------------------------------------------------- |
||||
movwf |
FSR |
; Копирование содержимого регистра W |
||
; в регистр FSR. |
||||
movf |
Indf,W |
; Копирование содержимого регистра с адресом, |
||
; записанным в регистре FSR, в регистр W. |
||||
call |
TABLE |
; Условный переход (адрес следующей команды |
||
; закладывается в стек) в ПП TABLE. |
||||
;--- |
> Возврат по стеку из ПП TABLE |
|||
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Группа команд установки запятой. |
||
;-------------------------------------------------------------------------------- |
||
movwf |
Temp |
; Копирование содержимого регистра W (7- |
; сегментные коды индицируемых двоично- |
||
; десятичных чисел) в регистр Temp. |
||
movlw |
5 |
; Запись в регистр W константы .05. |
bsf |
Status,Z |
; Поднятие флага нулевого результата Z. |
subwf |
Index,W |
; Вычесть содержимое регистра W (число .05) |
; из содержимого регистра Index |
||
; (числа от .00 до .07). |
||
btfss |
Status,Z |
; Проверка состояния флага Z. |
goto |
No_Dot |
; Если флаг Z опущен (результат операции |
; не=0), то переход в ПП No_Dot |
||
; (запятая не выставляется). |
||
bsf |
Temp,7 |
; Если флаг Z поднят (результат операции=0), |
; то установка в единицу 7-го бита |
||
; (установка запятой) регистра Temp. |
||
;--------------------------------------------------------------------------------
; Группа команд вывода десятичной цифры на индикацию.
;--------------------------------------------------------------------------------
235
No_Dot |
movf |
Temp,W |
; Копирование |
содержимого регистра Temp (7- |
|||
; сегментные |
коды индицируемых двоично- |
||||||
; десятичных |
чисел) |
в регистр W. |
|||||
movwf |
PortB |
; |
Копирование |
содержимого регистра W |
|||
; |
в 8 защелок |
порта |
В. |
||||
;--------------------------------------------------------------------------------
; Группа команд формирования адресного кода управления дешифратором.
;--------------------------------------------------------------------------------
movf |
Index,W |
; Копирование содержимого регистра Index |
; в регистр W. |
||
movwf |
PortA |
; Копирование содержимого регистра W в первые |
; 3 защелки порта А (работа "на выход"), |
||
; управляющие адресными входами внешнего |
||
; дешифратора. |
||
;-------------------------------------------------------------------------------- |
;Группа команд задержки, определяющей время нахождения одного 7-сегментного
;индикатора в активном состоянии (определяющей время прохождения малого
;кольца индикации).
;"Грубое" формирование времени полного цикла динамической индикации.
;-------------------------------------------------------------------------------- |
|||
movlw |
Const1 |
; Запись в регистр W константы Y1 (см"шапку") |
|
movwf |
Temp |
; Копирование содержимого регистра W |
|
; в регистр Temp. |
|||
PAUSE |
decfsz |
Temp,F |
; Декремент содержимого регистра Temp c |
; сохранением результата в нем же. |
|||
goto |
PAUSE |
; Если результат декремента не=0, |
|
; то переход в ПП PAUSE. |
|||
; Если результат декремента =0, |
|||
; то программа исполняется далее. |
|||
;-------------------------------------------------------------------------------- |
; Увеличение на 1 содержимого счетчика количества малых колец индикации Index с
; последующей проверкой результата инкремента на |
равенство (или нет) числу .08. |
|||
;-------------------------------------------------------------------------------- |
||||
incf |
Index,F |
; Увеличение |
на |
1 содержимого регистра Index |
; с сохранением |
результата в нем же. |
|||
movlw |
.08 |
; Запись в регистр W константы .08. |
||
bcf |
Status,Z |
; Сброс флага нулевого результата Z. |
||
subwf |
Index,W |
; Вычесть из |
содержимого регистра Index |
|
; содержимое |
регистра W, с сохранением |
|||
; результата |
в регистре W. |
|||
btfss |
Status,Z |
; Результат операции вычитания равен |
||
; или нет нулю? |
||||
goto |
CYCLE |
; Если не =0 |
(в |
регистре Index - число не |
; равное 8), |
то |
переход к циклу активизации |
||
; следующего |
по |
старшинству 7-сегментного |
||
; индикатора |
(переход на новое малое кольцо |
|||
; индикации, |
то |
есть, в ПП CYCLE). |
||
; Если =0 (в |
регистре Index - число равное |
|||
; 8), то программа исполняется далее. |
||||
;-------------------------------------------------------------------------------- |
||||
;Начало перехода на новое большое кольцо индикации после того, как
;последовательно активируются все 8 7-сегментных индикатора линейки
;(после прохождения 8-ми малых колец индикации).
;-------------------------------------------------------------------------------- |
|||
nop |
; |
Выравнивающий NOP. |
|
clrf |
Index |
; |
Сброс в 0 содержимого регистра Index. |
;-------------------------------------------------------------------------------- |
|||
; Уменьшение на 1 содержимого счетчика количества больших колец |
индикации Count. |
||
;-------------------------------------------------------------------------------- |
|||
decfsz |
Count,F |
; Декремент содержимого счетчика количества |
|
; больших колец индикации Count, |
|||
; с сохранением результата в нем же. |
|||
goto |
CYCLE |
; Если результат декремента |
не=0, то переход |
; в ПП CYCLE |
|||
; (переход на новое большое |
кольцо индикации) |
||
; Если результат декремента |
=0, то программа |
||
236
; исполняется далее |
(переход на |
новый полный |
||
; |
цикл динамической |
индикации). |
||
nop |
; |
Выравнивающий NOP. |
||
;================================================================================
;Группы подпрограмм и команд, осуществляющие различные операции.
;================================================================================
;"Точное" формирование времени полного цикла динамической индикации (если
;требуется точно калиброванное время полного цикла динамической индикации для
;использования его в качестве измерительного интервала).
;-------------------------------------------------------------------------------- |
|||
movlw |
Const2 |
; Запись в регистр W константы Y2 (см"шапку") |
|
movwf |
Temp |
; Копирование содержимого регистра W |
|
; в регистр Temp. |
|||
PAUSE_1 |
decfsz |
Temp,F |
; Декремент содержимого регистра Temp с |
; сохранением результата в нем же. |
|||
goto |
PAUSE_1 |
; Если результат декремента не=0, |
|
; то переход в ПП PAUSE_1. |
|||
; Если результат декремента =0, |
|||
; то программа исполняется далее. |
|||
;-------------------------------------------------------------------------------- |
|||
; Гашение активного разряда линейки. |
|||
;-------------------------------------------------------------------------------- |
|||
movlw |
0 |
; Запись в регистр W константы .00. |
|
movwf |
PortB |
; Сброс в 0 всех защелок порта В. |
|
;-------------------------------------------------------------------------------- |
|||
; ........................................
; ........................................
; ........................................
; ........................................
; ........................................
; ........................................
;На данный момент, регистры LED0 ... LED7 заполнены двоичными числами, которые,
;в дальнейшем, нужно преобразовать в двоично-десятичные и сохранить их все в тех
;же регистрах LED0 ... LED7.
goto |
Bin2_10 |
; |
Безусловный переход в ПП Bin2_10. |
|||
;-------------------------------------------------------------------------------- |
||||||
; |
Применение вычисляемого перехода. |
|||||
; (преобразование двоично-десятичного |
кода в код |
7-сегментного индикатора) |
||||
;-------------------------------------------------------------------------------- |
||||||
TABLE |
addwf |
PC,F |
; |
Содержимое |
счетчика команд PC увеличивается |
|
; |
на величину содержимого аккумулятора W. |
|||||
retlw |
b'00111111' ; |
..FEDCBA = |
0 |
Происходит скачек по таблице |
||
retlw |
b'00000110' ; |
.....CB. = |
1 |
на строку со значением, |
||
retlw |
b'01011011' ; |
.G.ED.BA = |
2 |
записанным в аккумуляторе, |
||
retlw |
b'01001111' ; |
.G..DCBA = |
3 |
и далее - возврат по стеку. |
||
retlw |
b'01100110' ; |
.GF..CB. = |
4 |
|||
retlw |
b'01101101' ; |
.GF.DC.A = |
5 |
|||
retlw |
b'01111101' ; |
.GFEDC.A = |
6 |
|||
retlw |
b'00000111' ; |
.....CBA = |
7 |
|||
retlw |
b'01111111' ; |
.GFEDCBA = |
8 |
|||
retlw |
b'01101111' ; |
.GF.DCBA = |
9 |
|||
;******************************************************************************** end ; Конец программы.
Часть этой программы мы уже разобрали, а остаток "разложим на молекулы" сейчас. Начну с "шапки".
Вы видите, что в ней дополнительно "прописаны" 2 регистра специального назначения (регистры управления защелками портов А и В: PortA и PortB) и один регистр общего назначения Temp, который выполняет функции многоцелевого регистра оперативной памяти ("Фигаро здесь, Фигаро там").
В него, по ходу исполнения ПП динамической индикации, будут записываться константы различного функционального предназначения.
И еще один новый "прибамбас": названия также можно присвоить и константам. Собственно, объяснять тут особо и нечего (см. "шапку").
237
Переходим к рабочей части программы.
После отработки ПП TABLE, возврат из нее происходит на первую команду группы команд установки запятой movwf Temp.
Вэтой группе команд, можно выставить десятичную запятую в любом знакоместе линейки, что есть "привязка" к единице измерения (например, гц, Кгц, Мгц ...).
Предположим, что запятую нужно выставить в 5-м знакоместе.
Чтобы не было путаницы, обращаю Ваше внимание на то, что в данном случае, речь идет о нумерации от 0 до 7.
Если "привязаться" к "обывательской" нумерации (от 1 до 8), то это будет соответствовать 6-му знакоместу.
Анализируем то, что мы имеем после возврата из ПП TABLE.
После этого возврата, в зависимости от того, какое из 8-ми малых колец индикации отрабатывается, в регистре W, будет записано какое-либо одно из 10-ти двоичных чисел (не забывайте, что ПИК работает только с двоичными числами) результата кодировки (или перекодировки, что по сути, одно и то же).
Напоминаю, что такая разновидность двоичных чисел позволяет отобразить, в одном из активированных знакомест, один из символов цифр (от 0 до 9).
Если речь идет о 5-м знакоместе, то на 5-м "витке" малого кольца индикации, необходимо изменить кодировку таким образом, чтобы не воздействуя на секторы 7-сегментного индикатора с названиями A, B, C, D, E, F, G (иначе будет индицироваться не то, что нужно), "выставить" единицу в секторе H ("загорание" запятой).
Винтервале времени отработки остальных 7-ми "витков" малого кольца индикации, процедура установки запятой должна игнорироваться (обходиться).
То есть, имеет место быть 2 сценария исполнения программы.
Следовательно, должна быть применена команда ветвления, проверяющая состояния какого-то флага.
Речь идет о выборе одного-разъединственного числа (из группы чисел) и "привязке", к этому числу, одного из 2-х сценариев работы программы.
Первое, что приходит на ум, - задействование флага нулевого результата Z.
Его состояния должны анализироваться с помощью байт-ориентированных команд btfsc или btfss.
Если задействуется флаг Z, то есть, осуществляется "привязка" к нулевому или ненулевому результату исполнения некой команды, влияющей на состояние этого флага, то одним из результатов исполнения этой команды должен быть ноль.
При "разборках" с флагом Z, мы это уже проходили (команда subwf).
После возврата по стеку, нужно скопировать содержимое регистра W в какой-нибудь регистр оперативной памяти.
Вданном случае, это регистр Temp (movwf Temp).
Необходимость этого сохранения обусловлена тем, что в дальнейшем, регистр W будет задействован, и если не принять мер по сохранению его содержимого, то оно, после записи "по верху", будет "потеряно".
Если содержимое регистра W сохранено в регистре Temp, то регистр W "высвобождается" и в него можно записать константу .05 (movlw 5), для последующего ее использования в операции вычитания.
Для разнообразия, в команде movlw 5, я указал числовое значение константы без атрибутов систем исчисления (о такой возможности говорилось ранее), но можно "настучать" и .05 или
05h, или b'00000101'.
Далее, командой bsf Status,Z флаг Z поднимается.
По большому счету, эта команда не нужна (Z – флаг 1-й группы), но я ее ввел в текст программы для удобства отслеживания работы процедуры в симуляторе (в обучающих целях).
При этом, я исходил из того, что 5-е знакоместо одно, а количество остальных знакомест – 7. Поэтому и поднял флаг Z.
Если эта команда Вам не нравится, то можете ее убрать.
После исполнения команды subwf Index,W, флаг Z будет либо опущен (если в регистре Index "лежит" одно из чисел .00, .01, .02, .03, .04, .06, .07), либо поднят (если в регистре Index "лежит" число .05).
Если флаг Z поднялся, то сначала исполнится "виртуальный" NOP, а затем будет исполнена команда bsf Temp,7.
238
Врегистре Temp, "лежит" результат перекодировки, в котором запятая программно "погашена" (бит №7 = 0).
Установка единицы в бите № 7 (bsf Temp,7), соответствует активации запятой ("загорится" сектор H 5-го знакоместа).
Так как для установки запятой применяется бит-ориентированная команда, то она не будет воздействовать на секторы A, B, C, D, E, F, G (воздействует только на сектор H).
После исполнения команды bsf Temp,7, рабочая точка программы переходит на метку
No_Dot.
Если флаг Z опущен, то с помощью команды goto No_Dot, рабочая точка программы переходит на метку No_Dot, "перескакивая" через команду bsf Temp,7 (это называется
обходом).
Вэтом случае, запятая не может быть выставлена.
Вконечном итоге, в 5-м знакоместе, запятая будет "высвечиваться" одновременно с
"высвечиванием" символа цифры, а в остальных знакоместах, сектор H будет "погашен", и на индикацию будут выводиться только символы цифр.
Вопрос: "Как изменить положение запятой"?
Ответ: очень просто. В команде movlw 5, пятерку нужно заменить на номер того знакоместа, в котором ее нужно выставить.
Всё. Запятая выставлена.
Переходим к исполнению группы команд вывода десятичной цифры (символа) на индикацию. Так же, как и "все пути ведут в Рим", оба сценария группы команд установки запятой "уперлись" в команду movf Temp,W.
Далее, movwf PortB подготовка к выводу символа на индикацию. "Подготовка" потому, что нужное знакоместо не активировано.
Значит, нужно озаботиться формированием адресного кода, который управляет внешним дешифратором.
Что и сделано: movf Index,W и movwf PortA.
После этого, символ "высветится" в нужном знакоместе, а проще говоря, он будет выведен на индикацию.
На всякий случай, "сделаю второй заход" (хуже от этого не будет).
В регистре Temp, находится двоичное число (результат кодировки), предназначенное для отображения в текущем знакоместе, в виде символа цифры.
После исполнения команды movf Temp,W, это число копируется в регистр W (сразу его скопировать в защелки порта В нельзя), а затем, из регистра W, в защелки (во все 8 штук)
порта В (movwf PortB).
Таким образом, на анодах светодиодов линейки, выставлен код одного из символов цифр
(0 ... 9).
Какое именно знакоместо будет активировано, зависит от того, каким будет числовое значение адресного кода, который управляет внешним дешифратором.
Числовое значение этого кода, в свою очередь, зависит от того, на каком именно, из 8-ми "витков" большого кольца индикации (одно большое кольцо индикации имеет в своем составе 8 малых колец индикации), находится рабочая точка программы.
Как раз этим "делом и занимается" группа команд формирования адресного кода. Задача сводится к выводу, в первые 3 защелки порта А, числа (.00 … .07), "лежащего" в регистре Index ("рулевой").
Для этого достаточно всего двух команд: movf Index,W и movwf PortA.
Естественно, что в этом случае, выводы порта А, управляющие внешним дешифратором, перед "влётом" в ПП динамической индикации, должны быть настроены на работу "на выход". После выхода рабочей точки программы из ПП динамической индикации, их можно перестраивать под решение других задач. Но только после этого выхода.
Направления работы остальных 2-х выводов порта А не важны (они не задействуются в ПП динамической индикации), но эти выводы могут быть как-то задействованы в "группах подпрограмм и команд, осуществляющих различные операции", что на практике и происходит.
Соответственно, направления работы этих 2-х выводов будут определяться тем, что происходит в этих "различных операциях".
Идем дальше.
После того, как адресный код управления дешифратором сформирован (активировалось одно из знакомест), рабочая точка программы устанавливается на первую команду группы
239