Skip to main content
Arduino

Return to Answer

Expanded explanation on how interrupts work.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

The project behaves as if enabling timer compare interrupts instantly triggered one

This can indeed happen, and it's likely what you are experiencing.

Explanation: whenever the timer value hitsan interrupt fires when three bits are simultaneously set:

  • the "interrupt flag" that signals the detection of some specific event
  • the "interrupt enable" bit associated with that particular interrupt
  • the "global interrupt enable" bit that is set by the sei() instruction

In your case, the value stored inrelevant interrupt flag is OCR1AOCF1A (Timer/Counter1, a "timer compare" event is registeredOutput Compare A Match Flag), which is recorded by raising the flagin register OCF1ATIFR1 (Timer/Counter1 Interrupt Flag Register). This flag is raised by a "timer compare" event, i.e. when the timer value hits the value stored in register TIFR1OCR1A. If the corresponding interrupt is enabledthe interrupt fires, the flag is automatically cleared when the CPU starts executing thestarts executing the corresponding ISR. Alternatively, the flag can be cleared manually bycleared manually by overwriting it with a logic 1 (yes, that's kind of backwards backwards). It is worth noting that the flag records the compare events whether or not the interrupt is enabled.

ifYou normally expect the interrupt flag to be the last of these three bits to be set, so that the interrupt is high whentriggered by the compare event. But this need not be the case. In your program, it is likely that the interrupt flag is raised one second after startup. The global interrupt enable is set by your sei() at the end of setup(). Thus, at this point, as soon as you set the interrupt enable bit the interrupt, then that interrupts fires is triggered immediatelyimmediately. You should normally

The standard solution to this problem is to clear the interrupt flag beforeright before setting the interrupt enable bit.:

TIFR1 |= _BV(OCF1A); // clear timer compare flag
TIMSK1 |= _BV(OCIE1A); // enable timer compare interrupt

The project behaves as if enabling timer compare interrupts instantly triggered one

This can indeed happen, and it's likely what you are experiencing.

Explanation: whenever the timer value hits the value stored in OCR1A, a "timer compare" event is registered, which is recorded by raising the flag OCF1A in register TIFR1. If the corresponding interrupt is enabled, the flag is automatically cleared when the CPU starts executing the corresponding ISR. Alternatively, the flag can be cleared manually by overwriting it with a logic 1 (yes, that's kind of backwards).

if the flag is high when you enable the interrupt, then that interrupts is triggered immediately. You should normally clear the interrupt flag before setting the interrupt enable bit.

The project behaves as if enabling timer compare interrupts instantly triggered one

This can indeed happen, and it's likely what you are experiencing.

Explanation: an interrupt fires when three bits are simultaneously set:

  • the "interrupt flag" that signals the detection of some specific event
  • the "interrupt enable" bit associated with that particular interrupt
  • the "global interrupt enable" bit that is set by the sei() instruction

In your case, the relevant interrupt flag is OCF1A (Timer/Counter1, Output Compare A Match Flag), in register TIFR1 (Timer/Counter1 Interrupt Flag Register). This flag is raised by a "timer compare" event, i.e. when the timer value hits the value stored in OCR1A. If the interrupt fires, the flag is automatically cleared when the CPU starts executing the corresponding ISR. Alternatively, the flag can be cleared manually by overwriting it with a logic 1 (yes, that's kind of backwards). It is worth noting that the flag records the compare events whether or not the interrupt is enabled.

You normally expect the interrupt flag to be the last of these three bits to be set, so that the interrupt is triggered by the compare event. But this need not be the case. In your program, it is likely that the interrupt flag is raised one second after startup. The global interrupt enable is set by your sei() at the end of setup(). Thus, at this point, as soon as you set the interrupt enable bit the interrupt fires immediately.

The standard solution to this problem is to clear the interrupt flag right before setting the interrupt enable bit:

TIFR1 |= _BV(OCF1A); // clear timer compare flag
TIMSK1 |= _BV(OCIE1A); // enable timer compare interrupt
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

The project behaves as if enabling timer compare interrupts instantly triggered one

This can indeed happen, and it's likely what you are experiencing.

Explanation: whenever the timer value hits the value stored in OCR1A, a "timer compare" event is registered, which is recorded by raising the flag OCF1A in register TIFR1. If the corresponding interrupt is enabled, the flag is automatically cleared when the CPU starts executing the corresponding ISR. Alternatively, the flag can be cleared manually by overwriting it with a logic 1 (yes, that's kind of backwards).

if the flag is high when you enable the interrupt, then that interrupts is triggered immediately. You should normally clear the interrupt flag before setting the interrupt enable bit.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /