MoreTimers PDF
MoreTimers PDF
MoreTimers PDF
The basic concepts of timers and its applications have been discussed in
earlier posts. In this post, we will discuss about a special mode of operation
– Clear Timer on Compare (CTC) Mode.
CTC Mode
So till now, we have dealt with the basic concepts. We had two timer values
with us – Set Point (SP) and Process Value (PV). In every iteration, we used
to compare the process value with the set point. Once the process value
becomes equal (or exceeds) the set point, the process value is reset. The
following code snippet explains it:
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.
Now, given XTAL = 16 MHz, with a prescaler of 64, the frequency of the clock
pulse reduces to 250 kHz. With a Required Delay = 100 ms, we get the Timer
Count to be equal to 24999. Up until now, we would have let the value of
the timer increment, and check its value every iteration, whether it’s equal
to 24999 or not, and then reset the timer. Now, the same will be done in
hardware! We won’t check its value every time in software! We will simply
check whether the flag bit is set or not, that’s all. Confused, eh? Well, don’t
worry, just read on!
Okay, so now let me introduce you to the register bits which help you to
implement this CTC Mode.
TCCR1A Register
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:
We can see that there are two possible selections for CTC Mode. Practically,
both are the same, except the fact that we store the timer compare value in
different registers. Right now, let’s move on with the first option (0100).
Thus, the initialization of TCCR1A and TCCR1B is as follows.
TCCR1A |= 0;
// not required since WGM11:0, both are zero (0)
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
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.
1 #include <avr/io.h>
2
3 // initialize timer, interrupt and variable
4 void timer1_init()
5 {
6 // set up timer with prescaler = 64 and CTC mode
7 TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
8
9 // initialize counter
10 TCNT1 = 0;
11
12 // initialize compare value
13 OCR1A = 24999;
14 }
15
16 int main(void)
17 {
18 // connect led to pin PC0
19 DDRC |= (1 << 0);
20
21 // initialize timer
22 timer1_init();
23
24 // loop forever
25 while(1)
26 {
27 // check whether the flag bit is set
28 // if set, it means that there has been a compare match
29 // and the timer has been cleared
30 // use this opportunity to toggle the led
31 if (TIFR & (1 << OCF1A)) // NOTE: '>=' used instead of '=
32 {
33 PORTC ^= (1 << 0); // toggles the led
34 }
35
36 // wait! we are not done yet!
37 // clear the flag bit manually since there is no ISR to e
38 // clear it by writing '1' to it (as per the datasheet)
39 TIFR |= (1 << OCF1A);
40
41 // yeah, now we are done!
42 }
43 }
So, now you have an LED flashing every 100 ms! Now let’s use another
methodology to sort out the same problem statement.
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 compare interrupt. 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.
ISR (TIMER1_COMPA_vect)
{
// toggle led here
PORTB ^= (1 << 0);
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.
+ expand source
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.
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
ATMEGA16/32 OC Pins
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:
Right now we are concerned only with the CTC mode. The following options
hold good for non-PWM mode.
Since we need to toggle the LED, we choose the second option (01). Well,
that’s all we need to do! No need to check any flag bit, no need to attend to
any interrupts, nothing. Just set the timer to this mode and we are done!
Whenever a compare match occurs, the OC1A pin is automatically toggled!
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.
+ expand source
TIMER1, except one – Forcing Compare Match. In the TCCR1A register, till
now we have ignored Bit 3:2 – FOC1A:B – Force Output Compare for
Compare Unit A/B.
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.
TCCR0 Register
The Timer/Counter0 Control Register– TCCR10 Register is as follows:
TCCR0 Register
Bit 5:4 – COM01:0 – Compare Match Output Mode – They control the
behaviour of the OC0 (PB3) pin depending upon the WGM mode –
non-PWM, Phase Correct PWM mode and Fast PWM mode. The selection
options of non-PWM mode are as follows. Choose 01 to toggle the LED.
Bit 7 – FOC0 – Force Output Compare – This bit, when set to ‘1’ forces an
immediate compare match and affects the behaviour of OC0 pin. For
ensuring compatibility with future devices, this bit must be set to ‘0’.
Bit 2:0 – CS02:0 – Clock Select Bits – We are already familiar with these
bits. View the TIMER0 post for more details.
OCR0 Register
The Output Compare Register– OCR0 Register is as follows:
OCR0 Register
TIMSK Register
The Timer/Counter Interrupt Mask– TIMSK Register is as follows:
TIMSK Register
TIFR Register
The Timer/Counter Flag Register– TIFR is as follows:
TIFR Register
That’s it! With this much information, I am sure that you can successfully
generate a timer in CTC mode of TIMER0.
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.
Thank You!
Mayank Prasad
[email protected]
Related Posts
AVR Timers – AVR Timers – AVR Timers – AVR Timers – AVR Timers –
TIMER0 TIMER1 TIMER2 PWM Mode – Part PWM Mode – Part
I II
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!
Follow Me:
85 Comments
REPLY
Hey Mayank,
thank you very much for writing this and all the other articles in your blog!
They just saved me a lot of time since I didn’t have to search for the
information I needed in the controller’s datasheet and I highly appreciate
that. Keep up the great work!
REPLY
REPLY
Thanks!
REPLY
Thank you very much about this artical.Atmel timers documents not clear.
Loves from Turkey
Serdar Cetin
REPLY
Hi,
Thank for the tutorial. It was really helpful.
I just wanted to know if I can modify the value of OCR1A in ISR (using 16 bit
Timer)?
Thank you
Jay
REPLY
REPLY
Jay
REPLY
Should:
Not read:
TCCR1A = 0;
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
TIMER1 has two physical channels, and hence there are two
compare registers. Every time, TCNT1 is compared with either
TCCR1A or TCCR1B. This can be used for fast switching between
frequencies or maybe generate two different and unique
frequencies at both the pins. I would suggest you to post this in
avrfreaks.net You will get a better insight into this.
REPLY
well. good article. i have one suggestion from you. i have to measure time
between pulse which i given to INT0. i am giving input pulse through INT0.
i have to find time to measure accurate time between two pulse. i tried
with over flow interrupt but its not correct. is there any way to do with CTC
mode?
REPLY
I guess so! You can set some value of TCCR1A (say 20) and then
divide the result by 20 to get the time between two pulses. Or else
you can also set TCCR1A to 1. This would give you the exact time.
REPLY
hello there I am in big trouble. I read your article but I am confused. I had
a program and it’s not working as it should. here is the code for atmega 32
REPLY
Hi Shahi
Such unexpected delays occur due to mismatch of the software
frequency and hardware frequency.
1. What is the frequency your microcontroller is running at?
2. What is the frequency you have set in your software? View this
to learn how to configure your software frequency.
3. If you are using an external crystal resonator, have you set the
fuses of your microcontroller properly?
REPLY
REPLY
umm so im writing this code where im using external interrupt 1,the 16 bit
counter as two b bit counters for pwm generation and timer 0 in ctc mode
the problem is the interrupt routines seem to work fine as long as i donot
use the pwm generation mode on timer 1 . as soon as i use timer 1 in pwm
REPLY
Hi Talal,
I haven’t used ISIS till now. Perhaps you should try posting your
query to avrfreaks.net
REPLY
REPLY
Hi Joel,
You can do this easily using the Timers/Counters
of AVR. Try reading my timer tutorials to get an
idea about them.
What you can do is you can run a timer for one
REPLY
Hi Mayank. Thanks for the explanation, but could you write a simple
program like that for me so that I can used it as example to write my own
one. I’ve already tried many unsuccessfully. I just want to measure a
frequency up to 20khz and display it through PortD on LCD.
Thanks.
this is what I’ve did ,but it isn’t working
REPLY
Hi Joel,
The code you have written does not seem to be written in Atmel
Studio 6, and so I may not be able to analyze it properly. But all the
concepts have been very clearly described along with code
examples in this post as well as my Timer1 post as well. Please
take some time to read through them and try to implement the
codes. The codes can also be found in my code gallery.
REPLY
REPLY
Thanks!
REPLY
effective tutorial..
REPLY
Thanks!
REPLY
Hi Mayank,
thanks for putting the effort into writing this series of tutorials. Clearer
than in your tutorial it is nowhere (for me).
REPLY
Thank you!
REPLY
I have to change the led to pin 9 (PB1) or 10 (PB2) to use timer1 right? I
used DDRB = 0×02; to set the output to pin 9 which is the same as DDRB
|= (1 << 1) right?
Another thing is that as soon as I add the ISR to the code I get a warning:
warning: 'main' is normally a non-static function
Any ideas?
REPLY
Hi Sigurdur,
First of all may I ask you if you are using Arduino Uno, then why
not program it using the Arduino software itself?
REPLY
REPLY
REPLY
REPLY
really good , one of the best tuts tht i came acrossso far
REPLY
Thanks Kunal!
REPLY
Hey Mayank awesome tutorail and the way yo answer all the doubts is
really cool
REPLY
REPLY
REPLY
Hi Luis,
There is only one register for Timer0, TCCR0 instead of TCCR0A
and TCCR0B. The same holds good for OCR0A. There is no such
register called so, only OCR0 exists. And you cannot assign a
floating point value to OCR register. I would suggest you to go
through my Timer0 tutorial. After that, try implementing it again,
and get back here in case you want it reviewed again!
REPLY
REPLY
awsm tutorial…
my all doubts are clear…
thnxx buddyy…
REPLY
REPLY
Hi!!
very good expaining..Thank you!
I’m second year of Electronics Engineering studying at Gangneung-Wonju
National University ,Gangneung – in South Korea.!!
Nice too meet you!..
REPLY
Hi!
Greetings from India!
Pleasure to have you here!
REPLY
REPLY
Your timer tutorials are great… best I ever read on the web…
Thanks a lot!
REPLY
Thank you!
REPLY
I have a problem……I read the above tutorial and wrote a code for
producing a 38KHz signal to be used with a TSOP1738.Here is the code:
Code: http://pastebin.com/sDmPtz1H
What I should get is a constant (or flickering) output from the LED but what
i’m getting are small pulses when ever i obstruct the IR led and reintroduce
it back.
Is the timer part of the code correct??
Any solutions to the problem
REPLY
REPLY
same problem.
REPLY
REPLY
Hi again!!! In the first code example, in the while() loop, there is the
following line: if (TIFR & (1 <=’ used instead of ‘==’
I looked up for a ‘>=’ but I did not find anything. Is this my mistake? Thank
you.
REPLY
Hello George
REPLY
REPLY
I cannot understand. I copy the line but the blog does not accept it. I type
the line with hands and still it does not appear correctly. Anyway, you may
find the line in the first code example, in the main() and in the while(1)
loop. Thanx!!!!
REPLY
It will seem funny Mr Yash but this CTC page went clear quite immediately.
But now, I will need your help definitely!!! I am a little bit confused with the
following syntax.
REPLY
DDRD |= (1 << 5); // ok I found it. Set the fifth bit of D Port equal to
1.
REPLY
sir i want used timer.if port A0 pin is high then LED will on & after 1min
LED will automatically off.the input is IR sensor which is connected to A0
pin & LED is connected to D0 pin.please give me solution on that.
THANKS…
REPLY
Hi Jishan,
Your problem is simple. Which microcontroller are you using? If
the sensor is an analog one, you can use ADC. If it is a digital one,
then simple GPIO operations would suffice. You can also read this
on how to program digital IR sensors. Once you detect input, then
simply start the timer and then wait for some event. The event
could be an interrupt or compare match or overflow or anything.
Read my timer tutorials to know how to do that.
Best,
Max
REPLY
Hi,
I don’t get it
REPLY
Hi Pablo,
This is a condition which checks whether the OCF1A flag in the
TIFR register is set(1) or not(0). And in case of AVR
microcontrollers (most of them), there is only one TIFR register,
and not TIFR1.
REPLY
REPLY
if (condition) {
// true
} else {
// false
}
REPLY
I know I know.
Hello Mayank,
I found this page while trying to fix a nasty bug in my code. Worked on a
Atmega16A with two timers, both are polled for CTC flag (one inside an
interrupt routine, one in main loop).
Better use TIFR = (1 << OCF1A) or, if you need to use interrupts, mask
the appropriate bis.
Paule
REPLY
Hi Paule,
Sorry for the late reply. I didn’t get the point you want to state
Best,
Max
REPLY
MAYANK sir can you write a code in which timer 0 use as a CTC MoDE
?
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
REPLY
Aim : To dipaly ADC value every 1 sec and take appropriate action.
AVR : ATMEGA328p
Timer used : 16 bit only
Board : ARDUINO UNO
REPLY
VenkateshSai,
It’d have been more helpful if you would have provided more
information about your problem. How can you expect a response
when you don’t even tell properly what’s wrong?!
REPLY
However may I pick your brains further – as I can’t decide which way to go
for my application…
As I see it, an obvious approach is to time stamp from one edge to the
next and when those stamps represent the correct pair, insert the
new/shorter pulse after a calculated delay from the last channel to go low.
Eventually the original pulse needs to ‘carry on’ after I’ve inserted about
100 extra pulses (guesstimate) and so my aim is to focus on adding one
pulse for each in the original. May I ask, what approach would you
gravitate to first?
Thanks a lot.
REPLY
Hi, sorry for the late response. Frankly speaking, your explanation
didn’t make much sense to me. I am afraid that I can’t give you any
suggestion on this. If you could describe it a little more and in
simple sentences, I might. Sorry!
REPLY
Hey Jyotendra,
We’re on it! It’s next on our list! Till then, try to get your hands on one of
them.
REPLY
Trackbacks/Pingbacks
AVR Timers – PWM Mode – Part I « maxEmbedded - [...] AVR Timers – CTC Mode [...]
AVR Timers – PWM Mode – Part II « maxEmbedded - [...] so I won’t be writing any
code here (just the pseudo code). I assume that after reading my previous …
Introduction to AVR Timers « maxEmbedded - [...] from normal operation, these
three timers can be either operated in normal mode, CTC mode or PWM mode. We
…
“Необычное” поведение режима CTC таймера1 | MyLinks - […]
ISR(TIMER1_COMPA_vect) { digitalWrite(7,!digitalRead(7)); Cntr++; } Ссылки в помощь
по теме: http://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
http://maxembedded.com/2011/07/14/avr-timers-ctc-mode/ […]
Post a Reply
Your email address will not be published. Required fields are marked *
Name *
Email *
Website
Comment
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>
SUBMIT COMMENT
Copyright
© Copyright 2011-2014 by
maxEmbedded. Some rights
reserved.
maxEmbedded is a free and open source platform to share knowledge and learn about the concepts of robotics, embedded syste
around the world who are enthusiastic about these topics and willing to support the open source community are invited to sha