Input capture mode

The input capture mode is used to capture external events and give them a timestamp that can be used to measure frequency, duty cycle or period times. 

To measure an event with Timer 1, the time is captured or held at the beginning of the event, the time is also captured at the end of the event, and the two are subtracted to find the time that it took for the event to occur. These tasks are managed by the input capture register (ICR1). ICR1 is a 16-bit register (ICR1H and ICR1L) that will capture the actual reading of Timer 1 when the microcontroller receives a certain signal. The signal that causes a capture to occur can be either a rising or a falling edge applied to the input capture pin (ICP) of the microcontroller. Since there is only one capture register available to TIMER1, the captured contents must be read out as soon as they are captured to prevent the next capture from overwriting and destroying the previous reading. In order to accomplish this, an interrupt is provided that occurs whenever new data is captured into ICR1. Each time the capture interrupt occurs, the program must determine whether the interrupt signals the beginning or the ending of an event that is being timed so that it can treat the data in ICR1 appropriately.

The program example below demonstrate the use of the input capture mode. The goal of this hardware and software is to measure the period of a square wave applied to the input capture pin (ICP) of the microcontroller and to output the result, in milliseconds on an LCD display connected to PORTD. For this project the ATMEGA328 board is used connected to a LCD display.

 

// program name: TIMER1_icp
// date: 30.08.2015
// author: www.avrprojects.net
// target device: atmega328
// hardware: ATMEGA326 board input capture pin
// software: WinAVR-20100110 compiler
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/lcd.h>
unsigned cha rov_counter,counter;/*counter for timer 1 overflow*/
unsigned int starting_edge,ending_edge;/*storage for times*/
unsigned int clocks;/*storage for actual clock counts in the pulse*/ ISR(TIMER1_OVF_vect)
{
ov_counter++; /*increment counter when overflow occurs*/
} ISR(TIMER1_CAPT_vect)
{ending_edge=256*ICR1H+ICR1L;//get end time for period
clocks=(unsignedlong)ending_edge+((unsignedlong)ov_counter*65536)-(unsignedlong)starting_edge;//clear overflow counter for this measurement ov_counter=0;//save end time to use as starting edge starting_edge=ending_edge;} intmain(void)
{LCDini();
DDRD=0xFF;/*set Port D for output*/
TCCR1A=0x00;/*disable all waveform functions*/
TCCR1B=0b10000101;/*Timer 1 input to clock/1024, enable input capture*/
TIMSK=0x24;/*unmask timer1 overflow and capture interrupts*/
sei();
LCDtxt("TIMER1 icp"); while(1) { LCDgoto(0,1); LCDint(clocks/16);// divide clocks by 16 gives milliseconds LCDtxt(" mS "); }
}