2
\$\begingroup\$

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?

\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I forgot to mantion about something. When I change the value of OCR1B the blink speed does not change. I will add it to my question \$\endgroup\$ – Zgrkpnr__ May 4 '15 at 18:30
  • \$\begingroup\$ @Zgrkpnr__ The value of OCR1A controls the period of Timer 1. No matter what the value of OCR1B is, the Compare B Match Interrupt still occurs one time per count cycle with a rate controlled by the period of the timer (OCR1A value) \$\endgroup\$ – alexan_e May 4 '15 at 18:37
  • \$\begingroup\$ @Zgrkpnr__ That is up to you, the timer has several modes and the interrupt functionality may or may not be useful depending on the mode you use. You could create a PWM signal using OCR1A to control the frequency and OCR1B to control the duty cycle but there is not much point in that since timer has better suited PWM modes. \$\endgroup\$ – alexan_e May 4 '15 at 18:46
  • \$\begingroup\$ I edited my comment. As a matter of fact, I did'n understand you at the first place correctly. Now I understand that "B occurs only once in a cycle of 0 to ORC1A no matter what it's value is". \$\endgroup\$ – Zgrkpnr__ May 4 '15 at 18:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.