Oct-24th-2008

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 !


30 Responses to “Timers in Compare Mode – Part I”

  1. 1
    Timers in Compare Mode - Part II | eXtreme Electronics Says:

    [...] 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 [...]

  2. 2
    Shyam Says:

    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.

  3. 3
    Avinash Says:

    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

  4. 4
    Mircea Says:

    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?

  5. 5
    Avinash Says:

    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.

  6. 6
    noufal Says:

    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…

  7. 7
    kiran Says:

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

  8. 8
    Avinash Says:

    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.

  9. 9
    tpike Says:

    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”

  10. 10
    Avinash Says:

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

    Enjoy !

  11. 11
    prathyusha Says:

    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.

  12. 12
    vishal Says:

    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.

  13. 13
    Avinash Says:

    Hello Vishal,

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

    :)

  14. 14
    Vibish Says:

    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.

  15. 15
    DeadMaN Says:

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

  16. 16
    chandan tiwary Says:

    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

  17. 17
    sukhvir singh Says:

    great work , just read and implement !!

  18. 18
    Dollar Says:

    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…

  19. 19
    sanju Says:

    A mistake

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

  20. 20
    Maferic Says:

    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.

  21. 21
    riya Says:

    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

  22. 22
    riya Says:

    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?

  23. 23
    Sarada Says:

    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?

  24. 24
    Servo Motor Control by Using AVR ATmega32 Microcontroller | eXtreme Electronics Says:

    [...] Timers in Compare Mode [...]

  25. 25
    Mayank Says:

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

  26. 26
    Mayank Says:

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

  27. 27
    Avinash Says:

    @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

  28. 28
    Mayank Says:

    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.

  29. 29
    sam Says:

    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.

  30. 30
    William Lewis Says:

    Excellent.. Just what i was looking for

Leave a Reply

Comments

    • wlewis: @Av.. To my knowledge, practically all the non-ic humidity sensors are frequency dependant...
    • wlewis: @Av.. about ADC.. how about a tutorial that does a 10bit conversion?
    • wlewis: @Av I have a great idea for a tutorial… sensors which output are measured by frequency....
    • BoB: Hello… I’m still a newbie in this field..so, may I ask…this application used...
    • Hill: Why dont you mention in your URL which PICs these burner supports? It will help avoid guesswork...
    • victor: I have to rectify, that is not an issue, instead is a LCD’s McU limitation in locations...
    • wlewis: Avrdude code for atmega32 // 16mhz crystal // Jtag disabled. avrdude -p m32 -b 19200 -P COM3...

Video

  • Comments

    • wlewis: @Av.. To my knowledge, practically all the non-ic humidity sensors are frequency dependant...
    • wlewis: @Av.. about ADC.. how about a tutorial that does a 10bit conversion?
    • wlewis: @Av I have a great idea for a tutorial… sensors which output are measured by frequency....
    • BoB: Hello… I’m still a newbie in this field..so, may I ask…this application used...
    • Hill: Why dont you mention in your URL which PICs these burner supports? It will help avoid guesswork...
    • victor: I have to rectify, that is not an issue, instead is a LCD’s McU limitation in locations...
    • wlewis: Avrdude code for atmega32 // 16mhz crystal // Jtag disabled. avrdude -p m32 -b 19200 -P COM3...