Как бы это ни казалось странным, но если вывод ССР сконфигурировать как выход, то захват состояния таймера можно будет осуществлять, программно изменяя состояние данного вывода. Эта особенность позволяет использовать модуль ССР для определения длительности какого-либо внутреннего события или же для «хитрого» одновременного считывания обоих байтов таймера. Позже результат можно будет считать из регистров модуля безо всяких проблем, связанных с раздельным чтением двух регистров.
В качестве примера воспользуемся модулем ССР для измерения периода сигнала кардиограммы, подключив пиковый детектор, показанный на Рис. 7.1 (стр. 208), к выводу ССР1. Предполагая, что Таймер 1 работает в синхронном режиме от собственного кварцевого резонатора частотой 32.768 кГц, инициализационная часть программы может выглядеть следующим образом:
movlw b’00001011’; Таймер включен, внешний такт, сигнал, синхр. режим
movwf T1CON; Генератор включен, предделитель — 1:1
movlw b’00000100’; Режим захвата по спадающему фронту
movwf CCP1CON
clrf NEW; Обнуляем флаг NEW
clrf TMR1H; Обнуляем Таймер 1
clrf TMR1H
bsf STATUS,RP0; Переключаемся в 1-й банк
bsf PIE1,CCP1IE; Разрешаем прерывание от ССР1
bcf STATUS,RP0; Возвращаемся в 0-й банк
bcf PIR1,CCP1IF; Сбрасываем флаг прерывания
bsf INTCON,PEIE; Разрешаем прерывания от периферийных устройств
bsf INTCON,GIE; Разрешаем работу системы прерываний
В обработчике прерывания просто считывается содержимое регистра ССР, которое затем сохраняется в двух временных регистрах. Затем в регистр NEW заносится ненулевое значение, извещающее фоновую программу о наличии нового значения. После этого Таймер 1 сбрасывается для регистрации следующего события.
При использовании резонатора частотой 32.768 кГц и отключенном предделителе разрешающая способность считываемого значения составит 30.5 мкс. Переполнение Таймера 1 при таких параметрах конфигурации будет происходить каждые 2 с, и этого достаточно для регистрации сердечного ритма частотой до 30 ударов в минуту (см. Программу 13.4).
; **************
; Сначала сохраняем контекст обычным образом
ISR movwf _work; Сохраняем W
swapf STATUS,w; и регистр STATUS
movwf _status
; ===========
; Основной код
btfss PIR1,CCP1IF; Было прерывание от CCP1?
goto ISR_EXIT; ЕСЛИ нет, ТО ложная тревога
incf NEW, f; Сообщаем о новом захвате
bcf PIR1,CCP1IF; Сбрасываем флаг прерывания
movf CCPR1L,w; Считываем младший байт
movwf TEMP+1; Запоминаем его
movf CCPR1H,W; Считываем старший байт
movwf TEMP; Запоминаем его
clrf TMR1L; Обнуляем Таймер 1
clrf TMR1H
; ============
ISR_EXIT swapf _status,w; Восстанавливаем регистр STATUS
movwf STATUS
swapf _work,f; Восстанавливаем регистр W,
swapf _work,w; не затрагивая регистр STATUS,
retfie ; и выходим из прерывания
В системах с повышенной надежностью также может быть разрешено прерывание по переполнению Таймера 1. Возникновение этого прерывания означает, что последующее захваченные данные будут некорректны, хотя можно подсчитать количество таких тайм-аутов и таким образом увеличить длительность определяемого интервала. Однако в нашей системе это прерывание было бы логичнее использовать для включения сигнала тревоги!
Режимы 1000…1011, указанные на Рис. 13.7, соответствуют четырем
Помимо установки флага CCP1IF при наступлении события «совпадение» может выполняться одно из четырех действий, определяемое состоянием битов ССР1М[3:0]: