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.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.