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

[...] and welcome back to the discussion on the TIMERs in compare mode. In the last article we discussed the basics and the theory about using the timer in compare mode. Now its time to write [...]
October 25th, 2008 at 12:27 pmCan 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.
November 16th, 2008 at 8:34 amHi,
Ya I can help u. Do you need a constant duty cycle of 30%?
November 16th, 2008 at 5:19 pmI will mail u the code in 2-3 days
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?
November 21st, 2008 at 3:42 amHi 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.
November 21st, 2008 at 11:47 amhai.. , 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…
November 27th, 2008 at 11:32 amHi, its very useful to me.. i am new to this avr series..if its possible please provide good projects on avr also…
December 30th, 2008 at 7:59 amHello 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.
December 30th, 2008 at 12:03 pmJust 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”
January 15th, 2009 at 2:20 am@Tpike

Thanks a lot for pointing out. I am correcting it right now !
Enjoy !
January 15th, 2009 at 5:40 pmhi , 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.
February 3rd, 2009 at 4:55 pmhello 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.
February 25th, 2009 at 7:28 pmHello Vishal,
Thanks!!!
Timers in Input Capture Mode will be surly covered in later tutorials.
February 25th, 2009 at 7:40 pmhai friends
March 20th, 2009 at 11:20 pmi want to write a program for capture mode for measuring the pulse width.can any one tell me the algorithm or the programing procedure.
hello avinash,
April 18th, 2009 at 12:09 pmneed 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).
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
April 22nd, 2009 at 11:51 pmchandan
jaipur
9309234034
great work , just read and implement !!
July 29th, 2009 at 11:02 pmYou 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…
August 27th, 2009 at 7:21 pmBut overall it’s a good Tutorial…it helped me a lot..thanks for your kindness…
A mistake
There is a mistake in the paragraph discribing OCR1A.
September 7th, 2009 at 1:41 pmIn that para OC1A is written insted of OCR1A. Pls edit it…
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.
September 7th, 2009 at 4:38 pmBut how the way to setup the parameter in timer 3 correlated with the parameter in timer 1 ?
Thanks.
Can anyone please tell me what memory do they use in the following devices?
October 9th, 2009 at 2:01 am1)) 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
Hey Avinash,
October 23rd, 2009 at 4:46 amYour 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?
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?
May 17th, 2010 at 5:46 pm[...] Timers in Compare Mode [...]
June 7th, 2010 at 6:55 pmSir, I use a 4MHz external oscillator with my MCU. So, which prescaler should I choose to get the result as above??
June 8th, 2010 at 4:56 pmSir, 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??
June 8th, 2010 at 5:37 pm@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
June 8th, 2010 at 6:41 pmwell, 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.
June 8th, 2010 at 11:11 pmHi
July 6th, 2010 at 11:10 pmA 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.
Excellent.. Just what i was looking for
August 21st, 2010 at 10:14 pm