Timers in Compare Mode – Part II

Hello 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 some practical code and run it in real world. The project we are making is a simple time base which is very useful for other project requiring accurate computation of time like a digital clock or a timer that automatically switches devices at time set by user. You can use it for any project after understanding the basics.

We will have three global variable which will hold the millisecond, second and minutes of time elapsed. These variables are automatically updated by the compare match ISR. Look at the figure below to get an idea how this is implemented.

Using AVR Timers

Fig – Using AVR Timer to generate 1ms Time base.

 

 

Complete Code


#include <avr/io.h>
#include <avr/interrupt.h>

#include "lcd.h"

//Global variable for the clock system
volatile unsigned int   clock_millisecond=0;
volatile unsigned char  clock_second=0;

volatile unsigned char  clock_minute=0;

main()
{
   //Initialize the LCD Subsystem
   InitLCD(LS_BLINK);
   //Clear the display
   LCDClear();

   //Set up the timer1 as described in the
   //tutorial

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

   //Enable the Output Compare A interrupt
   TIMSK|=(1<<OCIE1A);


   LCDWriteStringXY(0,0,"Time Base Demo");
   LCDWriteStringXY(0,1,"  :   (MM:SS)");

   //Enable interrupts globally

   sei();

   //Continuasly display the time
   while(1)
   {
      LCDWriteIntXY(0,1,clock_minute,2);
      LCDWriteIntXY(3,1,clock_second,2);
      _delay_loop_2(0);
   }

}


//The output compate interrupt handler
//We set up the timer in such a way that
//this ISR is called exactly at 1ms interval
ISR(TIMER1_COMPA_vect)
{
   clock_millisecond++;
   if(clock_millisecond==1000)
   {
      clock_second++;
      clock_millisecond=0;
      if(clock_second==60)
      {
         clock_minute++;
         clock_second=0;
      }
   }
}


Hardware

The hardware is ATmega8-16PU running at 16MHz with a LCD Connected to it. I have used xBoard MINI to make the prototype. You can also use your own ATmega8 board. To make a board in your own see this. The output is displayed in a 16×2 character LCD module so please see the LCD interfacing tutorial for information about the connections and use. I recommend you to first setup and test the LCD interfacing because it will help you in many projects. If you have any problems setting it up please post a comment here or use the forum.eXtremeElectronics.co.in

xBoard MINI

Fig – xBoard MINI can be used to prototype many projects easily!

 

 

LCD interface with AVR MCU

Fig – The output of above program in 16×2 LCD module.

 

 

Goodbye for now. Meet you in next tutorials !!! And don’t forget to subscribe to my feed via email to receive latest tutorials direct in your mail box.

 

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

35 thoughts on “Timers in Compare Mode – Part II

  • By vishal - Reply

    fantastic work! it helped me a lot.

  • By Amir - Reply

    You are Great!
    thanks a lot…

  • By James Webster - Reply

    Very easy to read and understand.
    Thank you very much,has been a great help
    Kind regards
    James Webster

  • By Rolf - Reply

    The best tutorials on the web. 🙂
    Very easy to understand.
    Kind regards
    Rolf

    • By anil - Reply

      hai to all i m thankful to the people who uploading all these topics ,those are very helpful to understand the concept and very easy to understand…….

  • By O-Decaff - Reply

    Well written and understandable, with images. Took some time to prepair these pages. Excellent work. Thanks

  • By abcd - Reply

    Hey,
    one increment take 1/250000 = 0.000004 Sec . How did you say that each increment takes @ 0.000004 Sec? Actually that 250KHz is the clock input for the timer1. Can you please tell me how to calculate?

    • By Avinash - Reply

      @ABCD (You don’t even care to enter your real name in lazyness 🙁 )

      I can’t explain more than what told above.

  • By riya - Reply

    Hi,
    I am new to microcontrollers. I have started to learn Hardware. Can any one explain me for the following question?

    Suppose we are using 120 nanosecond ROMs, which have valid data on the bus 120 ns after the falling edge on the Output Enable line (see Figure 3.4 in the textbook to see how the OE pin is typically connected), and are using the microprocessor discussed in Figure 3.7 with a clock rate of 25 MHz (which means a clock cycle of 40 nanoseconds). How many wait states must the microprocessor insert into each bus cycle that reads from the ROM?

    Any good links related to this is also fine

    regards,
    riya

  • By anshu - Reply

    hey…………..thanks it helped me alot….. nice work…avinash

  • By Arturo - Reply

    Good tutorials
    Do you have something about DC motor control like the ones used in a tank type vehicle?

  • By lokesh kumar k @ nitk - Reply

    NICE WORK AVINASH.

  • By sameer - Reply

    you are really great…Your tutorials are saving lot of time for us..also it is inspiring us to outsource on net projects which we have done…

  • By wlewis - Reply

    Alternate method for restoring a dead atmega32.. ya know when you get that device signature = 0x00000 and yikes! from avrdude.

    Get a 4mhz (4 pin) crystal.. these are commonly available. The ones that have vcc,gnd and an “out”. Ok.. hook up vcc and gnd then connect crystal out to pin13 of atmega32.

  • By wlewis - Reply

    Alternate method for restoring a dead atmega32.. ya know like when you get device signature = 0x00000 and yikes! from avrdude.

    Get a 4mhz (4 pin) crystal.. these are commonly available. The ones that have vcc,gnd and an “out”. Ok.. hook up vcc and gnd then connect crystal out to pin13 of atmega32.

  • By VIVEK - Reply

    AWESOME TUTORIALS

  • By Alex - Reply

    Hello,

    I was wondering if you could help me with the following. I want to read data from an accelerometer, which encodes it into PWM form factor. So basically I need to read the PWM output from the sensor and measure the time the signal stays on logic “1”.

    I want to do this using the Input Capture Unit from Timer1 (ATMega16). I have tried the following code, but I can’t make the timer trigger on the falling edge. It seems to work fine on rising edge only. Can you tell me what’s wrong with it?
    ———————————————————
    #include
    #include

    // define global variables
    volatile unsigned char t1_overflow = 0;

    #define ICP PIND6

    //define interrupt routines
    ISR(TIMER1_OVF_vect)
    {
    t1_overflow++;
    }

    ISR(TIMER1_CAPT_vect)
    {
    //stop clock
    TCCR1B = 0x00;
    //clear input capture flag
    TIFR&=~(ICF1);

    if (ICP) //input pin is high
    {
    //do stuff here
    TCCR1B=0x81;//(1<<CS10) | (1<<ICNC1) ;
    }
    else //pin is low
    {
    //do stuff here

    //reset timer in desired mode
    TCCR1B=0xC1;//(1<<CS10) | (1<<ICNC1)|(1<<ICES1) ;
    }

    }

    int main(void)
    {
    DDRA=0xFF;

    //initialize Timer1
    TCCR1A = 0;
    TCCR1B=0xC1;//(1<<CS10) | (1<<ICNC1) | (1<<ICES1);
    TIMSK|=(1<<TICIE1) | (1<<TOIE1);

    TCNT1=0;
    ICR1=0;

    //enable global interrupts
    sei();

    //loop infinetly
    while ( 1 )
    {
    };

    return 1;
    }

  • Pingback: Timers in Compare Mode – Part I | eXtreme Electronics

  • By giotux - Reply

    Hi,
    I have a problem with the program…
    Virtually everything in the ATmega8 load, seems to work but it starts to count and after 2 seconds turns off the screen and see a “?” on the right …
    The electronic card I built, following the pattern:
    “https://extremeelectronics.co.in/avr-projects/avr-project-relay-timer-with-atmega8-avr-mcu/”
    I do not know what to do.
    thanks

  • By eng-mustafa - Reply

    The best tutorials
    Thank you very much

  • By pratik - Reply

    excellent work this has helped a lot

  • By Jonathan - Reply

    Great tutorial! Thanks a lot, this saved me many hours of work!

  • By kamal - Reply

    nice work.

  • By Shyam B - Reply

    You should make a book out of all these tutorials combined !! Call it say ‘The Alive Projects in Microcontrollers’ !! 🙂

  • By Khayti - Reply

    Its really a fantastic tutorial for beginners..It really helped me a lot…Can u tell me how can I set predefined time.So that it can start from 3.40 and not from 0:0

    • By Avinash - Reply

      @Khayti,

      Please read it once again and go through the code you would get the answer yourself ! 🙂

  • By Nino - Reply

    Sincerely,
    follow the good directions of the tutorial I wrote a few lines in an assembler routine to manage the timer 1 ATmega2560 microcontroller. Unfortunately at compile time with the Atmel Studio6 I got so many error messages: “1 operand out of range: 0x0081”. The latter is the address of the register used: for TCCR1B 0x0081, 0x0080 for TCCR1A and so on …
    Each instruction OUT I generated the message.

    .INCLUDE “m2560def.INC” ;
    .DEF tmp = R16
    ;
    .ORG $0000
    rjmp avvio
    .ORG $0022
    rjmp ISR_compara_tc1a
    ;
    ISR_compara_tc1a:
    ;ISR
    reti
    avvio:
    sbi DDRB,5 ; Imposta la PORTB5 (OC1A) a OUTPUT
    ldi tmp,(1 << WGM12) ; Configura il timer 1 per la modalità CTC
    out TCCR1B, tmp
    ldi tmp,(1 << COM1A0) ; Enable timer 1 Compare Output hannel A
    out TCCR1A, tmp
    ;
    ldi tmp, (1 << OCIE1A) ; Abilitazione interrupt di CTC
    out TIMSK1, tmp
    sei
    ;
    ldi tmp, low(4000) ; carico un valore di prova sul registro OCR1A
    out OCR1AL, tmp ; low
    ldi tmp, high(4000)
    out OCR1AH, tmp ; high
    ldi tmp, (1 << CS10) | (0 << CS11); Imposta il prescaler
    OUT TCCR1B,tmp

    ldi tmp, (1 << OCF1A)
    out TIFR1, tmp
    MAIN LOOP:
    RJMP MAIN_LOOP ;A DO-NOTHING LOOP
    With astonishment errors disappear if I set the program to the Timer0. In this case the compilation is correct and this allows me to follow the phases of the program in the simulation Studio6.

    Beginner confusion is total and I can not find the error.

    I ask for advice and I apologize for the translation made by Google

  • By Toggle - Reply

    Can anyone help me in calculating time in atmega 8 which is running parallely with the code .
    Like I have 3 input pin pb0 and pb1 and pb2 from which I am checking input. When I get first 1 either from pb0 or pb1 (assuming pb0 ) then I have to start the timer which counts for the time elapsed and simultaneously check the value for other two.When i recieve the the input 1 from pb1 then i have to stop the timer and when i recieve 1 from pb2 i have to keep the timer running. I am a begginer

  • By NanduKakkad - Reply

    With the same code above and the F_CPU = 16000000UL, around 20 s increasing every second….
    I’m using ATMega32 with AVRDude in Ubuntu 14.04.
    Please help me.
    I’m just fifteen…..

    • By Avinash - Reply

      @Nandu,

      Please post your problem here. Also pay attention to the language so that your problem is easily comprehensible!

  • By NanduKakkad - Reply

    Thank you for your instant reply.
    I’m using Atmega32 with 16MHz crystal..
    My programming software is AVRDude(http://www.ladyada.net/learn/avr/avrdude.html) &
    Programmer is USBASP.
    In 1 second time, around 16 s (pardon me for last comment(20 s) ) is increasing in the lcd.

    • By Avinash - Reply

      I meant that you post your problem using that form only! This place for comment is for different purpose, not for problem discussion.

      • By NanduKakkad -

        I’m sorry.
        I was just asking for a solution to my problem….

  • By NanduKakkad - Reply

    Can you help me?
    I’m just a beginner….

  • By Karanbir Soin - Reply

    Hi Avinash,
    in your code
    ” OCR1A=250; ”
    Shouldnt it be
    OCRA1 = 249;
    ?

Leave a Reply

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


9 + = ten

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>