- •Лабораторная работа ¹4. Система прерываний. Специальные режимы работы.
- •4.1. Теоретическая часть.
- •4.1.1. Система прерываний.
- •4.1.2. Специальные режимы работы.
- •Режимы с пониженным энергопотреблением.
- •4.2. Практическая часть.
- •4.2.1. Внешнее аппаратное прерывание irq.
- •4.2.2. Программное прерывание swi.
- •4.2.3. Аппаратное прерывание reset.
- •4.2.4. Режимы пониженного энергопотребления stop и wait.
- •4.3. Контрольные вопросы.
- •4.4. Задания.
4.2.2. Программное прерывание swi.
Как было отмечено выше, SWIявляется программным прерыванием и инициируется программистом, в отличие от других прерываний, генерируемых аппаратурой микроконтроллера.SWIявляется немаскируемым, то есть его нельзя программно запретить.
Для генерации этого прерывания используется команда ассемблера SWI, при выполнении которой происходит следующее:
1. инкрементируется счетчик команд PC, в стеке сохраняется сначала младший, затем старший байтыPC;
2. в стеке последовательно сохраняются регистры X,A,C;
3. в счетчик команд заносятся два байта, хранящихся по адресам $1FFC, $1FFD.
Таким образом, после выполнения команды SWIуказатель стека смещается на пять байт в сторону младших адресов, и управление передается по вектору, записанному в ячейках $1FFC, $1FFD.
В качестве примера использования команды SWIрассмотрим программу вычисления факториала. Программу организуем следующим образом:
·с адреса $200 запишем блок начальной инициализации ячеек памяти и вызова подпрограммы обработки прерывания;
·с адреса $300 будет находиться собственно подпрограмма обработки прерывания, вычисляющая факториал;
·по адресу $400 поместим вспомогательную подпрограмму умножения двух чисел.
?в ячейке $50 разместим аргумент, а в ячейку $51 будем записывать результат (то есть факториал от содержимого ячейки $50).
Рассмотрим программу вычисления 4!
Основная программа :
200 LDA #$4 Записываем аргумент
202 STA $50 в ячейку $50.
204 LDA #$1 Записываем 1
206 STA $51 в ячейку $51.
208 RSP Устанавливаем указатель стека в $FF.
209 SWI Генерируем вызов подпрограммы обработки прерывания.
20À LDA $51 Записываем результат вычислений в регистрÀ.
20Ñ BRA $20Ñ Организуем бесконечный цикл.
Подпрограмма обработки прерывания :
300 LDA $50 Сравниваем аргумент
302 CMP #$1 с единицей.
304 BEQ $30Ñ Если аргумент равен единице, то переходим на $30С (вычисления окончены),
306 JSR $400 иначе вызываем подпрограмму умножения.
309 DEC $50 Уменьшаем аргумент на единицу.
30Â SWI Вызываем подпрограмму вычисления факториала.
30Ñ RTI Возврат из подпрограммы.
Подпрограмма умножения двух чисел :
400 LDA $50 Перемножаем два числа,
402 LDX $51 находящихся в ячейках $50 и $51
404 MUL Умножение
405 STA $51 Запоминаем результат.
407 RTS Возврат из подпрограммы.
Следующие несколько замечаний поясняют работу программы:
·при выполнении командыSWI, расположенной по адресу $209, в стеке сохраняются значения регистровPC,X,A,C, указатель стекаSPсмещается на 5 байт вниз, то есть в сторону младших адресов и управление передается по адресу, записанному в ячейках $1FFC (старший байт) и $1FFD (младший байт), где находится вектор программного прерывания (в данном случае - $300);
·поскольку вычисляется факториал с использованием рекурсии, то подпрограмма обработки прерывания будет иметь следующую структуру:
1. проверка условия завершения вычислений, возврат из подпрограммы в случае его истинности;
2. уменьшение аргумента на единицу и вложенный вызов этой же подпрограммы;
·при выполнении командыSWI, расположенной по адресу $30В, происходит вызов подпрограммы вычисления факториала от числа, на единицу меньшего, чем то, что хранится в ячейке $50; при этом регистры опять сохраняются в стеке, указатель стека смещается на 5 байт в сторону младших адресов, и управление передается по адресу, хранящемуся в ячейках $1FFC, $1FFD;
·задача вспомогательной подпрограммы умножения чисел - перемножить два числа, хранящихся в ячейках $50, $51 и поместить младший байт результата в ячейку $51;
Для правильной работы программы необходимо занести адрес подпрограммы обработки прерывания в ячейки $1FFC, $1FFD ($03 в $1FFC и $00 в $1FFD) и поставить точку останова по адресу $20C.
Запустите программу с адреса $200. На экране появится содержимое регистров микроконтроллера, причем регистр Aбудет содержать результат работы программы: число $18 (в десятичной системе счисления оно равно 24). Можно убедиться, что в ячейке $51 находится то же самое число.
Выведите на экран содержимое стека с адреса $C0 по адрес $FF. Напомним, что стек начинается с ячейки $FF и по мере заполнения растет вниз - в сторону младших адресов. Начиная с адреса $FF и ниже расположены 30 байт, которые были использованы программой в процессе работы. Каждый раз при выполнении команды SWIзанимаются очередные свободные пять ячеек памяти в стеке, а при выполнении командыRTIиз последних пяти использованных ячеек считываются значения регистров и указатель стека увеличивается на 5 байт, то есть занятая часть стека становится короче. После завершения работы программы стек полностью освобождается, указатель стека принимает то значение, которое он имел до запуска программы, но вся информация, сохраненная в свое время в стеке, остается. Убедитесь в этом.
При написании и отладке программ следует иметь ввиду, что стек может занимать максимум 64 байта (адреса $C0...$FF). Если происходит переполнение, то указатель стека циклически смещается на начало , что приводит к потере данных. Из вышесказанного следует, что для приведенного примера максимальное значение аргумента не должно превышать значения 10, в этом случае стек заполнится целиком. Однако, поскольку под результат отведен лишь один байт, то программа перестанет правильно работать уже при значении аргумента, равном 6. Избежать этого можно, предусмотрев в подпрограмме умножения чисел сохранение двухбайтного результата.