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 whenOCR1A = 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.