В данном уроке мы с Вами настроим прерывание которое будет запускаться от таймера. Для начала рассмотрим таймера микроконтроллера PIC16F873A.
Timer0 – таймер/счетчик, имеет следующие особенности:
• 8-разрядный таймер/счетчик (считает до FFh);
• Возможность чтения и записи текущего значения счетчика;
• Внутренний или внешний источник тактового сигнала;
• Выбор активного фронта внешнего тактового сигнала (переход с 0 в 1 или с 1 в 0);
• Прерывания при переполнении (переход от FFh к 00h)
Timer1 – 16-разрядный таймер/счетчик, состоящий из двух 8-разрядных регистров (TMR1H и TMR1L) доступных для чтения и записи. Счет выполняется в спаренных регистрах (TMR1H : TMR1L), инкрементируя их значение от 0000h до FFFFh, далее считает с 0000h. При переполнении (переход от FFFFh к 0000h))счетчика устанавливается в ‘1’ флаг прерывания TMR1IF в регистре PIR1. Само прерывание можно разрешить/запретить установкой/сбросом бита TMR1IE в регистре PIE1.
TMR1 может работать в двух режимах:
• Режим таймера;
• Режим счетчика.
Timer2 – 8-разрядный таймер с программируемыми претделителем и выходным делителем, 8-разрядным регистром периода PR2. TMR2 может быть опорным таймером для CCP модуля в ШИМ режиме. Регистры TMR2 доступны для записи/чтения и очищаются при любом виде сброса.
Работать в данном уроке мы будем с Timer0.
Работа Timer0:
При установке бита T0CS в ‘0’ (OPTION_REG), Timer0 работает от внутреннего тактового сигнала. Увеличение значения счетчика происходит в каждом машинном цикле (если претделитель отключен).
При записи данных в счетчик во время работы программы увеличение значения счетчика запрещено два следующих цикла. В критических программах это надо учитывать, в мигании светодиодом — можно проигнорировать.
Если бит T0CS установлен в ‘1’ (OPTION_REG), TMR0 работает от внешнего источника тактового сигнала который подключен к входу RA4/T0CKI. Активный фронт внешнего тактового сигнала выбирается битом T0SE в регистре OPTION_REG:
При TOSE = 0 активный будет передний фронт сигнала.
При TOSE = 1 активный будет задний фронт сигнала.
Претделитель может быть включен перед WDT или Timer1, в зависимости от состояния бита PSA (OPTION_REG). Нельзя прочитать или записать новое значение в претделитель во время работы программы.
Прерывания от TMR0 возникают при переполнении счетчика, т.е. при переходе его значения от FFh к 00h. При возникновении прерывания бит T0IF(INTCON) устанавливается в 1. Само прерывание может быть разрешено/запрещено установкой/сбросом бита T0IE (INTCON). Флаг прерывания от TMR0 T0IF (INTCON)должен быть сброшен в подпрограмме обработки прерываний. В SLEEP режиме микроконтроллера модуль TMR0 выключен и не может генерировать прерывания.
Биты управления T0CS, T0SE, PS2, PS1, PS0, PSA расположены в регистре OPTION_REG
Если претделитель не используется, внешний тактовый сигнал поступает непосредственно на синхронизатор.
Синхронизация T0CKI с таковым сигналом микроконтроллера усложняется из-за опроса выхода синхронизатора в машинные циклы Q2 и Q4. Поэтому длительность высокого или низкого логического уровня внешнего сигнала должна быть не меньше 2TOSC (плюс небольшая задержка внутренней RC цепи 20нс).
8-разрядный счетчик может работать как претделитель Timer0 или выходной делитель WDT. Для простоты описания этот счетчик всегда будем называть «претделитель». Обратите внимание, что существует только один претделитель, который может быть включен перед Timer0 или WDT. Использование претделителя пред TMR0 означает, что WDT работает без претделителя, и наоборот.
Коэффициент деления претделителя определяется битами PSA и PS2:PS0 в регистре OPTION_REG.
Если претделитель включен перед TMR0, любые команды записи в Timer0 (например, CLRF 1, MOVWF 1, BSF 1, т.д.) сбрасывают претделитель. Когда претделитель подключен к WDT, команда CLRWDT сбросит претделитель вместе с WDT. Претделитель также очищается при сбросе микроконтроллера. Претделитель недоступен для чтения/записи. Так же запись в регистр TMR0 сбросит претделитель, если он подключен к Timer0, но не изменит его режима работы.
Регистр OPTION_REG (адрес 81h или 181h):
Регистр INCON():
Для того, что бы поморгать светодиодами используя прерывания от TIMER0, напишем программу, при этом у нас будет два светодиода подключенных к ножкам RB2 и RB3:
*****
схема
****
Программный код:
#define _XTAL_FREQ 8000000
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <pic16f873A.h>
#include <xc.h>
int count=0;
int k=0;
void __interrupt() timer(){
if(TMR0IE&&TMR0IF){
if(count==0){
PORTB = 0b00100000;
}
if(count==5){
PORTB = 0b00010000;
}
count++;
if (count>10)
{count=0;}
T0IF=0;
}
}
void main(void) {
TRISB = 0x00;//otput
PORTB = 0xFF;//output all
OPTION_REG=0b00000111; //Prescaler 256
INTCON=0xA0;
TMR0 = 0;
while(1){
}
}