Сегодня мы рассмотрим работу прерывания которое будет срабатывать по счетчику. В качестве примера возьмем 16 битный счетчик ( 8 битные на много проще и на них мы не сможем реализовать длительные паузы между прерываниями).
Параметры счетчика:
Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1:
COM1A1, COM1A0, COM1B1, COM1B0 — настраивают поведение выводов OC1A и OC1B.
FOC1A, FOC1B — принудительное изменение состояния выходов OC1A и OC1B.
WGM11, WGM10 — настраивают TC1 для работы в режиме ШИМ.
Регистр TCCR1B служит для задания режимов работы таймера/счётчика 1:
CS10, CS11, CS12 — выбор частоты тактирования TC1.
Биты WGM13 (4) , WGM12 (3) регистра TCCR1B и биты WGM11 (1) , WGM10 (0) регистра TCCR1A устанавливают режим работы таймера/счетчика T1:
TCNTxH и TCNTxL — старший и младший счетный байт.
Необходимо учитывать, что записывать данные в счетный байт необходимо с старшего разряда, а потом младший. Менять последовательность нельзя.
В нашей программе, при переполнении счетчика будет отрабатывать прерывание, как следствие будут переключаться светодиоды на ножках D0 и D1.
И прежде чем приступить к написанию программы необходимо указать тип прерывания которое мы будем использовать, хи много, мы пока укажем то которое нам в данный момент нужно:TIMER1_COMPA_vect — прерывание по совпадению.
Программа:
#include <avr/io.h>
#include <avr/interrupt.h>
#define HL1_on PORTD|=(1<<PD0)
#define HL1_off PORTD&=~(1<<PD0)
#define HL2_on PORTD|=(1<<PD1)
#define HL2_off PORTD&=~(1<<PD1)
unsigned char i =0;
unsigned char n =0;
ISR (TIMER1_COMPA_vect){// прерывание по таймеру
i++;
if(i==1){
n=0;
}else{
n=1;
i=0;
}
}
int main(void) { /* Replace with your application code */
DDRD =0b0000011; //ножки D0-D1 выход
PORTD =0b1111100;// ножки D0-D1 – настроены на 0
TCCR1B |= (1<<WGM12); // устанавливаем режим СТС (сброс по совпадению)
TIMSK |= (1<<OCIE1A); //устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)
//62500
OCR1AH = 0b11110100; //записываем в регистр число для сравнения
OCR1AL = 0b00100100;
TCCR1B |= (1<<CS11)|(1<<CS10);//установим делитель. 80000000/64=125000кГц
//1/125000=8*10-7с * 62500 = 0,5с
sei();
while (1) {
if (n==0){HL1_on;HL2_off;}
if (n==1){HL2_on;HL1_off;}
}
}