org 0; Вектор сброса
goto MAIN; Фоновая программа
org 4;Вектор прерывания
goto ISR; Обработчик
MAIN clrwdt; Сбрасываем сторожевой таймер
bsf STATUS,RP0; Переключаемся в 1-й банк
movlw b’00000001’; Прерывание по спадающему фронту, внутр. такт, сигнал
movwf OPTION_REG; Предделитель — 1:4, подключен к Таймеру 0
bcf STATUS,RP0; Возвращаемся в 0-й банк
clrf NEW; Обнуляем флаг нового события
bsf NTCON,T0IE; Разрешаем прерывание от Таймера 0
bsf INTCON,INTE; Разрешаем внешнее прерывание
bsf INTCON,GIE; Разрешаем работу системы прерываний
clrf TMR0; Сбрасываем таймер
clrf COUNT; Обнуляем счетчик тиков
clrf COUNT+1
Помимо разрешения прерывания от Таймера 0, устанавливается также флаг INTE для разрешения внешнего прерывания с вывода INT, на который подается сигнал с пикового детектора. При этом нам не требуется обнулять ни Таймер 0, ни 2-байтный счетчик тиков, поскольку первый отсчет из серии всегда будет неверным — ведь сердцебиение пациента не синхронизировано со сбросом микроконтроллера! Однако регистр NEW, в который заносится ненулевое значение при каждом обнаружении импульса ЭКГ, сбрасывается.
Основное ядро обработчика прерывания, код которого приведен в Программе 13.2, выполняет следующие действия:
1. По прерыванию от Таймера 0:
• инкрементирует 2-байтный счетчик тиков;
• сбрасывает флаг прерывания от таймера T0IF;
• выходит из прерывания.
2. По внешнему прерыванию от пикового детектора:
• копирует содержимое счетчика тиков в РОНы;
• обнуляет Таймер 0;
• устанавливает флаг NEW;
• сбрасывает флаг внешнего прерывания;
• выходит из прерывания.
; *******************
; * По прерыванию от Таймера 0 в обработчике инкрементируется *
; * 2-байтный счетчик COUNT *
; * По внешнему прерыванию COUNT:2 копируется в DATA:2 *
; * и устанавливается флаг NEW, извещающий фоновую программу *
; * о готовности новых данных *
; ********************
; Сначала сохраним контекст
ISR movwf _work; Сохраняем W
swapf STATUS,w; и регистр STATUS
movwf _status
; ********************
; Основной код
btfss INTCON,T0IF; Сердечный импульс?
goto HEART_BEAT; ЕСЛИ да, TO обрабатываем его
incf COUNT+1,f; Регистрируем очередной 1-мс тик
btfsc STATUS,Z; ЕСЛИ перешли через ноль,
incf COUNT,f; ТО инкрементируем старший байт
bcf INTCON,T0IF; Сбрасываем флаг прерывания
goto ISR_EXIT
HEART_BEAT; Сюда попадаем при обнаружении импульса ЭКГ
movf COUNT+1,w; Берем младший байт периода
movwf DATUM+1; Копируем в пользовательский регистр
movf COUNT,w; Берем старший байт периода
movwf DATUM
clrf COUNT+1; Обнуляем счетчик тиков
clrf COUNT
btfsc INTCON,INTF; Сбрасываем флаг прерывания
incf NEW,f; Сообщаем о наличии новых данных
; ********************
ISR_EXIT swapf _status,w; Восстанавливаем регистр STATUS
movwf STATUS
swapf _work,f; Восстанавливаем W,
swapf _work,w; не затрагивая STATUS,
retfie; и выходим из прерывания