Pages Menu
TwitterRssFacebook
Categories Menu

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

AVR Timers – TIMER0

AVR Timers – TIMER0

AVR SeriesHello 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).

Timer CountThus, 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

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

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

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)

instead of

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

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

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

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!

Max

Max is the founder and admin of maxEmbedded. He describes himself as an 'embedded electronics freak' and an Apple/Linux fan. He likes to experiment, learn and share new things in this field. Furthermore, he likes to write stuffs on his website for techie newbies and loves to teach others. In his spare time, you will find him with volunteering somewhere!

More Posts - Website

Follow Me:
TwitterFacebookLinkedInGoogle Plus

193 Comments

  1. Dear Max, I get compilation error
    multiple definition of `__vector_9′

    • Strange. Could you paste your code at pastebin.com and share the link here? Which compiler are you using?

  2. sir
    i have avr robo board which has external crystal oscillator of 16 mhz. controller i used ATMEGA 16A, iam programming in atmel studio6, i write F_cpu 16000000UL,in program but still im not getting 1 s delay ,how to know fuse bit to set it before programming.sir can u help me in changing the fuse bit, here is my program:
    #define F_CPU 16000000UL
    #include
    #include

    int main(void)
    {
    DDRA = 0xFF;

    while(1)
    {
    PORTA =(0X00);
    _delay_ms(1000);
    PORTA =0XFF;
    _delay_ms(1000);

    }
    }in proteus it is not blinking..when i set to default 1 mhz internal, and change the program F_cpu 1000000UL then it starts blinking, but on board ihave external oscillato of 16 mhz,then how to set fuse bit for this please help …..

  3. i have a problem with timer count formula….i think this not correct. Plz inform me with correct version formula through my mail.
    timer count= requied delay/clk frequency

    • Fazal,
      Please read through my timer tutorials to understand about it.

  4. BEST OF THE BEST TUTORIAL

    saya pertama kali belajar MicroController tanpa guru,
    dan belum tahu apa-apa, tapi dengan membaca tutorial yang sangat terperinci dari Bapak, saya agak memahami.
    Sebelumnya sering baca tutorial yang lain, tapi menerangkannya tidak detail,
    Terimakasih…., Thank….., Sukron……

    • Thanks Komarudin! It’d be great if you could translate it to English so that I can understand what you wanna say. Thanks! :)

  5. HELLO MAYANK BHAIYA ;
    IN THE LAST EXAMPLE IF I PUT THIS CODE SNIPPET : http://pastebin.com/VzaNcyDC
    IN THE ISR THE PROGRAM DOESNT WORK ANY SPECIFIC REASON.

    • And why should it work? The ISR is executed whenever the TCNT0 overflows. Thus, whenever you’re checking the condition, TCNT0 is always 0, which is less than 53.
      And please turn off your CAPS LOCK while writing. Thanks.

      • Thanks bhaiya and ill keep the “caps” in mind

  6. Hi MAX, i need to make a frequency variable dual pulse generator (single and quadrature)using atmega169p. the quadrature mode has 90deg phase shift. the output frequency ranges from 0 Hz to 30kHz adjusted using a potentiometer. please help me where do i need to start PLEASE. it will be very much appreciated. THANKS in advance :)

    • Hi John,
      I hope you already know how to generate digital signal at a particular frequency. Phase shift in a signal essentially means that you’re delaying the signal. Connect the pot to your microcontroller via ADC and then based upon the reading, alter the element that controls the frequency of the digital signal. And give appropriate delays (phase shift) wherever necessary. Does that make any sense?

      • yup that makes sense. thanks a lot. i can already generate two signals with same frequency and vary it with pot. my problem now is setting the phase shift between them. i used _delay_ms() but it didn’t work.

        • im sorry, _delay_ms() works but it has to specify the time, i need to vary the delay base upon the variation of the frequency of the pulse.

        • Delay wouldn’t work here. You’ll have to use two different compare matches at unique locations.

          • how can i set up the phase shift between the two pulses? all i need is 90deg phase shift. please help me. thank you

          • That’s what I said! Using delays won’t work here since they are derived from the same timer. You’ll need to use compare matches at two separate locations.

            For instance, I compare TCNT0 with two values. Say, when TCNT0 == 20, then wiggle a some bit. Let the counter increment. Now, say, when TCNT0 == 187, then wiggle some other bit. Use this technique. This is just an example, you’ll need to calculate precisely.

            And by no means this is the only method to do so. There might be other better ways too, but you’ll need to figure it out on your own. You know the basics, now apply it for your application.

            Thanks!

  7. Thanks a lot! This is a treasure chest of knowledge :)

    • Good to hear that Patrick! You’re welcome! :)

    • I wouldn’t say what’s wrong, but I can point out what the mistake is and how many as well! :)
      Check out your if condition inside the tim0(). Do you see the cause? There are two things wrong over there!

      • first of all my observations are as follows:
        what i did was changed the value from 90 to around 900 then the leds were lit brighter than the value for 90.
        so this indicates that the timer delay caused it & hence the delay subroutine is correct.
        now i am really suspecting that i should clear the timer overflow flag i really do not know.
        but i even tried writing in the timer delay subroutine as TOV0=1// which clears the overflow flag .
        but it gave syntax error & so could not proceed & nor the blinking took place.

        • Don’t think so hard! Cuz I don’t think that’s the problem. Replace your current if condition with this:
          if(TCNT0>=190) {
          TCNT0=0;
          }

          • finally i copy pasted the code what you wrote above timer with no prescaling same result the led does not blink at all.
            And another thing i do not understand this:
            if(TCNT0>=190)
            {
            //TOGGLE LED
            //CLEAR TCNT0
            }
            this has no meaning as per me why?
            ans:
            assume no prescaling:
            initially TCNT0=0
            when it starts executing that if statement don’t you think the condition stated inside if will always dissatisfy and hence there will be no execution of the subroutine.

          • Disha,
            Seems like you have horribly misunderstood what prescaling is. Consider prescaling as frequency division. Whatever the frequency may be (doesn’t matter whether prescaling is enabled or not), once the timer starts, it always increments its count every tick no matter what. Initially it starts with TCNT0=0, next clock tick it becomes 1, then 2, and eventually it will become 190.
            And would you like to add something to the fact that your LED is not blinking? Is it on or off? Cuz the example I gave above, the LED blinks every 6 ms, which is too less of a time for your eyes to see it blink. It should always be visible as on.

          • ok then the previous code of which i provided a link in that whatever changes you asked me to make i have made i.e change in if statement but,still there is no effect.

  8. 1 sec on 1 sec off 2 sec on 2 sec off 3sec on 3 sec off in the led in microcontroller program…can u tell me the coding

    • No we can’t. You look smart enough to figure it out on your own. Enjoy!

      • [CODE REMOVED BY ADMIN]
        led on led off
        1sec 5sec
        2sec 5sec
        3 sec 5 sec
        output
        ths program just modify oly led off time…
        output comes nw
        led on led off
        1sec 1sec
        2sec 2sec
        3 sec 3 sec
        how to change in oly led off time.
        in 1sec 2 sec 3 sec

        • Dinesh, say what? I don’t understand your question. Could you please elaborate it and use full English sentences? And please use pastebin.com to share code. Thanks!

  9. i send the program that website..but i didnt get any reply

    • What website? Where did you post your code? I asked you to share your code using pastebin.com.

      • i shared that website..but i didnt get any reply for u …

        • Where’s the link? You need to send me the link to the code.

  10. [CODE REMOVED BY ADMIN]
    this is a code for distance measurement using ultrasonic sensors.I do not know what is the error.please guide me.
    Thanks.

    • Sorry Vaishali, but we help those who help themselves (which does not include throwing the code at someone and asking to find errors). We are too busy to compile someone’s code and find out the errors for free. Find the errors yourself, then explain it to us what you did, what you observed and what you think you should do. Then and only then there’s a possibility of us helping you out. Have fun! Cheers!

  11. Dear max,
    how to get maximum delay (say 30 min) using 8 bit timer?

    • What do you mean by maximum delay?

  12. I need your knowledge for this. please? :(((((((((((((
    could you help us to explain this code?

    [CODE REMOVED BY ADMIN]

  13. 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!

Trackbacks/Pingbacks

  1. Introduction to AVR Timers « maxEmbedded - [...] TIMER0 - 8-bit timer [...]
  2. AVR Timers – TIMER1 « maxEmbedded - [...] AVR Timers – TIMER0 [...]
  3. AVR Timers – TIMER2 « maxEmbedded - [...] AVR Timers – TIMER0 [...]
  4. AVR Timers – CTC Mode « maxEmbedded - [...] 8-bit TIMER0 [...]
  5. AVR Timers – PWM Mode – Part I « maxEmbedded - [...] AVR TIMER0 [...]
  6. AVR Timers – PWM Mode – Part II « maxEmbedded - [...] have come across this register in my Timer0 tutorial. Here, we will learn how to set appropriate bits to …
  7. AVR-Timer | Annotary - [...] More from Budi Prakosa: AVR-Interrupt AVR electronics …

Post a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>