I'm using a timer and the TIMERx_COMPA ISR to generate a signal in "the background".

This ISR is triggered when the timer reaches a certain value (OCRxA), which in turn can be changed by the user. Once the ISR triggers, the timer is reset and the next waiting period occurs.

If the compare value (OCRxA) is changed to a value below the current timer value before having hit the old compare value, the timer keeps running until it overflows back to 0 and hits the new OCRxA value. This results in no signal being generated until the timer has looped around, which can be quite long for the 16-bit TIMER1 timer.

There are multiple way to get around this:

  1. Reset TCNTx to zero whenever OCRxA. Easy, but one signal will always be off-clock
  2. If TCNTx is greater than OCRxA (after changing OCRxA), reset it to just below OCRxA
  3. If TCNTx is greater than OCRxA, trigger the interrupt manually, where the signal is generated and TCNTx is reset

I belive the third option would be the cleanest, both in checking whether the issue has occured as well as for the signal quality.

This is certainly an X -> Y problem, so I'm open for other approaches.

My question, for now, would be: Can I manually jump to an ISR regardless of its "normal" trigger?

  • @Juraj True, I suppose the "Electrical Engineering" SE would've been more appropriate? I am programming an Arduino Uno with the Arduino IDE though. I've always felt the line between those two SEs is very thin, especially when using the Arduino as nothing but a simple way to program the AVR.
    – towe
    Mar 19, 2019 at 13:59
  • I ask AVR specific questions on avrfreaks.net/forum
    – Juraj
    Mar 19, 2019 at 14:21

1 Answer 1


Can I manually jump to an ISR regardless of its "normal" trigger?

This should be possible, but is probably not the best solution.

This is certainly an X -> Y problem, so I'm open for other approaches.

It would seem you are using the timer in CTC mode. In this mode, when you write to OCRxA, the register is updated immediately, which leads to the problem you are experiencing. The solution is to instead set the timer to “fast PWM” mode. In fast PWM mode, the OCRxA register is double buffered: you will be actually writing to a buffer register, and OCRxA is automatically updated from that buffer on the same timer clock cycle that clears the counter.

It may sound counter-intuitive to use a PWM mode when you do not need the PWM feature. However, as long as the “compare output mode” is set to “normal port operation” for both channels, the timer will not generate any PWM output, and you can legitimately use the fast PWM mode only for its double buffer feature.

  • That's absolutely gorgeous. It seems to work perfectly with my test code, without ever checking whether TCNT has reached past OCRxA. The buffers delay would be irrelevant with OCRxA only being updated once per millisecond. I'm a bit ashamed to admit I wasn't even using CTC though, the entire code had been in "normal" (mode 0), with me resetting TCNT as the first action in the ISR. You were refering to "mode 4" where I could have just omitted the TCNT reset, right?
    – towe
    Mar 19, 2019 at 13:37
  • I had some code which would check for how long TCNT was larger than OCRxA and output that over serial. This now "always" displays some of that "lag". Am I right in assuming it's comparing my real TCNT value to the buffered OCRxA and not the active OCRxA and that this metric would now be meaningless / expected? If so, is there any way of reading the "active" OCRxA vs. the one in the buffer which is not yet "active"?
    – towe
    Mar 19, 2019 at 13:48
  • 1
    @TobiasWeiß: Re “the entire code had been in "normal" (mode 0) [...].”: Since the ISR prologue takes some time, and may even be delayed by other interrupts, your interrupt period is likely to be larger than you want. “You were refering to "mode 4" [...], right?” Right. “Am I right in assuming it's comparing my real TCNT value to the buffered OCRxA [...]?” Judging from the section “Output Compare Units” of the datasheet, it would seem this is the case. “Is there any way of reading the "active" OCRxA [...]?” Not that I am aware of. Mar 19, 2019 at 14:14

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.