Поправлю немного, вы забыли счётчик обнулить после достижения 400, ну и главный цикл в основной программе не помешает.
Код
void timer1_ovf_isr(void)
{
counter++;
if (counter >= 400)
{
counter=0;
doSomeThing();
}
}
void main(void)
{
timer1_init();
asm("sei");
while(1);
}
Другой подход: что если подать на вход таймера1 частоту Fclk/1024, тогда для 16МГц клока переполнение наступит как раз через 4с, первое прерывание даст то, что надо, не надо будет ничего считать.
Фрагмент подпрограммы обработки прерываний переполнения таймера1 на ассемблере в предположении, что счётчик переполнений находится в (r25,r24). Счётчик работает на вычитание.
Код
subi r24,1
sbci r25,0
brne no4sec
ldi r24,low(400)
ldi r25,high(400)
rcall dosomething
no4sec:
reti
Само собой разумеется, что статус-регистр и все модифицируемые регистры надо сохранять при входе в прерывание и затем восстанавливать при выходе.
Поправил while(1) для удобства пользования.