Why is this interrupt 2x too slow?

For many months I have been using software timers which were running 2x too fast without me knowing it.

I followed an instructable to set up the registers and according to the calculations the ISR should be running @ 1kHz but somehow it is running @2kHz

void initTimers()
{
    TCCR2B = 0;// same for TCCR2B
    TCNT2  = 0;//initialize counter value to 0
    // set compare match register for 1khz increments
    OCR2A = 249;// = (16*10^6) / (1000*64) - 1 (must be <256)
    // turn on CTC mode
    TCCR2A |= (1 << WGM21);
    // Set CS21and and CS20 bit for 64 prescaler
    TCCR2B |= (1 << CS20);
    TCCR2B |= (1 << CS21); 
    TCCR2B &= ~(1 << CS22); 
    // enable timer compare interrupt
    TIMSK2 |= (1 << OCIE2A);
}

This formula should work, but it does not.
compare match register = (1610^6) / (100064) - 1 = 249

I am using an arduino Nano with the old bootloader and it is running @16MHz.

Meanwell I managed to fix the frequency this by taking a 256 prescaler and a compare match register of:
reg = (1610^6) / (1000256) - 1 = 61.5 (I used 61) because of that 0.5 it is not exactly 1kHz but I can live with it.

However I really like to know why the first ISR settings are not working for me? I ran the math five times but I am not seeing what I did wrong here.

Kind regards,

Bas

Also my ISR is written as follows

ISR(TIMER2_COMPA_vect) {
// stuff
}

I am no specialist at setting up timer registries, but are you disabling interrupts while setting them up ?

You're setting the prescaler to /32, not /64:

    TCCR2B |= (1 << CS20);
    TCCR2B |= (1 << CS21);
    TCCR2B &= ~(1 << CS22);

This gives 250x2uS == 500uS period or 2kHz.

Use

    TCCR2B |= _BV(CS22);

to set 0b100 for the prescaler (/64) to get 1kHz.

    // turn on CTC mode
    TCCR2A |= (1 << WGM21);

You are setting a bit in TCCR2A without clearing all the bits first. Since the Arduino library sets up the timers for PWM it is likely a bit is set already.

Either add this at the top where you set TCCR2B to zero:

  TTCR2A = 0;

Or change the code to set the whole register instead of one bit:

    // turn on CTC mode
    TCCR2A = (1 << WGM21);

Blackfin:
You're setting the prescaler to /32, not /64:

    TCCR2B |= (1 << CS20);
TCCR2B |= (1 << CS21);
TCCR2B &= ~(1 << CS22);



This gives 250x2uS == 500uS period or 2kHz.

Use



TCCR2B |= _BV(CS22);



to set 0b100 for the prescaler (/64) to get 1kHz.

I agree it looks that way but according to the datasheet I am setting the correct prescaler bits. It clearly says that bits CSx0 and CXs1 must be 1 and bit CSx2 must be 0 for a 64 prescaler.

Since the Arduino library sets up the timers for PWM it is likely a bit is set already.

This makes much sense. And I will try out to clear the register first. It remains however strange that with a different prescaler and compare match registers it works well. You would expect a similar bug.
I will try the clearing the register now. Thanks for the answers.
Bas

bask185:

I agree it looks that way but according to the datasheet I am setting the correct prescaler bits.

The table you're showing there is for Timer1 (note "TCCR1B"). You're using Timer2.

See the '328 datasheet pg 131.