У меня подобная ситуация возникала, когда я ошибся с регистром переполнения таймера (OCRn). В даташите приведена формула для опрделения частоты вызова прерываний таймера при использовании режима CTC:
})
где

- частота прерываний

- частота кварца

- величина прескаллера таймера. Может равняться (для ATmega16) 1, 8, 64, 256 или 1024
(Формула получена умножением на два формулы для вычисления частоты генерации сигнала, представленной в документации. Для контроллера ATmega16, документация doc2466, стр. 77)
Нужно использовать именно CTC режим - тогда удается довольно тонко подобрать делители частоты кварца. У меня обработка секундного интервала (при чтстоте кварца 16МГц) выглядит так:
Инициализация:
Код
TCCR0 = (1 << WGM01)|(1 << CS02); // CTC режим, преаскаллер 256
TCNT0 = 0;
OCR0 = 249;
TIMSK = (1 << OCIE0); // Включаем прерывание по сравнению
В результате, прерывание будет вызываться 250 раз в секунду. Обработка прерывания выглядит так:
Код
uint8_t t = 0, timer_flag = 0;
SIGNAL (SIG_OUTPUT_COMPARE0)
{
++t
if (t == 250)
{
t = 0;
// Этот флаг используется, как событие секундного таймера
timer_flag = 1;
}
}
В вашем случае (для частоты 4 МГц) нужно задать прескаллер таймера равным 64:
Код
TCCR0 = (1 << WGM01)|(1 << CS01)|(1 << CS00);
Замечу, что это не единственный и не лучший способ добиться секундного интервала на частоте 4МГц. В общем случае, делать такие настройки, чтобы вызовы прерываний таймера проиходили как можно реже. Для этого стоит прескаллер устанавливать в максимально возможное значение и далее подбирать границу переполнения, так чтобы частота делилась нацело.