Electronic – AVR Timer1 OCR1A controls TIMER1_COMPB_vect interrupt!

avrinterruptstimer

I was struggling with timer interrupts in my project. I couldn't make it work properly. So I decided writing a simple code and I saw a very interesting case.

ISR(TIMER1_COMPB_vect)
{

        PORTB ^= (1 << PORTB5);

}


int main(void)
{
    cli();          // disable global interrupts
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B

    OCR1A = 10000;
    OCR1B = 100;

    TCCR1B |= (1 << WGM12);

    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);

    TIMSK1 |= (1 << OCIE1A);
    TIMSK1 |= (1 << OCIE1B);
    DDRB= 0xFF;

    #define F_CPU 16000000
    sei();
    while (1)
    {

    }
}

Here is my code. When I change OCR1B value, nothing happens, but if I change OCR1A value then blinking gets faster. Is there a logical explanation for this?

Best Answer

By setting TCCR1B |= (1 << WGM12); you operate the timer in CTC mode counting from 0 up to the value assigned to OCR1A and back to zero again.

With the given value of OCR1A = 10000; the timer counts 0-10000, 0-10000...
For each 0-10000 count you get a Compare B Match Interrupt when the counter reaches the value of 100 (because you have set OCR1B = 100).

By changing OCR1A you essentially change the upper count limit of the timer which means that you also change the duration of each count cycle, so the Compare B Match Interrupt occurs faster.

As an example, if you set OCR1A = 5000; the Compare B Match Interrupt occurs twice as fast compared to when OCR1A = 10000; because the timer restarts the count when it reaches 5000 instead of 10000 so the counter period shortens.

As a side-note, make sure that you include in your code the interrupt handler functions for all the enabled interrupts (ISR(TIMER1_COMPA_vect) seems to be missing) or resets may occur.