Timers in Compare Mode – Part I

Hi Friends,

In last tutorials we discussed about the basics of TIMERs of AVR. In this tutorial we will go a step further and use the timer in compare mode . In our first tutorial on timer we set the clock of the timer using a prescaler and then let the timer run and whenever it overflowed it informed us. This way we computed time. But this has its limitations we cannot compute time very accurately. To make it more accurate we can use the compare mode of the timer. In compare mode we load a register called Output Compare Register with a value of our choice and the timer will compare the current value of timer with that of Output Compare Register continuously and when they match the following things can be configured to happen.

  1. A related Output Compare Pin can be made to go high,low or toggle automatically. This mode is ideal for generating square waves of different frequency.
  2. It can be used to generate PWM signals used to implement a DAC digital to analog converter which can be used to control the speed of DC motors.
  3. Simply generate an interrupt and call our handler.

On a compare match we can configure the timer to reset it self to 0. This is called CTC – Clear Timer on Compare match.

The compare feature is not present in the 8 bit TIMER0 of the ATmega8 so we will use the TIMER1 which is a 16 Bit timer. First we need to setup the timer’s prescaler as described in the Timer0 tutorial. Please see this tutorial for a basic introduction of TIMERs.

The TIMER1 has two compare units so it has two output compare register OC1A and OC1B. The ‘1’ in the name signifies that they are for timer ‘1’.

In this tutorial we will create a standard time base which will be useful for many projects requiring timing such as clocks,timers,stopwatches etc. For this we will configure the timer to generate an Compare match every millisecond and in the ISR we will increment a variable clock_millisecond. In this way we will have a accurate time base which we can use for computing time in seconds,minutes and hours.

References

For learning about the basic idea of peripherals and their use with AVRs please see this tutorial.

For learning about basics of timers see this.

AVR’s Timers1 Registers

I will state the meaning of only those bits which are required for this tutorial. These bits are marked with a gray back ground in the table. For details about other bits please consult the datasheets.

Timer/Counter1 Control Register A (TCCR1A)

This register is used to configure the TIMER1. It has the following bits

Bit

7

6

5

4

3

2

1

0

Name

COM1A1

COM1A0

COM1B1

COM1B0

FOC1A

FOC1B

WGM11

WGM10

InitialValue

0

0

0

0

0

0

0

0

COM1A1 and COM1A0 –

This are used to configure the action for the event when the timer has detected a "match". As i told earlier the timer can be used to automatically set,clear or toggle the associated Output compare pin this feature can be configured from here. The table below shows the possible combinations.

COM1A1

COM1A0

Description

0

0

Normal Port Operation (The timer doesn’t touches the PORT pins).

0

1

Toggle OC1A Pin on match

1

0

Clear OC1A on match – set level to low (GND)

1

1

Set OC1A on match – set level to High(Vcc)

The OC1A pin is the Pin15 on ATmega8 and Pin19 on ATmega16/32. As you may guess that we don’t need any pin toggling or any thing for this project so we go for the first option i.e. Normal Port Operation

As I have told you that the TIMER1 has two compare unit, the COM1B1/COM1B0 are used exactly in same way but for the channel B.

WGM11 and WGM10 –

These combined with WGM12 and WGM13 found in TCCR1B are used for selecting proper mode of operation. WGM= Waveform Generation Mode.

Timer/Counter1 Control Register B (TCCR1B)

This register is also used for configuration. The Bits are.

Bit

7

6

5

4

3

2

1

0

Name

ICNC1

ICES1

WGM13

WGM12

CS12

CS11

CS10

InitialValue

0

0

0

0

0

0

0

0

The four bits

WGM13 – WGM12 – WGM11 – WGM10 are used to select the proper mode of operation. Please refer to the datasheet for complete combinations that can be used. We need the CTC mode i.e. clear timer on match so we set them as follows

WGM13=0

WGM12=1

WGM11=0

WGM10=0

This is the settings for CTC.

The CS12,CS11,CS10

These are used for selecting the prescalar value for generating clock for the timer. I have already discussed them on TIMER0 tutorial. I will select the prescalar division factor as 64. As the crystal we are using is of 16MHz so dividing this by 64 we get the timer clock as

F(timer)=16000000/64 = 250000Hz

so timer will increment its value @ 250000Hz

The setting for this is

CS12

CS11

CS10

0

1

1

So the final code we write is

TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);

TIMER Counter 1 (TCNT1)

TCNT1H (high byte) TCNT1L(low byte). This is the 16 Bit counter

Output Compare Register 1 A – OCR1A (OCR1AH,OCR1AL)

You load them with required value. As we need a time base of 1ms and our counter is running @ 250000Hz i.e. one increment take 1/250000 = 0.000004 Sec or 0.004 ms. So we need 1ms/0.004 = 250 increments for 1ms. Therefore we set OC1A=250. In this way when timer value is 250 we will get an interrupt and the frequency of occurrence is 1ms and we will use this for incrementing a variable clock_millisecond.

Output Compare Register 1 B – OCR1A (OCR1BH,OCR1BL)

 

Timer Counter Interrupt Mask (TIMSK)

This is the mask register used to selectively enable/disable interrupts. This register is related with the interrupts of timers (all timers TIMER0,TIMER1,TIMER2).

Bit

7

6

5

4

3

2

1

0

Name

OCIE2

TOIE2

TICIE1

OCIE1A

OCIE1B

TOIE1

TOIE0

InitialValue

0

0

0

0

0

0

0

0

Of all these bits 5,4,3,2 are for TIMER1 and we are interested in the OCIE1A which is Output Compare Interrupt Enable 1 A. To enable this interrupt we write

TIMSK|=(1<<OCIE1A);

After enabling the interrupt we also need to enable interrupt globally by using the function

sei();

This function is part of AVR-GCC interrupt system and enables the interrupt globally. Actually this translate in one machine code so there is no function call overhead.

So friends that’s its for now ! The rest will be covered in latter tutorials. To get all the latest tutorials on your mailbox subscribe to my RSS feed via e-mail.

And don’t forget to post your comment !!! What you think about them and what you will like to see here. Or simply post any doubt you have about this tutorial.

Goodbye, and have fun !

Move On …

Facing problem with your embedded, electronics or robotics project? We are here to help!
Post a help request.

Avinash

Avinash Gupta is solely focused on free and high quality tutorial to make learning embedded system fun !

More Posts - Website

Follow Me:
FacebookLinkedInGoogle Plus

62 thoughts on “Timers in Compare Mode – Part I

  • Pingback: Timers in Compare Mode - Part II | eXtreme Electronics

  • By Shyam - Reply

    Can u help me out in coding ?

    I need a PWM signal of about 10-15 Khz with a duty cycle of say 30%.I just want to generate the signal and want it as output.I am using Atmega16.

    • By sree - Reply

      am also doing same project can u help me

  • By Avinash - Reply

    Hi,

    Ya I can help u. Do you need a constant duty cycle of 30%?
    I will mail u the code in 2-3 days

  • By Mircea - Reply

    Hi, very good job.
    Thank’s for the tutorials, they are very helpful

    Is there any chance to have this one in a PDF version?

  • By Avinash - Reply

    Hi Mircea,

    Thanks!

    I will surely release them as pdf. I am quite busy this week. When I get time I will convert them to nice PDFs.

  • By noufal - Reply

    hai.. , I’m just beginner of programming AVR and I have some problems. I’m working with AVR Studio 4 and writing a program for ATmega16 TIMER0 normal mode in assembly language..the code is
    .equ TCCR0=$33
    .equ TCNT0=$32
    .equ TIFR=$38
    .cseg
    .org 0×00
    JMP MAIN

    MAIN:
    LDI R16,0X02
    out TCCR0,R16
    l1: SBIS TIFR,0
    JMP L1
    JMP MAIN

    when compiling it shows the error
    D:\avr\timer.asm(13): error: Operand 1 out of range: 0×38
    D:\avr assem\timer.asm(22): No EEPROM data, deleting D:\avr assem\timer.eep

    please help me to find the error…

  • By kiran - Reply

    Hi, its very useful to me.. i am new to this avr series..if its possible please provide good projects on avr also…

  • By Avinash - Reply

    Hello Kiran,

    Thanks!

    Ya, I will do provide good projects based on AVR MCUs soon. Till then enjoy the tutorials and for any doubt don’t hesitate to ask me.

  • By tpike - Reply

    Just a spelling correction and compliment. Wonderful series and great introduction. Has helped me a lot in getting my head around this stuff. Here is the minor spelling correction “In compare mode we load a resister called”

  • By Avinash - Reply

    @Tpike
    🙂
    Thanks a lot for pointing out. I am correcting it right now !

    Enjoy !

  • By prathyusha - Reply

    hi , I have some problem with… I’m working with AVR Studio 4 and writing a program for calculaing width of a pulse(square wave) using ATmega8 using timer/counters can u help me in writing the code.

  • By vishal - Reply

    hello sir,

    thanks for your help.
    you have provided the timer 1 tutorial, to use timer in compare mode. it was fantastic explanation. i need help in using a timer in input capture mode.

    thank you.

  • By Avinash - Reply

    Hello Vishal,

    Thanks!!! 🙂
    Timers in Input Capture Mode will be surly covered in later tutorials.

    🙂

  • By Vibish - Reply

    hai friends
    i want to write a program for capture mode for measuring the pulse width.can any one tell me the algorithm or the programing procedure.

  • By DeadMaN - Reply

    hello avinash,
    need a c code to generate 2 synchronised (at the end) square wave pulses using atmega32 whose duty cycle can be varied simultaneously .(may be we can connect some analog potentiometer to change the duty cycle).

  • By chandan tiwary - Reply

    hi avinash,
    chandan here.i did not get these lines upto 100% confidence.please illustrate them indetail.they were in ur tutoruals…timers in compare mode 1.

    After enabling the interrupt we also need to enable interrupt globally by using the function
    sei();
    This function is part of AVR-GCC interrupt system and enables the interrupt globally. Actually this translate
    in one machine code so there is no function call overhead.

    regards
    chandan
    jaipur
    9309234034

  • By sukhvir singh - Reply

    great work , just read and implement !!

  • By Dollar - Reply

    You could also start by saying there are 3 kinds of Register:
    01) Control Register-> TCCR, TIMSK
    02) Data Register-> TCNT.
    03) Flag Register->TIFR.

    and yor also could a simple example…
    But overall it’s a good Tutorial…it helped me a lot..thanks for your kindness…

  • By sanju - Reply

    A mistake

    There is a mistake in the paragraph discribing OCR1A.
    In that para OC1A is written insted of OCR1A. Pls edit it…

  • By Maferic - Reply

    I have a project to manipulate the squarewave signal. Based on your article can it combined with input capture timer (maybe must use 2(two) 16 bit timer as in Atmega 162) to manipulate the input signal and process it inside microcontroller and by using the other timer to generate the output signal using compare match method ? Maybe we use timer 1 as input capture and timer 3 as compara match.
    But how the way to setup the parameter in timer 3 correlated with the parameter in timer 1 ?
    Thanks.

  • By riya - Reply

    Can anyone please tell me what memory do they use in the following devices?
    1)) the memory used in our cell phone’s address book.
    2) the memory used in the executable code for a medical diagnostic machine.
    3) the memory used in (not the executable code) used in run-time calculations for an in-flight entertainment system.
    4) the memory used in program for a child’s toy (a robot).
    regards,
    riya

  • By riya - Reply

    Hey Avinash,
    Your AVR tutorial helps me a lot to understand the basic concepts. I am working on Atmega169. I need to initialize Timer2 to use the 32.7 kHz crystal on the board. i need to cause Timer2 to generate an overflow interrupt every 10 millisec. I am not supposed to select compare match interrupt. For this do I need to initialise TCCR2A. if yes then what is the value of cs0, cs1, cs2. & WGM20, WGM2. I cant use compare match then What abt COM2A1? Since i use 32.7 kHz crystal, how to select prescaler(CS0,CS1,CS2)?Can you help me?

  • By Sarada - Reply

    I am trying to use the 16bit TIMER1 to generate two separate pwm signals on OC1A and OC1B. My project requires 4 distinct pwm signals. I have already used TIMER0 and TIMER2 to generate 2 pwm signals. How do i use TIMER1 to generate 2 individual pwm signals?

    • By waintdeir - Reply

      i also need 4 pwm-signals with a frequency of 50Hz and different puls-lenghts.

      how did you manage 2 souch PWMs with 1 timer?
      cos maybe a ATmega644 with 3 timers can handle this…

      greetings 😉

  • Pingback: Servo Motor Control by Using AVR ATmega32 Microcontroller | eXtreme Electronics

  • By Mayank - Reply

    Sir, I use a 4MHz external oscillator with my MCU. So, which prescaler should I choose to get the result as above??

    • By Avinash - Reply

      @Mayan,

      Did you set the fuse bits for external crystal ???

      Or just hooked a crystal and thought that MCU will switch from internal to external xtal automatically ???

      Now don’t ask me that “what are fuse bit and how to set them!”

      -admin

  • By Mayank - Reply

    Sir, I posted a comment above stating that I use a 4MHz oscillator. I used a prescaler of 8 and assigned OCR1A = 500;

    The timer is running a bit slow.. I mean, for increasing the clock by 1sec, it takes approx 3sec.

    Do you have any idea what’s happening??

  • By Mayank - Reply

    well, actually, i use a microcontroller development board, which I bought from somewhere else. They have attached the 4Mhz crystal and given to me. So, i feel that they have had preset the fuse bits for that. Anyways, i will recheck that part.

    One reason that i could find for the slow process was a fault in the programming. 1sec = 100msec, but in your code (part II), 1000msec was used. But after that, the clock became too fast.. approx, it took 4sec to complete 10sec of display.

    • By waintdeir - Reply

      if you are programming the AVR with Studio4:

      go to PROGRAMMING and check for FUSE BITS,

      there you have to select:

      External cristal oscilator (middle frequencies)
      or something like that…

      mfg

  • By sam - Reply

    Hi
    A wonderful job done by you.. amazing
    I have made a program for my project in which i require the microcontroller to perform the following functions:
    1)pulse generation
    2)timer to ADC9220
    3)data acquisition from the 12 bit adc.
    can you check my code whether it is fine. i will be gratefull.

  • By William Lewis - Reply

    Excellent.. Just what i was looking for

  • Pingback: Interfacing Ultrasonic Rangefinder with AVR MCUs | eXtreme Electronics

  • By Mayank Sharma - Reply

    all these tutorials here are best on net

  • By sai - Reply

    damn good,really useful.clean ,ssimple,superb.thanks a lot

  • By Siddhartha - Reply

    The one of the very exceptional works I have ever seen on AVR tutorials.

    Greetings for the new year to all.

    I am using Atmega16 with 8 Mhz external crystal. I have been able to set the Timer1 prescaler and Fast PWM mode. By varying OCR1A and I could vary the duty of Fast PWM on OC1A.

    My query is as follows :
    In the above setup if I vary OCR1B, will I get a Fast PWM on OC1B, whose duty I can vary independent of OCR1A. In that case I can use OC1A and OC1B to drive the two ENABLE pins of LM293D (motor driver) independently.

    Let me know if the above concept is valid.

    Thank you.

  • By Siddhartha - Reply

    In case the following points help someone :

    ———————————————————–
    “In the above setup if I vary OCR1B, will I get a Fast PWM on OC1B, whose duty I can vary independent of OCR1A.”

    I tried. Yes it can be done.
    ———————————————————–
    “In that case I can use OC1A and OC1B to drive the two ENABLE pins of LM293D (motor driver) independently.”

    I have still not tried. But I am sure it can be done.
    ———————————————————–

  • By Micro - Reply

    I have read both your timer tutorials. These are the best I found. After reading these I was finally able to understand the datasheets. This helped me a ton. Thanks

    • By Avinash - Reply

      @Micro,

      Thanks a lot for your feedback! Only people like you provide energy to keep me writing …

  • By hans - Reply

    Well done! keep up the pace. we’re looking forward to get a pdf of this part and the next parts.

  • Pingback: AVR Timers - An Introduction. | eXtreme Electronics

  • By Eeshaanee - Reply

    very nice tutorials….
    really well explained..!!

  • By Armen - Reply

    Tremendous Tutorial, clean, simple, easy to get, cool table color filterm, …
    Thank you.
    awsome job!

  • By Thong - Reply

    Hi everyone
    I don’t understand the thing which is written in ATmega128 Data Sheet page 93 :
    “Changing the TOP to a value close to BOTTOM
    when the counter is running with none or a low prescaler value must be done with care since the CTC mode does not have the double buffering feature. If the new value written to OCR0 is lower than the current value of TCNT0, the counter will miss the compare match. The counter will then have to count to its maximum value (0xFF) and wrap around starting at 0x00 before the compare match can occur.”
    Why? and if in CTC mode have the double buffering. What is happen different?
    Thanks

  • By matrix - Reply

    MIND-BLOWING explanation…..u make topics so simple..doesn’t matter how hard the topic is. THUMBS UP 4 U. (*****)

  • By vinayak - Reply

    hi Avinash
    i am looking for touch screen interface to atmega32
    can you give me suggestion for this type implementation or can you give demo board for this
    please give me reply

  • By prakash - Reply

    THnks,sir

  • By Awais Khan - Reply

    Hello
    Timer tutorial was very beneficial to me. I wanna use AVR ATmega32 for page writing and page reading on AT24C1024 EEPROM. Is there any tutorial for that?

  • By taiwofolu - Reply

    Hello Avinash! Keep up the good work! I’m doing this as a personal project but I need some assistance. I had to do some reading and research of my own before asking any questions because many terms weren’t clear to me. Thanks to your site I now understand a whole lot of things. After my study, I wrote this code:

    /*PROGRAM WRITTEN BY TAIWO FOLU. PWM CONTROL OVER BLUETOOTH WITH DTMF TONES. INPUT ON ATTINY2313 PINS PB4 TO PB7. PWM SIGNAL OUTPUT ON PB2 (OC0A) AND PD5 (OC0B) USING TIMER0. TWO EXTRA I/O PINS ON PB0 AND PB1*/

    #include
    void initPWM()
    {
    TCCR0|=(1<<WGM01)|(1<<COM01)|(1<<CS00);
    //Freq=FCPU, phase correct pwm, non inverted PWM (mode3)
    DDRB|=0xE0; //Set PB0, PB1 and PB2 for output and the rest for input
    DDRD|=(1<<PD5); //Set PD5 for output
    }
    void SetPWMOutput(Uint8_t duty)
    {
    OCR0A=0; //Set dutyA to 0%
    OCR0B=127; //Set dutyB to 50%
    }
    void main()
    {
    Unsinged int f;
    while (1)
    {
    f=PINB;
    switch (f)
    {
    case 0x04: //when key 4 is pressed
    {
    OCR0B++; //increment OCR0B
    break;
    }
    case 0x05: //when key 5 is pressed
    {
    OCR0A++; //increment OCR0A
    break;
    }
    case 0x06: //when key 6 is pressed
    {
    OCRB–; //decrement OCR0B
    break;
    }
    case 0x0A: //when key0 is pressed
    {
    OCR0A–; //decrement OCR0A
    break;
    }
    }
    }[/syntax]

    I intend to use the dtmf tones to control the duty cycles of pwm channels A and B on timer0. Please look through the code and help me if i've made any mistakes or unnecessary statements or he there's a better way to implement this. Here, i've not used the PB0 and PB1 pins yet so I don't get confused, I want to get the duty cycles control right first.
    Thanks a lot.

  • By Prajwal - Reply

    hi avinash.. I jus wana say hats off!! ur tutorials r d best tat iv cin so far.. pls cntinue ur postings it wd help lots of beginners lik me to develop code on avr. thanx a million:-)

  • By samir - Reply

    Hi currently im developing a coding for a pedestrian traffic light with sensor that detect person that want to cross the road. but now im stuck at coding for the sensor..can you help me?it will be a pleasure for me..im a student from malaysia.

  • By kamal gangwar - Reply

    @Abhinash you explained the timers using a very
    good approach.
    But still i need your help , I have same problem i want
    to generate a pulse of 5 Khz frequency and 25% duty cycle . I’m very much confussed about setting in OCRx register. Can you help me .
    I would be thankfull to you.

  • By Aditya - Reply

    Hello Avinash
    timer tutorials are great. i am doing a project on generating a pulse train of desired numbers. the pulse train need to accelerate from 0hz to desired frequency then continue till the specified deceleration point and decelerate to 0Hz.
    can you help me with the code?
    waiting for your reply.

  • By shoaib - Reply

    i want to know how the timer will produce a tick after every 10ms and how we decide the timer?

  • By kais - Reply

    Hi;
    I just want to thank you so much for the excellent explained tutorials!!

    Warm Regards

  • By shail - Reply

    Hi,

    I am going to use PWM as Invertor in renesas RX 63T Microcontroller.

    Can you help me out in coding?
    I want generic program that work for all frequency and duty cycle.

    Depend upon machine cycle it should vary duty cycle.

    Thanks…….

  • By praba - Reply

    i need led blinking code using pwm i tried a lot bt i cant get it…. for pic24fj64ga002 …

  • By Jaani - Reply

    Hi Prabha,

    I can help you with the code . Ping me @ jaani.n@gmail.com

    Thanks

  • By barry - Reply

    Hi Avinash
    Is this possible to work with the aTTiny 45 with a variable pwm freqency
    using an analog input on same chip or from code. I program attiny with the Uno

    Many thanks in advance.
    Barry

  • By Islam Hassan Ahmed - Reply

    Hi Avinash,

    Thank you very much for your efforts and interested articles.
    I have some questions:
    1- What is the function of TCNT1 register. I think that it is useless. We can’t put values in it except 0 or 255
    so, why we need it? We can simply just use OCR1A or OCR1B and when its value reach to specific value,
    the interrupt will occurs.
    2- If i want to get 1 ms time from timer0, i can’t get that because TCNT0 take only 0 or 255 so, it must
    be increments or decrements from 0 or 255 respectively. Why i can’t set specific value? and if i can’t
    how to get 1 ms from this timer.Does for that reason timer 1 is more accurate?
    3- What benefits i will get when using external clock for timer?

    Thanks in advance.

  • By Murph - Reply

    You said “Therefore we set OC1A=250”. That’s incorrect. We start counting from 0, you want to set OC1A to 249. If you don’t believe me you should time it for about 5 minutes; you will notice the difference.

Leave a Reply

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


− 1 = eight

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=""> <s> <strike> <strong>