Файл: Самоучитель по программированию 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