The problem is that the timing behavior is totally wrong (factor 30).
I have an ATmega 644PA which is running with 8 Mhz (CKDIV8 fuse is not set).
I wanted an interrupt every 1 ms. I use Timer1 (16 bit timer) in the compare mode.
The prescaler was choiced by the timing range which i need.
Here 1 ms to ~2s. (limited through the 16 bit timer reg.)
Calculation
CPU: 8.000.000 Hz
Prescaler: 256
8.000.000 Hz / 256 = 31250 Cycles / s (Hz)
1000 ms = 31250 Cycles
1 ms = 30.25 Cycles (31.25 - 1, timer reg. start by 0)
From here i can calculate it up, for example:
100 ms = 3025 Cycles
2s = 60500 Cycles
Code
Timer Init
cli(); // disable global interrupts
TCCR1A = (1 << WGM01); // CTC ON
TCCR1B = 0x04; // Prescaler 256
OCR1A = 30; // set compare reg.
TIMSK1 = (1 << OCIE1A); // set interrupt mask
TCNT1 = 0x00; // set counter reg. to zero
sei(); // enable global interrupts
ISR:
ISR(TIMER1_COMPA_vect)
{
// start own code
...
// end own code
TCNT1 = 0x00; // reset counter reg. to zero after match (same which should CTC do)
}
Now i have for example a volatile variable which will be incremented in the ISR function.
I'm polling the variable and wait so long till it reach 60500, which is equal to 2s.
After it i just set an led on.
I measured it by phone and it takes 1 minute till the led goes on.
It takes to long with the factor 30 => 60s divided by 2s are 30.
I also tried to use an external program to calculate it, it came to the same results. (0x1E = 30)
Someone an idea where my mistake is ?
2 seconds is 60500 cycles. But your ISR is incrementing the volatile variable every 1 millisecond. Naturally, it will take 60.5 seconds for the variable to reach 60500.
As a side note, it is better to change the compare value, rather than reset TCNT, to avoid timing drift. That is, let the counter run freely, and use
OCR1A += 31;
to hit the next interrupt. Resetting TCNT as you do will ignore the time inside the ISR.