Рис. 2. Временная диаграмма циклов выполнения команд
2.2.Создание подпрограммы задержки
2.2.1.Тестовый пример
Вкачестве тестового примера рассмотрим простейшую программу, которая с частотой 1 Гц будет переключать выходную линию из логического нуля в логическую единицу. Алгоритм ее работы получится следующий. По включению контроллера программа выставит единицу на выходную линию, затем подождет 0,5 с, выставит нуль, опять подождет 0,5 с, а затем повторит все заново. Программа написана для микроконтроллера PIC16С84. Используемый генератор работает с частотой 32768 Гц. Изменяться будет состояние регистра ли-
нии RB0.
Программа начинается с секции заголовка, в которой при помощи директивы EQU осуществляется сопоставление символьного имени с его числовым значением. Отличие этого примера от предыдущего заключается в том, что в нем не производится описание регистров специального назначения. Так как в MPLAB уже включены файлы с описаниями этих регистров для каждой разновидности PIC контроллера. Эти файлы необходимо только подключить к основной программе директивой #include.
Кроме регистров специального назначения в программе используются и регистры общего назначения. Они описываются самостоятельно. Это можно делать как в предшествующем примере посред-
5
ством директивы EQU, присвоив каждому символьному названию свой адрес. Однако это несколько громоздко. Проще воспользоваться директивами cblock и endc. Эти директивы позволяют задать один начальный адрес, а ассемблер сам присвоит числовые значения заданным именам по возрастанию.
Так в примере используются два регистра – счетчика времени при формировании задержки на 0,5 с, имеющих название CounterLo и CounterHi.
Таким образом, программа будет иметь следующий вид:
#include p16С84a.inc |
;Подключение файла с описаниями |
|
;регистров специального назначения |
;Определение используемых в программе регистров |
|
;общего назначения: |
|
cblock 0x0C |
|
CounterLo |
;младший байт счетчика в подпрограмме |
|
;задержки |
CounterHi |
;старший байт счетчика в подпрограмме |
|
;задержки |
endc |
|
0x0C – это адрес нулевой ячейки регистров общего назначения. После ассемблирования строке CounterLo будет присвоен адрес 0x0C,
а строке CounterHi – адрес 0x0D.
Следующие строки посредством той же директивы EQU задают константы, используемые в примере.
INIT_PORTA |
EQU |
b'00000000' |
INIT_PORTB |
EQU |
b'00000000' |
INIT_OPTION |
EQU |
b'00000000' |
INIT_INTCON |
EQU |
b'00000000' |
DELAYLO EQU |
.79 |
|
DELAYHI EQU |
.21 |
|
Первые четыре константы будут использоваться при инициализации соответствующих регистров. Так как они предназначены для инициализации отдельных битов, то их удобно задавать в двоичном формате в виде b’x… x’. Следующие две – в подпрограмме задержки.
6
Они заданы в десятичном формате, который обозначается точкой. Если вместо «.21» написать «21», то ассемблер воспримет это как шестнадцатеричный формат, который установлен по умолчанию.
За секцией заголовка следует рабочая секция, в которой располагаются подпрограммы инициализации, формирования задержки, а также основное тело программы.
Подпрограмма инициализации имеет следующий вид:
Init |
|
bsf |
STATUS,RP0 |
movlw |
INIT_PORTA |
movwf |
TRISA |
movlw |
INIT_PORTB |
movwf |
TRISB |
movlw |
INIT_OPTION |
movwf |
OPTION_REG |
bcf |
STATUS,RP0 |
movlw |
INIT_INTCON |
movwf |
INTCON |
clrf |
STATUS |
Return |
|
При входе в подпрограмму производится выбор первого банка данных ОЗУ установкой бита RP0. Далее производится выбор направления линий ввода/вывода. Так как у контроллера задействована всего одна линия на выход, то во все регистры TRIS записываются нули, то есть линии будут выходами. Далее в регистры OPTION и INTCON записываются нули, так как таймер, сторожевой таймер и прерывания в программе не используются. После этого производится обнуление всех битов регистра STATUS, что вызывает переключение на нулевой банк ОЗУ.
Следующая подпрограмма реализует задержку, о которой говорилось выше.
Delay05 |
|
;Инициализация регистров счетчика: |
movlw |
DELAYLO |
;Младший байт |
movwf |
CounterLo |
; |
7
movlw |
DELAYHI |
;Старший байт |
movwf |
CounterHi |
; |
Del05 |
|
|
decfsz |
CounterLo,1 |
;Декремент младшего байта счетчика. |
|
|
;Выполняется до тех пор, |
goto |
Del05 |
;пока он не станет равным нулю, после |
|
|
;чего декрементируется |
decfsz |
CounterHi,1 |
;старший байт |
goto |
Del05 |
; |
Return |
|
;После того как оба байта станут |
|
|
;равными нулю, выход. |
Работа подпрограммы начинается с инициализации двух ранее определенных регистров общего назначения, которые будут использованы в качестве младшего и старшего байтов счетчика. Команда movlw DELAYLO записывает в регистр W константу DELAYLO. Затем из него значение передается в регистр CounterLo. Аналогичные действия производятся с константой DELAYHI и регистром CounterHi. После того как были заданы начальные значения младшего и старшего байтов счетчика, посредством декремента регистра CounterLo и CounterHi формируется задержка. Сначала производится декремент регистра CounterLo до тех пор, пока он не станет равным нулю, после чего команда goto Del05 пропускается и декрементируется старший байт счетчика CounterHi. После этого программа переходит на метку Del05 и цикл повторяется.
Примечание. После того как регистр CounterLo обнулится в результате следующего декремента, его значение станет равным 255. И подпрограмма будет выполняться в той же последовательности.
Когда оба байта станут равными нулю, произойдет возврат в основное тело программы.
Begin |
|
call |
Init |
bsf |
PORTB,0 |
call |
Delay05 |
bcf |
PORTB,0 |
cal |
Delay05 |
goto |
Begin |
End |
|
8
Ниже приведен полный листинг тестового примера:
#include p16f84a.inc ;Подключение файла с описаниями ;регистров специального назначения
;Определение используемых в программе регистров общего ;назначения:
cblock 0x0C
CounterLo ;младший байт счетчика в подпрограмме ;(ПП) задержки
CounterHi ;старший байт счетчика в ПП задержки endc
;Константы инициализации регистров специального назначения:
INIT_PORTA |
EQU |
b'00000000' |
;Все линии на выход |
INIT_PORTB |
EQU |
b'00000000' |
;Все линии на выход |
INIT_OPTION |
EQU |
b'00000000' |
;Константа для |
;инициализации регистра OPTION. |
|
||
;Т. к. таймер, сторожевой таймер не используются, то в него |
|||
;можно просто записать 0 |
|
||
INIT_INTCON |
EQU |
b'00000000' |
;Прерывания запрещены |
;Константы для ПП задержки на 0,5 с: |
|||
DELAYLO |
EQU |
.79 |
; |
DELAYHI |
EQU |
.6 |
; |
;Далее начинается исполняемый код программы: |
|||
|
goto |
Begin |
;Переход на начало |
int_point |
org |
0x04 |
;Вектор прерывания |
;ПП задержки на 0,5 с.
Delay05
;Инициализация регистров счетчика:
movlw DELAYLO ;Младший байт movwf CounterLo ;
9