Pages Menu
TwitterRssFacebook
Categories Menu

Posted by on Jul 14, 2011 in Atmel AVR, Microcontrollers | 105 comments

AVR Timers – CTC Mode

AVR Timers – CTC Mode

AVR SeriesHello friends! Welcome to the another tutorial on AVR Timers. Till now, we have covered the following topics in AVR Timers:

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:

max = 39999;   // max timer value set  <--- set point

// some code here
// ...
// ...
// ...

// TCNT1 <--- process value
if (TCNT1 >= max)   // process value compared with the set point
{
    TCNT1 = 0;      // process value is reset
}

// ...

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 my TIMER0 tutorial in order to understand this better. I won’t be revising the basic concepts here, just their application.Timer CountNow, 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 and TCCR1B Registers

The Timer/Counter1 Control Register A – TCCR1A Register is as follows:

TCCR1A Register

TCCR1A Register

The Timer/Counter1 Control Register B – TCCR1B Register is as follows:

TCCR1B 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:

Wave Generation Mode Bit Description

Wave Generation Mode Bit Description

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)

TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);   
// Mode = CTC, Prescaler = 64

OCR1A and OCR1B Registers

Now that we have set the CTC Mode, we must tell the AVR to reset the timer as soon as its value reaches such and such value. So, the question is, how do we set such and such values? The Output Compare Register 1A – OCR1A and the Output Compare Register 1B – OCR1B are utilized for this purpose.

OCR1A Register

OCR1A Register

OCR1B 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.

OCR1A = 24999;   // timer compare value

TIFR Register

The Timer/Counter Interrupt Flag Register – TIFR is as follows. It is a common register to all the timers.

TIFR Register

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>
 
// initialize timer, interrupt and variable
void timer1_init()
{
    // set up timer with prescaler = 64 and CTC mode
    TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
 
    // initialize counter
    TCNT1 = 0;
 
    // initialize compare value
    OCR1A = 24999;
}
 
int main(void)
{
    // connect led to pin PC0
    DDRC |= (1 << 0);
 
    // initialize timer
    timer1_init();
 
    // loop forever
    while(1)
    {
        // check whether the flag bit is set
        // if set, it means that there has been a compare match
        // and the timer has been cleared
        // use this opportunity to toggle the led
        if (TIFR & (1 << OCF1A)) // NOTE: '>=' used instead of '=='
        {
            PORTC ^= (1 << 0); // toggles the led
        }
 
        // wait! we are not done yet!
        // clear the flag bit manually since there is no ISR to execute
        // clear it by writing '1' to it (as per the datasheet)
        TIFR |= (1 << OCF1A);
 
        // yeah, now we are done!
    }
}

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 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

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)
{
    // 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.

#include <avr/io.h>
#include <avr/interrupt.h>
 
// initialize timer, interrupt and variable
void timer1_init()
{
    // set up timer with prescaler = 64 and CTC mode
    TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
 
    // initialize counter
    TCNT1 = 0;
 
    // initialize compare value
    OCR1A = 24999;
 
    // enable compare interrupt
    TIMSK |= (1 << OCIE1A);
 
    // enable global interrupts
    sei();
}
 
// this ISR is fired whenever a match occurs
// hence, toggle led here itself..
ISR (TIMER1_COMPA_vect)
{
    // toggle led here
    PORTC ^= (1 << 0);
{
 
int main(void)
{
    // connect led to pin PC0
    DDRC |= (1 << 0);
 
    // initialize timer
    timer1_init();
 
    // loop forever
    while(1)
    {
        // do nothing
        // whenever a match occurs, ISR is fired
        // toggle the led in the ISR itself
        // no need to keep track of any flag bits here
        // 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

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

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.

Compare Output Mode, non-PWM

Compare Output Mode, non-PWM

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!

But we need to compromise on the hardware. Only PD5 or PD4 (OC1A or OC1B) can be controlled this way, which means that we should connect the LED to PD5 (since we are using channel A) instead of PC0 (which we had been using in all the examples till now).

Now let’s see how the code looks like!

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()
{
    // set up timer with prescaler = 64 and CTC mode
    TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
 
    // set up timer OC1A pin in toggle mode
    TCCR1A |= (1 << COM1A0);
 
    // initialize counter
    TCNT1 = 0;
    // initialize compare value
    OCR1A = 24999;
}
 
int main(void)
{
    // connect led to pin PD5
    DDRD |= (1 << 5);
 
    // initialize timer
    timer1_init();
 
    // loop forever
    while(1)
    {
        // do nothing
        // whenever a match occurs
        // OC1A is toggled automatically!
        // no need to keep track of any flag bits or ISR
        // done!
    }
}

Forcing Compare Match

Okay, so till now we have discussed almost all the concepts of CTC mode for 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

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

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.
Wave Generation Mode Bit Description

Wave Generation Mode Bit Description

  • 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.
Compare Output Mode, non-PWM

Compare Output Mode, non-PWM

  • 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

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

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

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
mayank.vitu@gmail.com

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

105 Comments

  1. Hello Mayank bhaiya;
    Little confused over the first example code Methodology – Using CTC Mode. Even though u r using the TIFR Register why don’t u initialize sei() function to enable global interrupts.And are Input Capture Mode and Output Compare Mode part of the CTC stuff.

    • Hi Saad,

      In the first example, a bit is being polled to check if there is a match, and no interrupts are being used anywhere in the code. No interrupts being used, hence no initializing global interrupts.

      Input capture mode is for capturing a digital sequence using timers. Output compare mode is what you are using in CTC since you comparing the the output of the timer with the value stored in the Output Compare Register 1A (OCR1A).

      Hope this helps!

      • Thank you Vishwam Bhaiya

  2. hi max,can i use two timer1 interrupt routine in the same program? let’s say ISR(TIMER1_COMPA_vect) and ISR(TIMER1_COMPB_vect). is it possible? how? i want to output two pulses but same frquency using this. please help me. thank you sir.

    • Yes it is possible. Just follow the same method as shown above. I don’t understand, but why are you so afraid to try? It’s not going to burst your microcontroller! If you understand one of them, the other one is exactly the same implementation!

      And if you want to include phase difference between the two timers, and want them to run at the same frequency using the same timer, then you better not use the CTC mode. Use normal mode, and toggle the pins manually at compare match.

      • i tried it but failed the first time, now i made it work fine, i was able to output two pulses. now you are right, i want to include phase shift of 90deg. using the same timer. By normal mode do you mean overflow? thanks a lot sir :)

        • By normal, I mean “not CTC or PWM”.

          • sorry but i don’t get it :( your tutorials about avr timers cover overflows, pwm and ctc. Can you please elaborate what do you mean by normal mode? thank you sir

          • By normal mode, I mean that you control everything in software, the hardware doesn’t alter the registers at all (like in CTC/PWM). Generate an interrupt on compare match, then process it manually, that’s what I meant. If you need to clear the count, do it manually rather than letting the hardware control it. Does that help?

  3. hey max,
    i wanna make a digital clock n stopwatch with great accuracy n wanna use timer1 as counter , so frstly do counter automatically aftr reaching max value goes to 0 and start again and secondly do transition from max value to 0 take exact one clock pulse as it takes from 1 to 2 or 2 to 3 as it might affect accuracy…..
    n last bt not da least….u r really awesome…better dan a real trainer in a virtual work…thumbs up..!!

    • Hey Greenthorn,
      Yes, yes and thanks for your kind words! :)

      • n max one more thing, we r using incrementing counter only but how to use it in decrementing mode and as u said it automatically goes to zero and start again so we need not have worry bout ISR() and interrupt flags ryt..??

        • We usually use timers in incrementing mode. The concept behind timers is that every change in the counter value takes exactly one clock tick. So decrementing the counter from 10 to 0 takes the same time as incrementing it from 246 to 0 (for 8-bit). Makes sense?
          If interrupts are enabled, whenever the counter overflows, the interrupt flag is set and the ISR is executed automatically. So the point is that the counter getting overflowed from TOP to zero is inevitable since the hardware register cannot hold value greater than that, but whether to generate the interrupt flag and/or the ISR is totally up to you.

          • thnx a ton max fr ol ur valuable hlp n yes m wrkin on high accuracy stopwatch n clock nw n its olmost done too….
            n one more thing max,i ws bout to burn my hex file into atmega mc n ws confused between isp, usbasp and bootloading so plz can u gve me a hint wats da dffrnce as i jus wanna burn my program n i dun wanna go to coding part of master slave as u have provided in ur tutorials ahead so jus gve me a brief idea….
            thnx….

  4. this is a great article . that’s help me a lot .

    • Thanks, keep reading :D

  5. awesome expalnation……….thanks..:)

  6. Hey Jyotendra,
    We’re on it! It’s next on our list! Till then, try to get your hands on one of them. :)

Trackbacks/Pingbacks

  1. AVR Timers – PWM Mode – Part I « maxEmbedded - [...] AVR Timers – CTC Mode [...]
  2. 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 …
  3. Introduction to AVR Timers « maxEmbedded - [...] from normal operation, these three timers can be either operated in normal mode, CTC mode or PWM mode. We …
  4. “Необычное” поведение режима 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 *

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>