# Enabling TIMER0 Interrupt breaks the timer

**URL:** <https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172>\
**Category:** Programming\
**Created:** [August 15, 2024, 6:05pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172 "2024-08-15T18:05:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 15, 2024, 6:05pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/1 "2024-08-15T18:05:38Z")

</div>

Hello,

I try to learn how to use interrupts and I use an Arduino Uno R3. I code in C.  
I managed to use the INT0 and INT1 interrupt with buttons but I now want to use the timer interrupts.  
The goal is to replicate the millis() function with the TIMER0.

Here is the first approach without an interrupt which works :

```arduino
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>

unsigned long millis = 0;

int main () {
	// Declare LED as output
	DDRB |= (1 << PORTB3);

	// Set timer0
	// Set CTC mode
	TCCR0A |= (1 << WGM01);
	// 16 000 000 / (64 * 250) = 1000 Hz
	// Set top value
	OCR0A = 250;
	// Prescaler 64
	TCCR0B |= ((1 << CS01) | (1 << CS00));

	while (1) {
		if ((TIFR0 & (1 << OCF0A)) != 0) {
			// Reset the timer
			TIFR0 |= (1 << OCF0A);
			// Increase millis
			millis++;
		}
		if (millis >= 1000) {
			millis = 0;
			// Switch the state of the LED
			PORTB ^= (1 << PORTB3);
		}
	}
}

```

Now the second approach with the interrupt which doesn't work :

```arduino
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>

unsigned long millis = 0;

// Timer0
ISR (TIMER0_COMPA_vect) {
	millis++;
	TIFR0 |= (1 << OCF0A);
}

int main () {
	// Declare LED as output
	DDRB |= (1 << PORTB3);

	// Set timer0
	// Set CTC mode
	TCCR0A |= (1 << WGM01);
	// 16 000 000 / (64 * 250) = 1000 Hz
	// Set top value
	OCR0A = 250;
	// Prescaler 64
	TCCR0B |= ((1 << CS01) | (1 << CS00));

	// Enable interrupt for timer0
	TIMSK0 |= (1 << OCIE0A);
	// Enable global interrupts
	SREG |= 0b10000000; 

	while (1) {
		if (millis >= 1000) {
			millis = 0;
			// Switch the state of the LED
			PORTB ^= (1 << PORTB3);
		}
	}
}

```

It doesn't works because the led never turns on. Also, I tried to change the code in the ISR (to turn on a LED for example) and it is never ran.

I don't know why this doesn't work because the documentation of the atmega328p says :  
"When the OCIE0A bit is written to one, and the I-bit in the Status Register is set, the Timer/Counter0 Compare Match A interrupt is enabled. The corresponding interrupt is executed if a Compare Match in Timer/Counter0 occurs, i.e., when the OCF0A bit is set in the Timer/Counter 0 Interrupt Flag Register – TIFR0."  
It seems to me like the OCIE0A is set to 1, the I-bit in the SREG is set to 1 and the CTC is enable for counter 0, match A.

Also, I found out that the first code breaks as soon as I add this line :

```arduino
// Enable interrupt for timer0
TIMSK0 |= (1 << OCIE0A);

```

It means to me that the OCF0A flag is not longer even set to 1.

I searched for an answer for a long time but I couldn't find anything.

I hope I have been understandable enough and I stay at your disposal for any question.

Thank you for reading,  
Pauloux

---

<div class="post-metadata">

**Author:** ![hmeijdam](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/hmeijdam/32/218564_2.png) [@hmeijdam](https://forum.arduino.cc/u/hmeijdam)\
**Post date:** [August 15, 2024, 6:20pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/3 "2024-08-15T18:20:15Z")

</div>

> [@Pauloux](#):
>
> `unsigned long millis = 0;`

change that to: `volatile unsigned long millis = 0;`

---

<div class="post-metadata">

**Author:** ![blh64](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/blh64/32/605986_2.png) [@blh64](https://forum.arduino.cc/u/blh64)\
**Post date:** [August 15, 2024, 6:37pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/4 "2024-08-15T18:37:03Z")

</div>

in addition to making `millis` `volatile` you need to turn off interrupts when accessing it in your main code since the Uno can only atomically access an 8 bit variable and `millis` is 4 bytes. If you don't, it can eventually bite you.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [August 15, 2024, 7:47pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/5 "2024-08-15T19:47:26Z")

</div>

> [@Pauloux](#):
>
> second approach with the interrupt which doesn't work

Here is how to make that work:

> **[Multi-tasking the Arduino - Part 2](https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers)**
>
> Explore the magic of interrupts. Learn how to harness timer interrupts to keep your tasks running like clockwork. And use external and pin-change interrupts to notify you of events that need urgent attention.

This action is not required in an ISR:

```arduino
	TIFR0 |= (1 << OCF0A);

```

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 15, 2024, 8:00pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/6 "2024-08-15T20:00:49Z")

</div>

Thank you and the other who told me to add `volatile`. I tried it and I now have this code :

```arduino
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>

volatile unsigned long millis = 0;

// Timer0
ISR (TIMER0_COMPA_vect) {
	millis++;
}

int main () {
	// Declare LED as output
	DDRB |= (1 << PORTB3);

	// Set timer0
	// Set CTC mode
	TCCR0A |= (1 << WGM01);
	// 16 000 000 / (64 * 250) = 1000 Hz
	// Set top value
	OCR0A = 250;
	// Prescaler 64
	TCCR0B |= ((1 << CS01) | (1 << CS00));

	// Enable interrupt for timer0
	TIMSK0 |= (1 << OCIE0A);
	// Enable global interrupts
	sei();

	while (1) {
		// Disable global interrupts
		cli();
		if (millis >= 1000) {
			millis = 0;
			// Switch the state of the LED
			PORTB ^= (1 << PORTB3);
		}
		// Enable global interrupts
		sei();
	}
}

```

As you can see I also use the cli() and sei() function to be certain that this part works as expected.

However, it still doesn't work ☹

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 15, 2024, 8:05pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/7 "2024-08-15T20:05:41Z")

</div>

> [@anon94801460](#):
>
> Here is how to make that work:

Thank you for the link but I can't see want I did differently. Also I used this post in the first place to better understand the timer interrupts.

> [@anon94801460](#):
>
> This action is not required in an ISR:
> 
> ```arduino
> TIFR0 |= (1 << OCF0A);
> 
> ```

Thank you ! I found on the internet some code with and some without so I added it to be sure. It still doesn't work when I remove it

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [August 15, 2024, 8:07pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/8 "2024-08-15T20:07:49Z")

</div>

> [@Pauloux](#):
>
> I can't see want I did differently.

Try Adafruit's code and make sure it works on your setup. Then compare your and their code line by line to find the differences.

Hint: the **only** modifications made by Adafruit to the Timer0 registers are these:

```arduino
  // Timer0 is already used for millis() - we'll just interrupt somewhere
  // in the middle and call the "Compare A" function below
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);

```

---

<div class="post-metadata">

**Author:** ![westfw](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/westfw/32/213443_2.png) [@westfw](https://forum.arduino.cc/u/westfw)\
**Post date:** [August 15, 2024, 9:13pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/10 "2024-08-15T21:13:49Z")

</div>

> [@anon94801460](#):
>
> the **only** modifications made by Adafruit

The Adafruit code is adding to the timer functionality already enabled by the Arduino init code. OP here is replacing main(), so it isn't running any arduino code and may need to do more complete timer initialization.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [August 15, 2024, 9:33pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/11 "2024-08-15T21:33:37Z")

</div>

The hint can be taken in several different ways.

---

<div class="post-metadata">

**Author:** ![luckyekene](https://avatars.discourse-cdn.com/v4/letter/l/c57346/32.png) [@luckyekene](https://forum.arduino.cc/u/luckyekene)\
**Post date:** [August 16, 2024, 7:58am UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/12 "2024-08-16T07:58:12Z")

</div>

Insert the cli() function to the line before the ddrb comment, just after the int main().

Then remove the sei() and cli() functions in the while loop.

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 16, 2024, 9:26am UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/13 "2024-08-16T09:26:16Z")

</div>

> [@anon94801460](#):
>
> Try Adafruit's code and make sure it works on your setup.

To be honest I'm a beginner so I don't really want to install a c++ compiler and learn OOP just for this example.

> [@anon94801460](#):
>
> Hint: the **only** modifications made by Adafruit to the Timer0 registers are these:
> 
> ```arduino
> // Timer0 is already used for millis() - we'll just interrupt somewhere
> // in the middle and call the "Compare A" function below
> OCR0A = 0xAF;
> TIMSK0 |= _BV(OCIE0A);
> 
> ```

I tried putting only those lines but it still doesn't work.

> [@Delta\_G](#):
>
> You have the timer in CTC mode with OCR0A serving as the TOP value. Since OCR0A is TOP you can't get a compare match on it. If you want an interrupt there then use the OVF interrupt instead of COMPA

I tried changing the interrupt to the OVF interrupt but it doesn't change anything.

Also, I found this in the documentation :  
Talking of the TIFR0 register :  
"The OCF0A bit is set when a Compare Match occurs between the Timer/Counter0 and the data in OCR0A – Output Compare Register0. OCF0A is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, OCF0A is cleared by writing a logic one to the flag. When the I-bit in SREG, OCIE0A (Timer/Counter0 Compare Match Interrupt Enable), and OCF0A are set, the Timer/Counter0 Compare Match Interrupt is executed."  
Maybe I understand badly because English isn't my native language but this extract explains that the OCR0A is set to 1 when there is a Compare Match (so in CTC mode ?) with the value inside OCR0A. Also, "when the OCF0A is set, the Compare Match Interrupt is executed" so I don't understand why it doesn't work. Maybe because the OCF0A is never set ? But the OCF0A is set when I remove the line `TIMSK0 |= (1 << OCIE0A);` which should just enable the interrupt.

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 16, 2024, 9:30am UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/14 "2024-08-16T09:30:35Z")

</div>

In order for everybody to better understand the conversation, here is my current program based on all of your responses :

```arduino
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>

volatile unsigned long millis = 0;

// Timer0
ISR (TIMER0_OVF_vect) {
	millis++;
}

int main () {
	// Disable global interrupts
	cli();
	// Declare LED as output
	DDRB |= (1 << PORTB3);

	// Set timer0
	// Set CTC mode
	TCCR0A |= (1 << WGM01);
	// 16 000 000 / (64 * 250) = 1000 Hz
	// Set top value
	OCR0A = 250;
	// Prescaler 64
	TCCR0B |= ((1 << CS01) | (1 << CS00));

	// Enable interrupt for timer0
	TIMSK0 |= (1 << OCIE0A);
	// Enable global interrupts
	sei();

	while (1) {
		if (millis >= 1000) {
			millis = 0;
			// Switch the state of the LED
			PORTB ^= (1 << PORTB3);
		}
	}
}

```

Thank you again for your time and I am still open to new idea to correct my program or at least some explanations on why it doesn't work.

---

<div class="post-metadata">

**Author:** ![GolamMostafa](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/golammostafa/32/239011_2.png) [@GolamMostafa](https://forum.arduino.cc/u/GolamMostafa)\
**Post date:** [August 16, 2024, 1:34pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/17 "2024-08-16T13:34:39Z")

</div>

> [@Pauloux](#):
>
> The goal is to replicate the millis() function with the TIMER0.

The following sketch uses TC0 of ATmega328P MCU of Arduino UNOR3 Board to generate 992 ms TimeTick which is indicated by flashing onBoard LED of UNOR3 Board.

```arduino
#include <util/delay.h>
#define F_CPU 16000000UL

#define LED 13
byte tickCount = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  bitClear(TIMSK0, TOIE0); //overflow interrupt is disabled
  bitClear(TIMSK0, OCIE0A); //compare-A interrut is inactive
  bitClear(TIMSK0, OCIE0B);
  TCNT0 = 6; //preset count for 16 ms tick
  TCCR0B = 0x05; //statrt with clkTC0 = 15625 Hz
}

void loop()
{
  while (bitRead(TIFR0, TOV0) != HIGH)
  {
    ; //wait until 16 ms has elapsed
  }
  bitSet(TIFR0, TOV0);
  TCNT0 = 6;
  tickCount++;
  if (tickCount == 62) //992 ms has gone
  {
    tickCount = 0;
    digitalWrite(LED, HIGH);
    _delay_ms(100);
    digitalWrite(LED, LOW);
    _delay_ms(100);
  }
}

```

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [August 16, 2024, 2:29pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/18 "2024-08-16T14:29:41Z")

</div>

> [@Pauloux](#):
>
> so I don't really want to install a c++ compiler and learn OOP just for this example.

What? If you are using the standard Arduino IDE, that is C++.

The points made by @westfw and @Delta_G above are that the Arduino IDE sets up Timer0 for you in the appropriate way. You don't need to change the timer operating mode if you use Adafruit's approach.

---

<div class="post-metadata">

**Author:** ![b707](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/b707/32/854321_2.png) [@b707](https://forum.arduino.cc/u/b707)\
**Post date:** [August 16, 2024, 2:59pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/19 "2024-08-16T14:59:56Z")

</div>

> [@Pauloux](#):
>
> here is my current program based on all of your responses :
> 
> ```arduino
> // Timer0
> ISR (TIMER0_OVF_vect) {
> ...
> }
> 
> TIMSK0 |= (1 << OCIE0A);
> 
> ```

You defined a handler for overflow interrupt, but enabled a compare one....

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 16, 2024, 3:56pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/20 "2024-08-16T15:56:45Z")

</div>

I found the problem !  
First of all, the working code :

```arduino
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>

volatile unsigned long millis = 0;

// Timer0
ISR (TIMER0_COMPA_vect) {
	millis++;
}

int main () {
	// Declare LED as output
	DDRB |= (1 << PORTB3);

	// Set timer0
	// Set CTC mode
	TCCR0A |= (1 << WGM01);
	// 16 000 000 / (64 * 250) = 1000 Hz
	// Set top value
	OCR0A = 250;
	// Prescaler 64
	TCCR0B |= ((1 << CS01) | (1 << CS00));

	// Enable interrupt for timer0
	TIMSK0 |= (1 << OCIE0A);
	// Enable global interrupts
	SREG |= (1 << 7);

	while (1) {
		if (millis >= 1000) {
			millis = 0;
			// Switch the state of the LED
			PORTB ^= (1 << PORTB3);
		}
	}
}

```

So what have changed ? The compilation... Indeed, I code in C, compile with avr-gcc and upload the program with avrdude.  
However, I reused the compilation command from another project which used another card. I didn't have any problem until here but now it matters.

Thank you everybody contributing to this post for your time, talent and kindness.

Pauloux ❤

---

<div class="post-metadata">

**Author:** ![GolamMostafa](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/golammostafa/32/239011_2.png) [@GolamMostafa](https://forum.arduino.cc/u/GolamMostafa)\
**Post date:** [August 16, 2024, 4:08pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/21 "2024-08-16T16:08:33Z")

</div>

> [@Pauloux](#):
>
> The goal is to replicate the millis() function with the TIMER0.

The above is your goal. The _millis()_ function reads the content of _miilisCounter_ which is advanced by 1 ms in the background using Timer0 interrupt.

I am confused as to what you have achived vs your goal.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [August 16, 2024, 4:14pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/22 "2024-08-16T16:14:07Z")

</div>

> [@Pauloux](#):
>
> First of all, the working code

Which differs from the non-working code.

---

<div class="post-metadata">

**Author:** ![Pauloux](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/pauloux/32/1098795_2.png) [@Pauloux](https://forum.arduino.cc/u/Pauloux)\
**Post date:** [August 18, 2024, 7:11pm UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/23 "2024-08-18T19:11:19Z")

</div>

> [@GolamMostafa](#):
>
> I am confused as to what you have achived vs your goal.

I use the timer 0 to track the time spend since the beginning of the program. I store this information in the variable `millis`.  
So yes it is not exactly like the `millis()` function but the result is the same since I can acces the time in milliseconds since the program started.

---

<div class="post-metadata">

**Author:** ![GolamMostafa](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/golammostafa/32/239011_2.png) [@GolamMostafa](https://forum.arduino.cc/u/GolamMostafa)\
**Post date:** [August 19, 2024, 5:58am UTC](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172/24 "2024-08-19T05:58:46Z")

</div>

> [@Pauloux](#):
>
> I store this information in the variable `millis`.

Please don't get confused with the popular _millis()_ functionon of Arduino UNO. It is a function and its name should not be used by the user as an identfier for any other variable.

[Next page](https://forum.arduino.cc/t/enabling-timer0-interrupt-breaks-the-timer/1292172.md?page=2)
