Timers are standard features of almost every microcontroller. So it is very important to learn their use. Since an AVR microcontroller has very powerful and multifunctional timers, the topic of timer is somewhat “vast”. Moreover there are many different timers on chip. So this section on timers will be multipart. I will be giving basic introduction first.
What is a timer ?
A timer in simplest term is a register. Timers generally have a resolution of 8 or 16 Bits. So a 8 bit timer is 8Bits wide so capable of holding value withing 0-255. But this register has a magical property ! Its value increases/decreases automatically at a predefined rate (supplied by user). This is the timer clock. And this operation does not need CPU’s intervention.Fig.: Basic Operation Of a Timer. |
Fig.: Basic Operation Of a Timer. |
Using The 8 BIT Timer (TIMER0)
The ATmega16 and ATmega32 has three different timers of which the simplest is TIMER0. Its resolution is 8 BIT i.e. it can count from 0 to 255. Note: Please read the “Internal Peripherals of AVRs” to have the basic knowledge of techniques used for using the OnChip peripherals(Like timer !) The Prescaler The Prescaler is a mechanism for generating clock for timer by the CPU clock. As you know that CPU has a clock source such as a external crystal of internal oscillator. Normally these have the frequency like 1 MHz,8 MHz, 12 MHz or 16MHz(MAX). The Prescaler is used to divide this clock frequency and produce a clock for TIMER. The Prescaler can be used to get the following clock for timer. No Clock (Timer Stop). No Prescaling (Clock = FCPU) FCPU/8 FCPU/64 FCPU/256 FCPU/1024 Timer can also be externally clocked but I am leaving it for now for simplicity.TIMER0 Registers.
As you may be knowing from the article “Internal Peripherals of AVRs” every peripheral is connected with CPU from a set of registers used to communicate with it. The registers of TIMERs are given below.
TCCR0 – Timer Counter Control Register. This will be used to configure the timer.
Fig.: TCCR0 - Timer Counter Control Register 0 |
As you can see there are 8 Bits in this register each used for certain purpose.
For this tutorial I will only focus on the last three bits CS02 CS01 CS00 They
are the CLOCK SELECT bits. They are used to set up the Prescaler for timer.
TCNT0 – Timer Counter 0
Timer Interrup Mask Register TIMSK
This register is used to activate/deactivate interrupts related with timers. This register controls the interrupts of all the three timers. The last two bits (BIT 1 and BIT 0) Controls the interrupts of TIMER0. TIMER0 has two interrupts but in this article I will tell you only about one(second one for next tutorial). TOIE0 : This bit when set to “1” enables the OVERFLOW interrupt. Now time for some practical codes !!! We will set up timer to at a Prescaler of 1024 and our FCPU is 16MHz. We will increment a variable “count” at every interrupt(OVERFLOW) if count reaches 61 we will toggle PORTC0 which is connected to LED and reset “count= 0”. Clock input of TIMER0 = 16MHz/1024 = 15625 Hz Frequency of Overflow = 15625 /256 = 61.0352 Hz if we increment a variable “count” every Overflow when “count reach 61” approx one second has elapse.
Setting Up the TIMER0
// Prescaler = FCPU/1024 TCCR0|=(1<<CS02)|(1<<CS00);
//Enable Overflow Interrupt Enable TIMSK|=(1<<TOIE0);
//Initialize Counter TCNT0=0;Now the timer is set and firing Overflow interrupts at 61.0352 Hz
The ISR
ISR(TIMER0_OVF_vect)
{
//This is the interrupt service routine for TIMER0 OVERFLOW Interrupt.
//CPU automatically call this when TIMER0 overflows.
//Increment our variable
count++;
if(count==61)
{
PORTC=~PORTC; //Invert the Value of PORTC
count=0;
}
}
Demo Program (AVR GCC)
Blink LED @ 0.5 Hz on PORTC[3,2,1,0]
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t count;
void main()
{
// Prescaler = FCPU/1024
TCCR0|=(1<<CS02)|(1<<CS00);
//Enable Overflow Interrupt Enable
TIMSK|=(1<<TOIE0);
//Initialize Counter
TCNT0=0;
//Initialize our varriable
count=0;
//Port C[3,2,1,0] as out put
DDRC|=0x0F;
//Enable Global Interrupts
sei();
//Infinite loop
while(1);
}
ISR(TIMER0_OVF_vect)
{
//This is the interrupt service routine for TIMER0 OVERFLOW Interrupt.
//CPU automatically call this when TIMER0 overflows.
//Increment our variable
count++;
if(count==61)
{
PORTC=~PORTC; //Invert the Value of PORTC
count=0;
}
}
Hardware
ATmega16 or ATmega32 running @ 16MHz. Connet LEDs using 330ohms resistors on PORTC[3,2,1,0]. If you are using xBoard you can connect four onboard LEDs to PORTC using four PIN Connectors. Thats it for now meet in next tutorial. And please don't forget to post a comment, I am waiting for them !
Move On ...
Download PDF version | Get Adobe Reader Free !!!


You do not need to mark a global variable volatile, am I wrong?
I liked the way you explained the timer so much.
Kind Regards,
Mahmoud
wil u plz tell me what do u mean by volatile variable and when v declare it
No I will NOT because it is already explained in every book on C! And it is assumed that an embedded developer knows C well. Or atleast has 3 or 4 book on C on his/her book self.
Bye.
With embedded programming the variables which are used/altered by the interrupt routines need to be declared as global volatiles.
I usually stick them just after my #defines and before my functions. Because they are defined outside of any functions, even main(), enables the variable to be accessed by all the functions in the program.
The variable is declared as volatile to stop the complier assuming the variable is a constant.
This drove me nuts when I was just learning
sir,
i want 2 control speed of bldc motor by pwm using atmega8.i want 2 vary speed from 1ms to 2ms.eg at 1ms,1.25ms,1.50,1.75ms,2ms at 50hz.will u plz tell me abt how 2 code in c.how prescaler should set or mail me code in c for 1ms at 50hz.
thank you
Really amazing sir,
I have some doubt about PWM
How can I contact you sir?
My mail-aji_maxim@yahoo.in
@Ajit Kumar,
so what you have done with the above comment? Funny.
Thanks
Hi Avinash. I like all your tutorials. I have some questions.
1st. I port your code to ATMega8,but now I can detect is button presed on ports. Why??
2nd. You said that about second type of interrupt of Timer0 you will tell in next tut, but next tut is about timer1.
3rd. Why you stopped writing articles??
Thnx.And sorry for silly questions I’m new in uC’s.
@Garegin!
3rd. Why you stopped writing articles??
Ha ha !
Will write now, may be from next month.
And please Avinash write an article about TWI(I2C). I need to understand it , but all articles in i-net are pieces of shit.
Thanks. I’m waiting for your articles, because now is next month.
THANKS.Really helped me a lot.I was having trouble to understand interrupts ,not anymore “yay”.after this I used TIMER1 and OCR1A(for PWM) also TIMER2…it’s fun AVR interrupts .
you’re great! thanks for all the informations inside your site!!
very good explanation
Thank you
Thanks.I find my question.
the a above comments are getting printed incorrectly no idea know why??
my actual code is :
int main()
{
DDRB |= 0b00000001;
PORTB |= 0b00000000;
TCCR0|=(1<<CS02)|(1< 254)
{
count++;
if(count == 61)
{
count = 0;
PORTB ^= (1 << PINB0);
}
}
}
}
but i m not getting my led blinking as expected.
done same thing with interrupt i m getting the proper output
As ,i am new in embedded c so plz help me as :i want to generate 1 mhz waveform in pwm in atmega32,how i can code in c.
What is TOIE0 ? There is no description of it and tutorial goes very fast !
awesome work here!!
hi!..i wanted to display the count value on an lcd after the timer has been started and stopped whenever the i/p makes a high to low transition…can i do it by jus passing the value of tcnt reg as a char to the lcd??..i dunno wer the exact count value will be stored and if it can be acccessed directly and given to an o/p port…
@Vrinda,
When ever you are trying to do anything in any field, first you need to know the basic very well! Thorough understanding of basic is very much important. I hate to see people with confused idea?
Do you know anything about character representation in computers and ASCII code?
yea i do know about ascii code..atleast i did try converting the timer value to ascii and then transferred it to the o/p port which is inturn connected to the lcd…..sorry about not putting the question properly…i wanted a sequential display rather than the final value of the timer
Dear sir i am repairing a watch so that for after every 60 seconds i have to generate a waveform that will further drive my watch’s minute’s niddle…i have generated a delay of 60 seconds but using the same timer i am unable to generate a waveform for only 250 ms…because i have used 4Mhz clock with 64 as prescale…so my timer clock is reduced as 15625 Khz…for 1 sec i will have to put 15624 in TCNT1…i run a loop at 60 times then i wll get 60 seconds delay but for 250 ms its value goes out of range as 16 bit timer registers max limit(65536)…so what should i do?
can u plz help me my dear…..
nice work.I need ur help. I want to reset and restart digital watch using a same switch as I want to display digital watch.Here is my code:
if(!(PINB & (1<<PB4)))
{
TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);
}
else
{
clock_millisecond=0;
second=0;
minute=0;
hour=0;
TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);
}
Here in if condition first clock is incrementing its value but in else statement the clock is set to 0 and second clock is not incrementing its value.Please help i want to increment both clock after resetting it to 0 using a single switch.Plz help