Posted by on Jun 24, 2011 in Atmel AVR, Microcontrollers | 256 comments

# AVR Timers – TIMER0

Hello friends! Welcome back to the second part of the AVR Timers Series. In the previous post, we have discussed the basic concepts of AVR Timers. Let me summarize it:

• We have seen how timers are made up of registers, whose value automatically increases/decreases. Thus, the terms timer/counter are used interchangeably.
• In AVR, there are three types of timers – TIMER0, TIMER1 and TIMER2. Of these, TIMER1 is a 16-bit timer whereas others are 8-bit timers.
• We have seen how prescalers are used to trade duration with resolution.
• We have also discussed how to choose an appropriate value of a prescaler.
• And then, to finish off, we learnt about interrupts.

So, I will move towards its implementation directly. I have assumed that you have understood the concepts discussed above.

In this tutorial, we will learn to use TIMER0. Since timer is a peripheral, it can be activated by setting some bits in some registers. Instead of discussing all the registers at once, we will be discussing them as and when necessary. For those who are new to the term ‘register’, they can read about it from this page. To have an idea about AVR Peripherals, view this page (you need to scroll down a bit).

# Problem Statement

Let’s define a problem statement for us. The simplest one being the LED flasher. Let’s say, we need to flash an LED every 6 ms and we are have a CPU clock frequency of 32 kHz.

Well, I know that an LED flashing at every 6 ms will be always visible as on by our eye, but I could not find any simpler example which does not include prescalers. Take this as a demonstration.

# Methodology

Now, as per the following formula, with a clock frequency of 32 kHz and 8-bit counter, the maximum delay possible is of 8 ms. This is quite low (for us, but not for the MCU). Hence for a delay of 6 ms, we need a timer count of 191. This can easily be achieved with an 8-bit counter (MAX = 255).

Thus, what we need to do is quite simple. We need to keep a track of the counter value. As soon as it reaches 191, we toggle the LED value and reset the counter. For this, we need the help of the following registers.

### TCNT0 Register

The Timer/Counter Register – TCNT0 is as follows:

TCNT0 Register

This is where the uint 8-bit counter of the timer resides. The value of the counter is stored here and increases/decreases automatically. Data can be both read/written from this register.

Now we know where the counter value lies. But this register won’t be activated unless we activate the timer! Thus we need to set the timer up. How? Read on…

### TCCR0 Register

The Timer/Counter Control Register – TCCR0 is as follows:

TCCR0 Register

Right now, we will concentrate on the highlighted bits. The other bits will be discussed as and when necessary. By selecting these three Clock Select Bits, CS02:00, we set the timer up by choosing proper prescaler. The possible combinations are shown below.

Clock Select Bit Description

For this problem statement, we choose No Prescaling. Ignore the bits highlighted in grey. We will be using it later in this tutorial. Thus, we initialize the counter as:

`TCCR0 |= (1 << CS00);`

Please note that if you do not initialize this register, all the bits will remain as zero and the timer/counter will remain stopped.

Thus now we are ready to write a code for this. To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this.

### Code

```#include <avr/io.h>

void timer0_init()
{
// set up timer with no prescaling
TCCR0 |= (1 << CS00);

// initialize counter
TCNT0 = 0;
}

int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);

// initialize timer
timer0_init();

// loop forever
while(1)
{
// check if the timer count reaches 191
if (TCNT0 >= 191)
{
PORTC ^= (1 << 0);    // toggles the led
TCNT0 = 0;            // reset counter
}
}
}```

I guess the code is pretty simple and straightforward. It doesn’t need any explanation. Or maybe one thing needs explanation. In the if statement, I have used

`if (TCNT0 >= 191)`

`if (TCNT0 == 191)`

This is because sometimes due to missed compares or unexpected increment, this condition may never be true. Thus to remain on the safer side, we use ‘>=’ instead of ‘==’.

# Problem Statement Redefined

Now let’s change the above problem statement to the following. We need to flash an LED every 8 ms and we have an XTAL of 16 MHz. Well, 8 ms is still low, but it’s good enough for the following illustration.

### Methodology – Using Prescalers

Now since the CPU clock frequency is 16 MHz, the maximum time delay that it can measure is 16 μs! But 8 ms (which is quite a small duration for us) is way much larger. So what do we do? Yes, you guessed right (I hope so ;))! We use a prescaler in order to trade duration with resolution. Now the following table summarizes the results of using different prescalers 8, 64, 256 and 1024. See previous tutorial for details.

Prescaler Selection

From the values of the counter, we can easily rule out the top three prescalers as they are above the maximum limit of an 8-bit counter (which is 255). Thus we use a prescaler of 1024. Now refer to the descriptions of clock select bits as shown in the TCCR0 register. Have a look at the selection highlighted in grey. This implements a prescaler of 1024. The rest remains the same. Moving to the coding part, we simply change the initialize function and the compare value. The rest remains the same.

### Code

```#include <avr/io.h>

void timer0_init()
{
// set up timer with prescaler = 1024
TCCR0 |= (1 << CS02)|(1 << CS00);

// initialize counter
TCNT0 = 0;
}

int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);

// initialize timer
timer0_init();

// loop forever
while(1)
{
// check if the timer count reaches 124
if (TCNT0 >= 124)
{
PORTC ^= (1 << 0);    // toggles the led
TCNT0 = 0;            // reset counter
}
}
}```

# Problem Statement Redefined Again!

Now let’s change the problem statement to something you can actually see! Let’s flash an LED every 50 ms (you can surely see the LED flashing this time ;)). We have an XTAL of 16 MHz.

### Methodology – Using Interrupts

So now, we have to flash the LED every 50 ms. With CPU frequency 16 MHz, even a maximum delay of 16.384 ms can be achieved using a 1024 prescaler. So what do we do now? Well, we use interrupts.

The concept here is that the hardware generates an interrupt every time the timer overflows. Since the required delay is greater than the maximum possible delay, obviously the timer will overflow. And whenever the timer overflows, an interrupt is fired. Now the question is how many times should the interrupt be fired?

For this, let’s do some calculation. Let’s choose a prescaler, say 256. Thus, as per the calculations, it should take 4.096 ms for the timer to overflow. Now as soon as the timer overflows, an interrupt is fired and an Interrupt Service Routine (ISR) is executed. Now,

50 ms ÷ 4.096 ms = 12.207

Thus, in simple terms, by the time the timer has overflown 12 times, 49.152 ms would have passed. After that, when the timer undergoes 13th iteration, it would achieve a delay of 50 ms. Thus, in the 13th iteration, we need a delay of 50 – 49.152 = 0.848 ms. At a frequency of 62.5 kHz (prescaler = 256), each tick takes 0.016 ms. Thus to achieve a delay of 0.848 ms, it would require 53 ticks. Thus, in the 13th iteration, we only allow the timer to count up to 53, and then reset it. All this can be achieved in the ISR as follows:

```// global variable to count the number of overflows
volatile uint8_t tot_overflow;

// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
// keep a track of number of overflows
tot_overflow++;
}

int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);

// initialize timer
timer0_init();

// loop forever
while(1)
{
// check if no. of overflows = 12
if (tot_overflow >= 12)  // NOTE: '>=' is used
{
// check if the timer count reaches 53
if (TCNT0 >= 53)
{
PORTC ^= (1 << 0);    // toggles the led
TCNT0 = 0;            // reset counter
tot_overflow = 0;     // reset overflow counter
}
}
}
}```

Please note that the code is not yet ready. Not until you learn how to enable the interrupt feature. For this, you should be aware of the following registers.

### TIMSK Register

The Timer/Counter Interrupt Mask – TIMSK Register is as follows. It is a common register for all the three timers. For TIMER0, bits 1 and 0 are allotted. Right now, we are interested in the 0th bit TOIE0. Setting this bit to ‘1’ enables the TIMER0 overflow interrupt.

TIMSK Register

### TIFR Register

The Timer/Counter Interrupt Flag Register– TIFR is as follows. Even though we are not using it in our code, you should be aware of it.

TIFR Register

This is also a register shared by all the timers. Even here, bits 1 and 0 are allotted for TIMER0. At present we are interested in the 0th bit TOV0 bit. This bit is set (one) whenever TIMER0 overflows. This bit is reset (zero) whenever the Interrupt Service Routine (ISR) is executed. If there is no ISR to execute, we can clear it manually by writing one to it.

In this example, since we are using ISR, we need not care about this bit (thus this register as a whole).

Enabling Global Interrupts

In the AVRs, there’s only one single bit which handles all the interrupts. Thus, to enable it, we need to enable the global interrupts. This is done by calling a function named sei(). Don’t worry much about it, we simply need to call it once, that’s all.

### Final Code

```#include <avr/io.h>
#include <avr/interrupt.h>

// global variable to count the number of overflows
volatile uint8_t tot_overflow;

// initialize timer, interrupt and variable
void timer0_init()
{
// set up timer with prescaler = 256
TCCR0 |= (1 << CS02);

// initialize counter
TCNT0 = 0;

// enable overflow interrupt
TIMSK |= (1 << TOIE0);

// enable global interrupts
sei();

// initialize overflow counter variable
tot_overflow = 0;
}

// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
// keep a track of number of overflows
tot_overflow++;
}

int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);

// initialize timer
timer0_init();

// loop forever
while(1)
{
// check if no. of overflows = 12
if (tot_overflow >= 12)  // NOTE: '>=' is used
{
// check if the timer count reaches 53
if (TCNT0 >= 53)
{
PORTC ^= (1 << 0);    // toggles the led
TCNT0 = 0;            // reset counter
tot_overflow = 0;     // reset overflow counter
}
}
}
}```

So friends, we are done with the basics of TIMER0. What remains to be discussed in it are CTC Mode and PWM Mode. We will be discussing them in upcoming posts. In the next post, we will discuss how to apply the same concepts to use TIMER1, and then to TIMER2.

Till then, enjoy flashing LEDs at different intervals! ;)

And please comment below to encourage me to keep on updating interesting stuffs! :) Also you can grab the RSS Feeds or subscribe to my blog to stay updated!

Thank You!

could you help us to explain this code?

2. please suggest how to write program to generate 38Khz frequency?
and how to calculate OCR0A value from attint 13

• Hi Varun,

Assuming you are trying to generate a square wave of 38kHz Frequency with 50% Duty Cycle, you have to take the inverse of the frequency, it will give you the time period of the wave. Divide this Time period by 2. Now make a function to give you a delay of this value. Assuming that you have read this post, it will be really easy for you to do it. Finally, Set the desired pin, call this function, then clear the desired pin, and call this function again. Run these four lines in the indefinite loop, and you should have your signal. There is another, much easier method to do this, read the post carefully to find out.

Hope this helps!

3. Hi, I want to generate 2 pulses, in B0 & B1:

BO: 14ms(High), then 236ms (low)
B1: 2ms(Low), then 5 ms(high), then 243 ms (low).

Both sincronized with a period of 250 ms.

I will tray using Timer0, but I can’t generate exactly the pulso. I’m only generated with PWM (Phase correct), but with 130 ms of PERIOD.

Thankfully

• Why can’t you generate pulses using Timer0? What’s the problem that you’re facing?

• Thanks. I solve the problem. I had a mistake using prescaler and the configuration of the clock in Proteus.
Your post help me a lot.

• Cool. Good job!

4. I don’t understand what’s the difference between toggle bit and inverting bit, they look like the same, as toggle bit (1 to 0, 0 to 1) and inverting bit ~.
thx

• Yup, they mean the same. Toggle bit, invert bit, wiggle bit.. all mean similar.

• Hello Morteza,
This is an overflow interrupt. When that happens, the value of TCNT0 is always 0. So your condition `if(TCNT0 >= 198)` is always false. Think of some other way around.

5. Hello
I want to see the toggle (PORTx) and the timerx status in simulation but I cant see any thing change in simulation mode by active the simulation.
can you help
thanks

• Timers don’t work well in simulation. Work with real hardware if you’re working with timers.

6. hello sir, i tried to write a timer code in atiny13 for 10sec delay
loaded the value to OCR0A such that for every 10ms interrupt occure.

Frequency:1Mhz
Prescalar used : 1024

problem facing:
1)the problem is im not getting proper 10 sec delay.
2) if i load 11 to OCR0A im getting 10sec delay, and as time passes the delay wont be 10 sec, its gradually decreases by 100ms or 200ms.
3) can u please tell me what and where im doing wrong?

here is my code. [CODE REMOVED BY ADMIN]

• The reason you’re not getting 10 seconds accurately is because your prescaler is too high! As you increase the prescaler, you are decreasing the clock rate, which means you’re essentially decreasing the accuracy. If you want to have a delay of exactly 10 seconds, I would suggest using a 32.768kHz clock frequency. You’ll know why once you do the calculations using 16-bit timer. :)

7. Hello,
you did great job.
can we use one timer for delay as well as for PWM.

• Hi RV

Yes, you absolutely can.

Hope this Helps!

8. Hi, I want to send a serie of 8pulses at 40kHz . I’ve a continuous signal at 40kHz but I can’t send just 8 pulses … How can I do that ?

• I don’t understand what you mean by “series of 8 pulses at 40 kHz”. Please elaborate. Thanks!

• I want to generate and send a burst to my ultrasonic transceiver … I know how to generate a constant 40Khz whit normal mode but I don’t know how to send a burst at 40khz … When I use while or for to do this I’ve got bad thing .

Now I try to generate a 40kHz with timer0 CTCmode but bad result too … I try to generate my wave with this mode for use interrupt ! See my code : http://pastebin.com/0XNQMjNi

• Hi Sylvain,
All you have to do is to set a timer to run at 80KHz and flip a pin every time the timer overflows. Keep a counter so that you stop after 8 times. Makes sense?

• Sir, I want to make an LED on for 15 minutes & then it will turn off forever until user wants to turn it on again. how & which code i have write for Atmega8. please help me.

9. hello sir….
Im using a RTC PCF8563 with xmega32a4u
RTC’s INT pin is ommected to controller power pin.

What i need to do is, i need to design suh that for every 1 hour INT pin should active and it should bring the controller from sleep mode to active mode, do some stuff and again go back to sleep. It should happen for every 1hour.

1) thought of using timer present in the RTC, but it is only 8bit timer.
2) can i use alaram concept ? if yes plz give some idea.

Thank u.

10. you r great………….thanks

11. its a great blog sir …..but sir I cant understand only timer interrupt programming so plz send me this timer interrupt programing in codevisionavr form in my email id mahisagariya@gmail.com ,,,sir

12. #include
volatile int a;
void timer0_init(void);
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
a++;

}

void main(void)
{
PORTB=0x00;
DDRB=0x10;
timer0_init();
#asm(“sei”)

while (1)
{
// check if no. of overflows = 12
if (a>= 12) // NOTE: ‘>=’ is used
{
// check if the timer count reaches 53
if (TCNT0 >= 53)
{
PORTB^=0x10; // toggles the led
TCNT0 = 0; // reset counter
a= 0; // reset overflow counter

}
}

}
}

void timer0_init(void)
{
// set up timer with prescaler = 256
TCCR0 |=0x04;

// initialize counter
TCNT0 = 0;

// enable overflow interrupt
TIMSK |=0x01;

// enable global interrupts
sei();

// initialize overflow counter variable
a= 0;
}

sir I am using codevisionavr for programming but this show error “undefined sei ” and afters remove sei so error also remove but led not flash at 50ms delay it take more time to blink sir plz reply

13. HEllo, I’m confused, shouldn’t we write 52 instead of 53, cause the count start from 0 and we want 53 ticks,
Thanks for the great work .

14. I have a question, why compare the value of overflow in the while loop, why not in the ISR? I know ISR should be small but this is just 5 extra lines.

15. I wanted to ask wht is is the use of enabling the interrupt before weve got into the loop of 12.207 iterations.. . I mean wht ive understood is that i have to go the 12.207 iterations n then the interrupt is fired so that the leds light up.. Is tht wht it means or smthing else. Enlighten please

16. Thank you for the tutorial, it is really helpful

17. Many thanks, Max. Your tutorial about AVR timer is absolutely clear. It’s really time-consuming to consult datasheet and figure out how to use this module to beginners like me. Anyway, I am very enjoying learning from your tutorial. I will keep learning other AVR topics from your tutorials~

Holmes Chang

18. TCCR0 |= (1 << CS02);
should TCCR0B |= (1 << CS02);
&
TIMSK |= (1 << TOIE0);
is TIMSK0 |= (1 << TOIE0);

otherwise Atmel Studio will shows error………