org 0
; Вектор сбросаgoto MAIN
; Фоновая программаorg 4
;Вектор прерыванияgoto ISR
; ОбработчикMAIN clrwdt
; Сбрасываем сторожевой таймерbsf STATUS,RP0
; Переключаемся в 1-й банкmovlw b’00000001’
; Прерывание по спадающему фронту, внутр. такт, сигналmovwf OPTION_REG
; Предделитель — 1:4, подключен к Таймеру 0bcf STATUS,RP0
; Возвращаемся в 0-й банкclrf NEW
; Обнуляем флаг нового событияbsf NTCON,T0IE
; Разрешаем прерывание от Таймера 0bsf 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
; Сохраняем Wswapf STATUS,w;
и регистр STATUSmovwf _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
; Восстанавливаем регистр STATUSmovwf STATUS
swapf _work,f
; Восстанавливаем W,swapf _work,w
; не затрагивая STATUS,retfie
; и выходим из прерывания