AVR Timer Tutorial
AVR Timer Tutorial
3 Votes
Timers
You come across timers everyday. Simplest example hangs on your wall or maybe tied around your
wrist. You can say that they have a unique property to measure time. Everything in this world is
synchronized with time. You wake up at, say, 6 o’clock; you work everyday for 8 hours; you need to
drink water every 4 hours, etc. But the concept of timers isn’t confined to your daily routines. Every
electronic component works on a time base. This time base helps to keep all the work synchronized.
Without a time base, you would have no idea as to when to do a particular thing.
Thus, timers is an important concept in the field of electronics. You can generate a time base using a
timer circuit, using a microcontroller, etc. Since all the microcontrollers work at some predefined
clock frequency, they all have a provision to set up timers.
AVR boasts of having a timer which is very accurate, precise and reliable. It offers loads of features
in it, thus making it a vast topic. In this tutorial, we will discuss the basic concepts of AVR Timers.
We will not be dealing with any code in this tutorial, just the concepts. The procedure of generating
timers and their codes will be discussed in subsequent posts.
Timers as registers
So basically, a timer is a register! But not a normal one. The value of this register
increases/decreases automatically. In AVR, timers are of two types: 8-bit and 16-bit timers. In an 8-
bit timer, the register used is 8-bit wide whereas in 16-bit timer, the register width is of 16 bits.
This means that the 8-bit timer is capable of counting 2^8=256 steps from 0 to 255 as
demonstrated below.
8 bit Counter
Similarly a 16 bit timer is capable of counting 2^16=65536 steps from 0 to 65535. Due to this
feature, timers are also known as counters. Now what happens once they reach their MAX? Does
the program stop executing? Well, the answer is quite simple. It returns to its initial value of zero. We
say that the timer/counter overflows.
In ATMEGA32, we have three different kinds of timers:
TIMER0 - 8-bit timer
TIMER1 – 16-bit timer
TIMER2 – 8-bit timer
The best part is that the timer is totally independent of the CPU. Thus, it runs parallel to the CPU and
there is no CPU’s intervention, which makes the timer quite accurate.
Apart from normal operation, these three timers can be either operated in normal mode, CTC mode
orPWM mode. We will discuss them one by one.
Timer Concepts
Basic Concepts
Since childhood, we have been coming across the following formula:
The Prescaler
Assuming F_CPU = 4 MHz and a 16-bit timer (MAX = 65535), and substituting in the above formula,
we can get a maximum delay of 16.384 ms. Now what if we need a greater delay, say 20 ms? We are
stuck?!
Well hopefully, there lies a solution to this. Suppose if we decrease the F_CPU from 4 MHz to 0.5
MHz (i.e. 500 kHz), then the clock time period increases to 1/500k = 0.002 ms. Now if we
substituteRequired Delay = 20 ms and Clock Time Period = 0.002 ms , we get Timer Count =
9999. As we can see, this can easily be achieved using a 16-bit timer. At this frequency, a maximum
delay of 131.072 ms can be achieved.
Now, the question is how do we actually reduce the frequency? This technique of frequency division
is called prescaling . We do not reduce the actual F_CPU. The actual F_CPU remains the same (at 4
MHz in this case). So basically, we derive a frequency from it to run the timer. Thus, while doing so,
we divide the frequency and use it. There is a provision to do so in AVR by setting some bits which
we will discuss later.
But don’t think that you can use prescaler freely. It comes at a cost. There is a trade-off between
resolution and duration. As you must have seen above, the overall duration of measurement has
increased from a mere 16.384 ms to 131.072 ms. So has the resolution. The resolution has also
increased from 0.00025 ms to 0.002 ms. This means each tick will take 0.002 ms. So, what’s the
problem with this? The problem is that the accuracy has decreased. Earlier, you were able to measure
duration like 0.1125 ms accurately (0.1125/0.00025 = 450), but now you cannot (0.1125/0.002 =
56.25). The new timer can measure 0.112 ms and then 0.114 ms. No other value in between.
Choosing Prescalers
Let’s take an example. We need a delay of 184 ms (I have chosen any random number). We have
F_CPU = 4 MHz. The AVR offers us the following prescaler values to choose from: 8, 64, 256 and
1024. A prescaler of 8 means the effective clock frequency will be F_CPU/8. Now substituting each of
these values into the above formula, we get different values of timer value. The results are
summarized as below:
Choosing Prescaler
Now out of these four prescalers, 8 cannot be used as the timer value exceeds the limit of 65535.
Also, since the timer always takes up integer values, we cannot choose 1024 as the timer count is a
decimal digit. Hence, we see that prescaler values of 64 and 256 are feasible. But out of these two,
we choose 64 as it provides us with greater resolution. We can choose 256 if we need the timer for a
greater duration elsewhere.
Thus, we always choose prescaler which gives the counter value within the feasible limit (255
or 65535) and the counter value should always be an integer.
We will discuss how to implement it in later posts.
Interrupts
Well, this is not exclusively related to timers, but I thought of discussing it as it is used in a variety of
places. Let me explain it using an analogy. Say now you are reading my post. It’s dinner time and
your mom (only if you live with your mom ) calls you for dinner. What do you do (if she gets too
creepy)? You save your work and attend to your mom’s call, then return and resume reading. This is
an example of interrupt.
In most microcontrollers, there is something called interrupt. This interrupt can be fired whenever
certain conditions are met. Now whenever an interrupt is fired, the AVR stops and saves its execution
of the main routine, attends to the interrupt call (by executing a special routine, called the Interrupt
Service Routine, ISR) and once it is done with it, returns to the main routine and continues executing
it.
For example, in the condition of counter overflow, we can set up a bit to fire an interrupt whenever
an overflow occurs. Now, during execution of the program, whenever an overflow occurs, an
interrupt is fired and the CPU attends to the corresponding ISR. Now it’s up to us what do we want to
do inside the ISR. We can toggle the value of a pin, or increment a counter, etc etc.
If you didn’t get the concept of interrupts and ISR, behold for sometime till we discuss it how to
implement it in hardware.
So folks, I guess this much is enough for you to get a hold of what timers are and the features of
AVR Timers. From the next post, we will implement these concepts and learn how to code the AVR!
So grab the RSS feeds or subscribe to my blog to stay updated! And don’t forget to post your
response down below!
4 Votes
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).
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.
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()
// initialize counter
TCNT0 = 0;
int main(void)
// initialize timer
timer0_init();
// loop forever
while(1)
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
instead of
if (TCNT0 == 191)
This is because sometimes due to missed compares or unexpected increment, this condition
maynever be true. Thus to remain on the safer side, we use ‘>=’ instead of ‘==’.
Code
#include <avr/io.h>
void timer0_init()
// initialize counter
TCNT0 = 0;
}
int main(void)
// initialize timer
timer0_init();
// loop forever
while(1)
ISR(TIMER0_OVF_vect)
tot_overflow++;
}
int main(void)
// initialize timer
timer0_init();
// loop forever
while(1)
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
bitTOIE0. 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>
void timer0_init()
// initialize counter
TCNT0 = 0;
tot_overflow = 0;
ISR(TIMER0_OVF_vect)
tot_overflow++;
int main(void)
// initialize timer
timer0_init();
// loop forever
while(1)
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!
] AVR Timers – TIMER1
Filed under: Atmel AVR, AVR Timers — 11 Comments
June 28, 2011
1 Vote
TCCR1B Register
Right now, only the highlighted bits concern us. The bit 2:0 – CS12:10 are the Clock
Select Bitsof TIMER1. Their selection is as follows.
TIMSK Register
As we have discussed earlier, this is a common register for all the timers. The bits
associated with other timers are greyed out. Bits 5:2 correspond to TIMER1. Right
now, we are interested in the yellow bit only. Other bits are related to CTC mode which
we will discuss later. Bit 2 – TOIE1 – Timer/Counter1 Overflow Interrupt Enable bit
enables the overflow interrupt of TIMER1. We enable the overflow interrupt as we are
making the timer overflow 61 times (refer to the methodology section above).
TIFR Register
The Timer/Counter Interrupt Flag Register – TIFR is as follows.
TIFR Register
Once again, just like TIMSK, TIFR is also a register common to all the timers. The
greyed out bits correspond to different timers. Only Bits 5:2 are related to TIMER1. Of
these, we are interested in Bit 2 – TOV1 – Timer/Counter1 Overflow Flag. This bit is
set to ’1′ whenever the timer overflows. It is cleared (to zero) automatically as soon as
the corresponding Interrupt Service Routine (ISR) is executed. Alternatively, if there is
no ISR to execute, we can clear it by writing ’1′ to it.
Code
Now that we are aware of the methodology and the registers, we can proceed to write
the code for it. To learn about I/O port operations in AVR, view this. To know about bit
manipulations, view this. To learn how to use AVR Studio 5, view this. To learn how
this code is structured, view the previous TIMER0 post.
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init()
// initialize counter
TCNT1 = 0;
tot_overflow = 0;
ISR(TIMER1_OVF_vect)
tot_overflow++;
int main(void)
// initialize timer
timer1_init();
// loop forever
while(1)
// do nothing
So folks, this is how to apply the basic timer concepts for TIMER1. Please note that if
you learn the basics, everything will be easy. If you find yourself struggling with the
code, then please visit the TIMER0 tutorial, clear your concepts and give it a try again.
If still you don’t get it, I will be glad to help you!
In my next post, we will learn how to apply the same concepts to TIMER2. It is, once
again, an 8-bit timer. Thus all the TIMER2 registers are similar to TIMER0. After that,
we move towards the interesting part, the Clear Timer on Compare (CTC) mode!
Till then, grab the RSS Feeds or subscribe to my blog to stay updated! Also, post
your responses below. I am awaiting for them!
ADVERTISEMENT
Share this:
Facebook1
Twitter2
More
Like this:
Like
Be the first to like this post.
Muhib Raza
Thanks Muhib! The font which is used comes along with the theme. I will try to get
a font upgrade for my theme soon. Till then, please bear with me. Thanks a lot for
your suggestion!
Reply
Mohan
Nice tutorials please update soon for counters also..very nice work keep it up
Reply
Atra
Radha
Very helpful I have a question, suppose i want to use an ATMEGA 8L, it has an
internal clock of 1MHz frequency right? can that be prescaled to?
Also i was told that, to make the micro recognise that we are using an external crystal ,
we need to set somthing called FUSE BITS . What is that? please explain.
Thank you
Reply
o
Mayank
Hello Radha
Yes, the internal clock frequency can also be prescaled to the desired level.
In AVR, there are three bytes of memory reserved for fuses. These bytes determine
how the microcontroller will behave (like the bootloader, JTAG, clock, etc). By
default (in a newly bought microcontroller), the fuses are set so that it works
according to the internal clock of the microcontroller. Simply buying an external
crystal and fixing it across the XTAL pins of the microcontroller won’t make the
microcontroller to work at that frequency. You have to tell the microcontroller to
follow the external clock source instead of the internal one. This is done by setting
proper fuses. But beware, fuses are set only once. Once you have set the wrong
fuses, your microcontroller will be rendered useless.
For details, refer this tutorial.
Reply
5 Trackbacks / Pingbacks for this entry:
AVR Timers – TIMER0 « maxEmbedded
[...] AVR Timers – TIMER1 « maxEmbedded [...]
Introduction to AVR Timers « maxEmbedded
[...] TIMER1 – 16-bit timer [...]
AVR Timers – TIMER2 « maxEmbedded
[...] AVR Timers – TIMER1 [...]
AVR Timers – CTC Mode « maxEmbedded
[...] 16-bit TIMER1 [...]
AVR Timers – PWM Mode – Part I « maxEmbedded
[...] AVR TIMER1 [...]
Problem Statement
We need to flash an LED every 50 ms. We have an XTAL of 16 MHz. This is the same problem
statement that we discussed in TIMER0 (the last one). We will implement the same using TIMER2.
TCCR2 Register
The Timer/Counter Control Register – TCCR2 is as follows:
TCCR2 Register
Since we will be dealing with the CTC mode later, we are only concerned with Bits2:0 – CS22:20 –
Clock Select Bits. Unlike other timers, TIMER2 offers us with a wide range of prescalers to choose
from. In TIMER0/1 the prescalers available are 8, 64, 256 and 1024, whereas in TIMER2, we have 8,
32, 64, 128, 256 and 1024!
TCNT2 Register
In the Timer/Counter Register – TCNT2, the value of he timer is stored. Since TIMER2 is an 8-bit
timer, this register is 8 bits wide.
TCNT2 Register
TIMSK Register
The Timer/Counter Interrupt Mask – TIMSK Register is as follows. It is a register common to all the
timers.
TIMSK Register
Here we are concerned with the 6th bit – TOIE2 – Timer/Counter2 Overflow Interrupt Enable . We
set this to ’1′ in order to enable overflow interrupts.
TIFR Register
The Timer/Counter Interrupt Flag Register – TIFR is as follows. It is a register common to all the
timers.
TIFR Register
Here we are concerned with the 6th bit – TOV2 – Timer/Counter2 Overflow Flag . This bit is set
(one) whenever the timer overflows. It is cleared automatically whenever the corresponding Interrupt
Service Routine (ISR) is executed. Alternatively, we can clear it by writing ’1′ to it.
Code
To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this. To
learn how this code is structured, view the TIMER0 post. To learn how to use AVR Studio 5, view this.
#include <avr/io.h>
#include <avr/interrupt.h>
void timer2_init()
{
// initialize counter
TCNT2 = 0;
sei();
tot_overflow = 0;
ISR(TIMER2_OVF_vect)
int main(void)
// initialize timer
timer2_init();
// loop forever
while(1)
So friends, this is how to operate TIMER2 in general mode. Other modes of operation will be
discussed in upcoming posts. In the next post, we will learn about the Clear Timer on Compare
(CTC) Mode and learn how to apply it to different timers.
So till then, grab the RSS Feeds or subscribe to my blog to stay updated! And please don’t
forget to leave a reply below. I will be happy to see them!
2 Votes
// ...
// ...
// ...
// ...
Here, we have used the example of TIMER1. Since TIMER1 is a 16-bit timer, it can
count upto a maximum of 65535. Here, what we desire is that the timer (process
value) should reset as soon as its value becomes equal to (or greater than) the set
point of 39999.
So basically, the CTC Mode implements the same thing, but unlike the above example,
it implements it in hardware. Which means that we no longer need to worry about
comparing the process value with the set point every time! This will not only avoid
unnecessary wastage of cycles, but also ensure greater accuracy (i.e. no missed
compares, no double increment, etc).
Hence, this comparison takes place in the hardware itself, inside the AVR CPU! Once
the process value becomes equal to the set point, a flag in the status register is set
and the timer is reset automatically! Thus goes the name – CTC – Clear Timer
on Compare! Thus, all we need to do is to take care of the flag, which is much more
faster to execute.
Let us analyze this CTC Mode in detail with the help of a problem statement.
Problem Statement
Let’s take up a problem statement to understand this concept. We need to flash an LED
every 100 ms. We have a crystal of XTAL 16 MHz.
Methodology – Using CTC Mode
Before proceeding any further, let’s jot down the formula first. I also recommend you
to read myTIMER0 tutorial in order to understand this better. I won’t be revising
the basic concepts here, just their application.
TCCR1B Register
You are already aware of the Clock Select Bits – CS12:0 in TCCR1B (if not, view
the TIMER1 post, scroll down a bit and you will find it there). Hence, right now, we are
concerned with the Wave Generation Mode Bits – WGM13:0. As you can see, these
bits are spread across both the TCCR1 registers (A and B). Thus we need to be a bit
careful while using them. Their selection is as follows:
OCR1A Register
OCR1B Register
Since the compare value will be a 16-bit value (in between 0 and 65535), OCR1A and
OCR1B are 16-bit registers. In ATMEGA16/32, there are two CTC channels – A and B.
We can use any one of them or both. Let’s use OCR1A.
TIFR Register
The Timer/Counter Interrupt Flag Register – TIFR is as follows. It is a common
register to all the timers.
TIFR Register
We are interested in Bit 4:3 – OCF1A:B – Timer/Counter1, Output Compare A/B
Match Flag Bit. This bit is set (one) by the AVR whenever a match occurs i.e. TCNT1
becomes equal to OCR1A (or OCR1B). It is cleared automatically whenever the
corresponding Interrupt Service Routine (ISR) is executed. Alternatively, it can be
cleared by writing ’1′ to it!
Code
Now that we are aware of the methodology and the registers, we can proceed to write
the code for it. To learn about I/O port operations in AVR, view this. To know about bit
manipulations, view this. To learn how to use AVR Studio 5, view this. To learn how
this code is structured, view the previous TIMER0 post.
#include <avr/io.h>
void timer1_init()
// initialize counter
TCNT1 = 0;
int main(void)
// initialize timer
timer1_init();
// loop forever
while(1)
{
PORTC ^= (1 << 0); // toggles the led
So, now you have an LED flashing every 100 ms! Now let’s use another methodology
to sort out the same problem statement.
Methodology – Using Interrupts with CTC Mode
In the previous methodology, we simply used the CTC Mode of operation. We used
to check every time for the flag bit (OCF1A). Now let’s shift this responsibility to the
AVR itself! Yes, now we do not need to check for the flag bit at all! The AVR will
compare TCNT1 with OCR1A. Whenever a match occurs, it sets the flag bit OCF1A,
and also fires an interrupt! We just need to attend to that interrupt, that’s it! No other
headache of comparing and stuffs!
There are three kinds of interrupts in AVR – overflow, compare and capture. We have
already discussed the overflow interrupt in previous posts. For this case, we need to
enable the compareinterrupt. The following register is used to enable interrupts.
TIMSK Register
The Timer/Counter Interrupt Mask Register- TIMSK Register is as follows. It is a
common register to all the timers. The greyed out bits correspond to other timers.
TIMSK Register
We have already come across TOIE1 bit. Now, the Bit 4:3 – OCIE1A:B –
Timer/Counter1, Output Compare A/B Match Interrupt Enable bits are of our
interest here. Enabling it ensures that an interrupt is fired whenever a match occurs.
Since there are two CTC channels, we have two different bits OCIE1A and OCIE1B for
them.
Thus, to summarize, whenever a match occurs (TCNT1 becomes equal to OCR1A =
24999), an interrupt is fired (as OCIE1A is set) and the OCF1A flag is set. Now since an
interrupt is fired, we need an Interrupt Service Routine (ISR) to attend to the interrupt.
Executing the ISR clears the OCF1A flag bit automatically and the timer value (TCNT1)
is reset.
Interrupt Service Routine (ISR)
Now let’s proceed to write an ISR for this. The ISR is defined as follows:
ISR (TIMER1_COMPA_vect)
Okay, that’s all we need to do in the ISR. Now let’s see how the actual code looks like.
Final Code
To learn about I/O port operations in AVR, view this. To know about bit manipulations,
view this. To learn how to use AVR Studio 5, view this. To learn how this code is
structured, view the previous TIMER0 post.
#include <avr/io.h>
#include <avr/interrupt.h>
// initialize timer, interrupt and variable
void timer1_init()
// initialize counter
TCNT1 = 0;
OCR1A = 24999;
sei();
int main(void)
// initialize timer
timer1_init();
// loop forever
while(1)
// do nothing
// done!
}
Hence, now we have seen how to implement the CTC mode using interrupts, reducing
the code size, comparisons and processing time. But this is not over yet! We can
reduce them further! Let’s take the same problem statement.
ATMEGA16/32 OC Pins
Methodology – Using Hardware CTC Mode
Okay, so now, all of you have a look at the pin configuration of ATMEGA16/32. Can
you see the pins PB3, PD4, PD5 and PD7? Their special functions are mentioned in the
brackets (OC0, OC1A, OC1B and OC2). These are the Output Compare pins of TIMER0,
TIMER1 and TIMER2 respectively. Before we learn how to use them, let’s have another
look at the TCCR1A register.
TCCR1A Register
The Timer/Counter1 Control Register A – TCCR1A Register is as follows:
TCCR1A Register
Now time for us to concentrate on Bit 7:6 – COM1A1:0 and Bit 5:4 – COM1B1:0 –
Compare Output Mode for Compare Unit A/B. These bits control the behaviour of
the Output Compare (OC) pins. The behaviour changes depending upon the following
modes:
Non-PWM mode (normal / CTC mode)
Fast PWM mode
Phase Correct / Phase & Frequency Correct PWM mode
Right now we are concerned only with the CTC mode. The following options hold good
for non-PWM mode.
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init()
{
// initialize counter
TCNT1 = 0;
OCR1A = 24999;
int main(void)
// initialize timer
timer1_init();
// loop forever
while(1)
// do nothing
// done!
TCCR1A Register
If you see clearly, it’s mentioned that these bits are write only bits. They are active only
in non-PWM mode. Well, for ensuring compatibility with future devices, these bits must
be set to zero (which they already are by default). Setting them to ‘1’ will result in an
immediate forced compare match and the effect will be reflected in the OC1A/OC1B
pins. The thing to be noted is that FOC1A/FOC1B will not generate any
interrupt, nor will it clear the timer in CTC mode.
CTC Mode – TIMER0
Till now we have explored CTC mode of TIMER1. In this section, I will describe the CTC
mode of TIMER0 in brief. In other words, we will discuss about the registers only. We
will not take a problem statement this time, because I assume that you have read
whatever is written above and can use CTC mode of TIMER0 exactly in the same way!
So let’s get started.
TCCR0 Register
The Timer/Counter0 Control Register– TCCR10 Register is as follows:
TCCR0 Register
Bit 6:3 – WGM01:0 – Wave Generation Mode – Just like in TIMER1, we choose
the type of wave mode from here as follows. Choose 10 for CTC mode.
OCR0 Register
The value to be compared (max 255) is stored in this register.
TIMSK Register
The Timer/Counter Interrupt Mask– TIMSK Register is as follows:
TIMSK Register
The Bit 1 – OCIE0 – Timer/Counter0 Output Compare Match Interrupt
Enable enables the firing of interrupt whenever a compare match occurs.
TIFR Register
The Timer/Counter Flag Register– TIFR is as follows:
TIFR Register
The Bit 1 – OCF0 – Output Compare Flag 0 is set whenever a compare match occurs.
It is cleared automatically whenever the corresponding ISR is executed. Alternatively it
is cleared by writing ‘1’ to it.
That’s it! With this much information, I am sure that you can successfully generate a
timer in CTC mode of TIMER0.
CTC Mode – TIMER2
Well, I leave this to you! It is exactly similar to the TIMER0 CTC Mode! Just go through
the datasheet and you are through!!
Well, that’s all for CTC Mode. I hope you enjoyed reading it! In the next post, we will
discuss the different PWM modes and how to generate them.
So till then, subscribe to my blog to stay updated! Alternatively, you can also
grab the RSS Feeds for that!
Thank You!
Mayank Prasad
[email protected]
Share this:
Facebook3
Twitter2
More
Like this:
Like
Be the first to like this post.
hemanth
2 Votes
Welcome back! Till now, in the AVR Timers, we have discussed regarding the
timer concepts, prescalers, interrupts, ctc mode, etc. Refer to the following tutorials for them.
Introduction to AVR Timers
AVR TIMER0
AVR TIMER1
AVR TIMER2
AVR Timers – CTC Mode
In this tutorial, I will introduce you to another mode of AVR Timers – PWM Mode.
Introduction
Let us assume that a DC motor is connected to the power supply as follows.
Motor 12V 300rpm
The motor is rated 12V/300rpm. This means that (assuming ideal conditions) the motor will run at
300 rpm only when 12V DC is supplied to it. If we apply 6V, the motor will run at only 150 rpm. For
more details regarding controlling DC motor using AVR, view this. Now let us provide the following
signal (12V DC) to the motor.
12V DC Supply
The motor will rotate at 300 rpm. Now let us change the voltage level as follows (6V DC).
6V DC Supply
We find that the motor rotates at 150 rpm. Now let us change the voltage level once again as follows
(0V DC).
0V DC Supply
This time, unsurprisingly, the motor doesn’t run at all. Okay, so let’s make it more interesting. What
if we provide the following supply to the motor.
50% Duty Cycle PWM
Now how will the motor respond? Will it start for some time, then after some time it stops, then
starts, then stops, and then starts again, and so on. Or will it get confused and simply blast?
Well, each and every body in this world has some inertia. Say the motor above rotates whenever it is
powered on. As soon as it is powered off, it will tend to stop. But it doesn’t stop immediately, it
takes some time. But before it stops completely, it is powered on again! Thus it starts to move. But
even now, it takes some time to reach its full speed. But before it happens, it is powered off, and so
on. Thus, the overall effect of this action is that the motor rotates continuously, but at a lower
speed. In the above case, the motor will behave exactly as if a 6V DC is supplied to it, i.e. rotate at
150 rpm!
Okay, so now, let’s modify the signal as follows.
PWM Generation
The simplest way to generate a PWM signal is by comparing the a predetermined waveform with a
fixed voltage level as shown below.
Compare PWM
In the diagram shown above, we have a predetermined waveform, sawtooth waveform.
Wecompare this waveform with a fixed DC level. It has three compare output modes of operation:
Inverted Mode - In this mode, if the waveform value is greater than the compare level, then
the output is set high, or else the output is low. This is represented in figure A above.
Non-Inverted Mode - In this mode, the output is high whenever the compare level is
greater than the waveform level and low otherwise. This is represented in figure B above.
Toggle Mode - In this mode, the output toggles whenever there is a compare match. If the
output is high, it becomes low, and vice-versa.
But it’s always not necessary that we have a fixed compare level. Those who have had exposure in
the field of analog/digital communication must have come across cases where a sawtooth carrier
wave is compared with a sinusoidal message signal as shown below.
PWM Modulation
Here you can clearly see and understand the meaning of ‘width’ in Pulse Width Modulation!
PWM can also be generated by making analog circuits like the one described here.
Duty Cycle
The Duty Cycle of a PWM Waveform is given by
Fast PWM
Consider the following diagram.
Fast PWM
In simple terms, this is Fast PWM! We have a sawtooth waveform, and we compare it with a fixed
voltage level (say A), and thus we get a PWM output as shown (in A). Now suppose we increase the
compare voltage level (to, say B). In this case, as we can see, the pulse width has reduced, and hence
the duty cycle. But, as you can see, both the pulses (A and B) end at the same time irrespective of
their starting time.
In this mode, since sawtooth waveform is used, the timer counter TCNTn (n = 0,1,2) counts from
BOTTOM to TOP and then it is simply allowed to overflow (or cleared at a compare match) to
BOTTOM.
Making Choices
Now that you are familiar with all the PWM concepts, it’s upto you to decide
Which timer to choose?
Which mode of operation to choose?
Which compare output mode to choose?
Choosing Timer
In AVR, PWM Mode is available in all timers. TIMER0 and TIMER2 provide 8bit accuracy whereas
TIMER1 provides 16bit accuracy. In 8bit accuracy, you have 256 individual steps, whereas in 16bit
accuracy, you have 65536 steps.
Now suppose you want to control the speed of a DC motor. In this case, having 65536 steps is
totally useless! Thus we can use an 8bit timer for this. Even 8bit is too much, but there is no other
choice. Obviously there isn’t much difference in speed between 123/256th and 124/256th of full
speed in case of a motor! But if you use servo motors, you have to use 16bit timer. More on that
later.
If you need quite high resolution in your application, go for 16bit timer.
January 7, 2012
There are three modes of PWM operation - Fast PWM, Phase Correct PWM and Frequency and Phase Correct
PWM
How to choose timer, operation mode and compare output mode for generating the desired PWM.
So now, without much hassle, let’s see how to implement it using the AVR microcontrollers. Before we proceed, I suggest
you to go through my previous posts on Timers and PWM.
Problem Statement
Let us take a problem statement. We need to generate a 50 Hz PWM signal having 45% duty cycle.
Analysis
Given that
Frequency = 50 Hz
T(on) = 9 ms
T(off) = 11 ms
#include <avr/io.h>
#include <avr/interrupt.h>
void timerX_init()
// initialize counter
ISR (TIMERx_COMPA_vect)
{
// do whatever you want to do here
count++;
if (count % 2 == 0)
else
int main(void)
// initialize timerX
timerX_init();
// loop forever
while(1)
// do nothing
Now this is one method. And it’s very inefficient. You can increase its efficiency by writing a better C code (syntax-wise),
however the concept remains the same. If you have any other method/concept, you are most welcome to share it here!
Please note that this code not tested yet! So, if any of you is trying it out, do post your results here, I would be happy to see
them!
Methodology – PWM Mode
Okay, so now lets learn about the PWM mode. The PWM Mode in AVR is hardware controlled. This means that
everything, by everything I mean “everything”, is done by the AVR CPU. All you need to do is to initialize and start the
timer, and set the duty cycle! Cool, eh?! Let’s learn how!
Here, I have used Timer0 of ATMEGA32 for demonstration. You can choose any other other timer or AVR microcontroller
as well. Now let’s have a look at the registers.
TCCR0 – Timer/Counter0 Control Register
We have come across this register in my Timer0 tutorial. Here, we will learn how to set appropriate bits to run the timer in
PWM mode.
TCCR0 Register
We will discuss only those bits which are of interest to us now.
Bit 6,3 – WGM01:0 – Waveform Generation Mode - These bits can be set to either “00″ or “01″ depending
upon the type of PWM you want to generate. Here’s the look up table.
Bit 5,4 – COM01:0 – Compare Match Output Mode - These bits are set in order to control the behavior of
Output Compare pin (OC0, pin 4 in ATMEGA32) in accordance with the WGM01:0 bits. The following look up table
determine the operations of OC0 pin for Fast PWM mode.
Now lets have a look at the Fast PWM waveforms. Detailed explanation can be found in myprevious tutorial.
Fast PWM
Now let me remind you that the AVR PWM is fully hardware controlled, which means that even the timer compare
operation is done by the AVR CPU. All we need to do is to tell the CPU what to do once a match occurs. The COM01:0
pins come into play here. We see that by setting it to “10″ or “11″, the output pin OC0 is either set or cleared (in other
words, it determines whether the PWM is in inverted mode, or in non-inverted mode).
Similarly for Phase Correct PWM, the look up table and the waveforms go like this.
Compare Output Mode, Phase Correct PWM Mode
And that’s it! Now we are ready to write a code for it!
Code
So here goes the code. To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this.
To learn how to use AVR Studio 5, view this. To learn how this code is structured, view the previous TIMER0 post.
#include <avr/io.h>
#include <util/delay.h>
void pwm_init()
TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00);
// make sure to make OC0 pin (pin PB3 for atmega32) as output
pin
DDRB |= (1<<PB3);
}
void main()
uint8_t duty;
pwm_init();
// run forever
while(1)
OCR0 = duty;
Problem Statement
So now, let’s take another problem statement. This one is going to be a more of a practical stuff unlike the previous one!
Let’s take the traditional LED flasher where we need to blink an LED at a particular frequency. But hey, wait, didn’t we
discuss it long back in this post (scroll down towards the end)? Hmm, so let’s modify it so as to incorporate PWM. Unlike
the traditional LED flasher (where LEDs are either ON or OFF), lets make it glow at the maximum brightness, and then
slowly decrease its brightness till it reaches zero, and then again increase its brightness slowly till it becomes maximum.
Analysis and Code
So how do we do it? Yes, you guessed it right! Decrease the duty cycle slowly from 255 to zero, and then increase it from
zero to 255. Depending upon the duty cycle, the voltage applied to the LED varies, and thus the brightness. The following
formula gives the relation between voltage and duty cycle.
So here goes the code. I won’t explain it, you can decode it yourself. To learn about I/O port operations in AVR, view this.
To know about bit manipulations, view this. To learn how to use AVR Studio 5, view this. To learn how this code is
structured, view the previous TIMER0 post.
// demonstration of PWM
#include <avr/io.h>
#include <util/delay.h>
// initialize PWM
void pwm_init()
TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00);
// make sure to make OC0 pin (pin PB3 for atmega32) as output
pin
DDRB |= (1<<PB3);
void main()
{
uint8_t brightness;
pwm_init();
// run forever
while(1)
// increasing brightness
OCR0 = brightness;
_delay_ms(10);
// decreasing brightness
OCR0 = brightness;
_delay_ms(10);
So here ends my another much awaited and long tutorial! Next up.. Serial Communication! See you around!!
And yeah, if you have any suggestions, doubts, constructive criticisms, etc, you are most welcome to drop a note below!
Subscribe to my blog or grab the RSS Feeds to stay updated!
Tags: atmega32, avr, avr studio 5, avr tutorial, pulse width modulation, pwm
Comment