Осталось упомянуть о двух специальных командах - CLRWDT и SLEEP.
Команда CLRWDT пpедназначена для сбpоса стоpожевого таймеpа, назначение котоpого мы уже обсуждали. Эта команда должна пpисутствовать в таких участках пpогpаммы, чтобы вpемя выполнения пpогpаммы между двумя соседними командами CLRWDT не пpевышало вpемени сpабатывания стоpожевого таймеpа. Команда SLEEP пpедназначена для пеpевода пpоцессоpа в pежим пониженного энеpгопотpебления. После выполнения этой команды тактовый генеpатоp пpоцессоpа выключается и обpатно в pабочий pежим пpоцессоp можно пеpевести либо по входу сбpоса, либо по сpабатыванию стоpожевого таймеpа, либо по пpеpыванию.
Система команд приведена в сводной таблице 4 Приложения 2. Большинство команд выполняется за 1 цикл (4 такта, 200 нс при F=20 МГц). Команды байтовой обработки включают обычный набор арифметических, логических и сдвиговых операций. При наличии двух операндов один из них всегда находится в аккумуляторе W.
Для организации циклов и условных переходов в программе используются команды пропуска DECFSZ, INCFSZ, BTFSC, BTFSS, которые в случае выполнения заданного условия пропускают следующую команду - увеличивают счетчик команд PC сразу на 2.
|
|
При переходах по команде GOTO 11-битовый адрес перехода из кода команды загружается в разряды PC.10-0, а два старших разряда берутся из 5-битового регистра PCLATH (PC.12-11 = PCLATH.4-3), т.е. без переустановки PCLATH переход возможен в пределах 2 Кслов. Аналогично формируется адрес перехода командой CALL, однако она предварительно спасает в стеке содержимое РС. Аппаратный стек глубиной 8 слов пользователю недоступен, загрузка РС из стека производится командами RETURN, RETFIE, RETLW, причем последняя команда перед возвратом загружает в W константу и используется для организации постоянных таблиц. Формирование признаков отмечено в последней графе табл.4, сами признаки фиксируются в младших разрядах регистра STATUS (табл.3).
При записи программ на Ассемблере имя команды можно указывать заглавными или прописными буквами, в имени переменных эти буквы имеют различные значения. Целые числа можно задавать в двоичном, десятичном или 16-ричном формате в следующей форме:
MOVLW b'10100110'; двоичное число
MOVLW d'166'; десятичное число
MOVLW 0A6; шестнадцатиричное число
Далее в основном используется 16-ричная форма представления чисел.
В обычном тексте и поле комментария мы будем использовать запись типа A6,однако на Ассемблере следует записывать 0A6, т.к. 16-ричное число должно начинаться с цифры.
Для большинства команд байтовой обработки возможны 2 варианта, например:
ADDWF Adr1,w; W=W+(Adr1)
ADDWF Adr1,f; (Adr1)=W+(Adr1)
В первом случае бит d в коде команды равен 0 и сумма остается в аккумуляторе W, во втором случае d=1 и сумма остается в ячейке с адресом Adr1.
|
|
Адрес Adr1 может быть определен в начале программы как 8-разрядный, однако в код команды транслятор помещает только 7 младших разрядов, а старший разряд адреса выбирается из 5 бита регистра STATUS (это бит регистрового банка RP0). Если Adr1=20, то при RP0=0 полный адрес будет 20, а при RP0=1 полный адрес составит A0.
Необходимость переключения регистрового банка RP0 создает определенные неудобства при составлении программ. Их можно избежать при использовании косвенной адресации, если предварительно загрузить 8-разрядный адрес в регистр косвенной адресации FSR.
MOVLW Adr1; W=Adr1
MOVWF FSR; (FSR)=W
ADDWF INDF,f; ((FSR))=((FSR))+W
Нулевой адрес INDF в коде команды инициирует выборку полного 8-разрядного адреса из регистра FSR, т.е. последняя команда всегда работает с полным адресом 20. Косвенную адресацию обычно используют при необходимости модификации адреса в программе, для чего достаточно изменить содержимое FSR.
При выполнении работы необходимо для заданного варианта программы
указать в поле комментария динамику изменения содержимого аккумулятора W и ячеек 20,21,22,23. В качестве примера рассмотрим следующий вариант программы.
----------------------------------------------------------------------
Title "Lab1.asm"
;
list p=16c74; processor type
errorlevel 1, -(305)
;
#include "p16c74.inc"
;
Buf1 equ 20
Cnt equ 23
RxBuf equ 24
org 0; стартовый переход
movlw 0
movwf PCLATH
goto Start
org 100; программа пользователя
Start; начальная установка
call ConstInit
Priem caLL Receiv
movlw 2
xorwf PORTA,f
movlw 3
movwf Cnt
movlw Buf1
movwf FSR
bsf STATUS,C
movf RxBuf,w
; if (RfBuf)=21
; W 20 W 20 21 W 20 21 22 23
Beg1 movwf INDF; 21 21 43 67 43 86 67 CF 86
rlf INDF,w; 43 21 86 67 43 0C 67 CF 86
addwf INDF,f; 43 64 86 67 C9 0C 67 CF 92
iorwf INDF,f; 43 67 86 67 CF 0C 67 CF 9E
incf FSR,f
decfsz Cnt,f
End1 goto Beg1
; W 20 21 22 23
movwf INDF; 0C 67 CF 9E 0C
incf FSR,f
movf STATUS,w
movwf INDF
movlw 5
movwf Cnt
movlw Buf1
movwf FSR
Tra movf INDF,w
call Transm
incf FSR,f
decfsz Cnt,f
goto Tra
goto Priem
ConstInit
bsf STATUS,RP0
bcf TRISA,1; диод
movlw b'10000011'
movwf OPTION_REG
movlw d'129'
movwf SPBRG
movlw b'00100100'
movwf TXSTA
bcf STATUS,RP0
clrf INTCON
clrf PORTC
movlw b'10010000'
movwf RCSTA
return
Receiv; прием байта в RxBuf
RecA btfss PIR1,RCIF; check for received data
goto RecA
RecB movf RCREG,w
movwf RxBuf
return
Transm; выдача байта из W
movwf TXREG; transmit byte to PC
bcf PIR1,TXIF
tr3 btfss PIR1,TXIF
goto tr3
return
end
----------------------------------------------------------------------
В начале программы определяются значения используемых переменных, т.е. задается распределение оперативной памяти. Оператор ORG фиксирует начальный адрес размещения кодов программы в постоянной памяти.
Как упоминалось ранее, загрузочный модуль передает управление на метку Start и подпрограмма ConstInit выполняет настройку асинхронного канала на скорость 9600 бод. На метке Priem программа ожидает прихода байта из ПЭВМ. Принятый подпрограммой Receiv байт записывается в ячейку RxBuf, переключается светодиод командой XORWF PORTA,f и начальный адрес Buf1 загружается в регистр FSR. Устанавливается бит переноса С в регистре STATUS и в счетчик цикла Cnt загружается число 3. Эта часть программы идентична для всех вариантов.
С метки Beg1 начинается конкретный вариант программы. В аккумулятор W загружается начальное значение и цикл из нескольких команд повторяется 3 раза. Содержимое аккумулятора W и ячеек ОЗУ при каждом проходе цикла следует указать в поле комментария. В цикле выполняются сдвиги, арифметические и логические команды. Следует учитывать, что бит переноса формируется арифметическими командами и включается в кольцо сдвига при выполнении команд RLF, RRF.
После выхода из цикла содержимое W и регистра STATUS записывается в ячейки 23, 24 и в поле комментария отмечаются заключительные значения всех переменных. Далее для контроля эти значения в цикле Tra передаются в ПЭВМ по последовательному каналу и отражаются на экране дисплея. Управление возвращается на метку Priem.
В заключение остановимся несколько подробнее на используемых подпрограммах. Для загрузки регистров SPBRG и TXSTA в подпрограмме Init сначала устанавливается первый регистровый банк. В регистре TXSTA
|
|
задается 8-битовый формат, разрешение выдачи, асинхронный режим и повышенная скорость (см. табл.3). При частоте кварца 20 МГц и повышенной скорости загрузка десятичного числа d'129' в регистр SPBRG обеспечивает асинхронную передачу со скоростью 9600 бод. Затем устанавливается нулевой регистровый банк и в регистре RCSTA задается разрешение приема и 8-битовый формат. Сброс регистра INTCON запрещает прерывания.
Прием байта подпрограммой Receiv начинается с цикла ожидания готовности на метке RecA до установки флага готовности RCIF в регистре PIR1.Затем байт переписывается из буфера приема RCREG в ячейку RxBuf. При выдаче байта подпрограммой Transm он сначала загружается в буфер выдачи TXREG, затем сбрасывается флаг выдачи TXIF и программа входит в цикл ожидания Tr3 до установки флага TXIF после окончания выдачи байта из буфера TXREG.