Рассмотрим пример настройки прерывания таймера T1 с периодом 1 раз в 1 сек (1 Гц). на микроконтроллере Atmega8. Такая настройка может очень пригодиться при разработке девайсов отсчитывающих реальное время, например часов. Итак:
1. Выбраем и устанавливаем делитель в регистре TCCR1B (биты CS12,CS11,CS10). Делитель частоты следует выбирать таким образом, что бы частота кварца, на которой работает контроллер в Гц деленная на делитель было целым числом. Например для кварца 8мГц (8000000Гц) нужно выбрать делитель TCCR1B равный 256 (установиь биты CS12=1,CS11=0,CS10=0).
2. Делим основную частоту на делитель. Полученное значение нужно будет для корректировки регистра TCNT1 (см. п. 3): 8000000/256=31250.
3. Корректируем регистр TCNT1 для получения прерывания ровно 1 сек. T1 - 16 разрядный таймер - это 65535 тиков. Тогда регистр TCNT1 будет равен 65535-31250=34285
4. Незабываем корретировать TCNT1 в самом прерывании.
Код для WinAvr будет выглядеть следующим образом:
1. Выбраем и устанавливаем делитель в регистре TCCR1B (биты CS12,CS11,CS10). Делитель частоты следует выбирать таким образом, что бы частота кварца, на которой работает контроллер в Гц деленная на делитель было целым числом. Например для кварца 8мГц (8000000Гц) нужно выбрать делитель TCCR1B равный 256 (установиь биты CS12=1,CS11=0,CS10=0).
2. Делим основную частоту на делитель. Полученное значение нужно будет для корректировки регистра TCNT1 (см. п. 3): 8000000/256=31250.
3. Корректируем регистр TCNT1 для получения прерывания ровно 1 сек. T1 - 16 разрядный таймер - это 65535 тиков. Тогда регистр TCNT1 будет равен 65535-31250=34285
4. Незабываем корретировать TCNT1 в самом прерывании.
Код для WinAvr будет выглядеть следующим образом:
// Инициализация прерывания
void t1_init()
{
// Настраиваем делитель
TCCR1B = (1<<CS12)|(0<<CS11)|(0<<CS10);
// Выставляем значение TCNT1
// для коррекции счетчика, чтобы время было ровно 1 секунда
TCNT1 = 65535-31250;
// Разрешаем прерывание по переполнению таймера
TIMSK |= (1<<TOIE1);
// Выставляем бит общего разрешения прерываний
sei();
}
// Прерывание
ISR(TIMER1_OVF_vect)
{
// Выставляем значение TCNT1
// для коррекции счетчика, чтобы время было ровно 1 секунда
TCNT1 = 65535-31250;
// Что-то делаем каждую секунду
// ...
}