ATmega32A Input Capture Example

Input capture in AVR microcontroller allows users to capture external events and measure signal properties such as period, frequency or duty cycle. It can also be used to capture time stamp of occurrence of the signal to create log/record of the events and can also be used to count events. Here it is explained how the ATmega32A/ATmega32 input capture works with example application and program code.

For illustrating the input capture of ATmega32 we will use a push button which when pressed the input capture is triggered and a LED is turned on. The following circuit diagram and animation illustrates this.

ATmega32A input capture
The ATmega32A has three timers/counters called timer/counter 0, timer/counter1 and timer/counter  2.Out of these timers only the timer 1 has the capability of input capture. 

The timer/counter 1 hardware block diagram of ATmega32A is shown below.

Timer 1 block diagram
In this block diagram, the registers and the hardware associated with input capture is highlighted in yellow. The timer 1 is a 16 bit timer/counter. The input signal which we want to capture and measure is connected to the ICP1 pin which is PD6(Port D pin 6) pin.

A more detailed diagram of the input capture hardware which shows registers, and other hardware involved and flags involved is shown below.

In order to use the input capture feature the timer1 must be configured for input capture, the trigger source must be configured, and the condition for capturing events must be configured. After this we can either poll the ICF1 flag and do the storing or processing of the input signal data or we can use the input capture hardware interrupt.

So the steps in using input capture is as follows.

1. Set the mode of operation as Normal mode with pre-scalar 1024

2.  Disable ICNC1(Input Capture Noise Canceler 1) and Set ICES1(Input Capture Pin 1)

1. Set the mode of operation as Normal mode with pre-scalar of 1(no pre-scalar).

The mode of operation is set using the WGM bits and the prescalar is set using the CS bits. These bits are located in the TCCR1A and TCCR1B registers.


 

The normal mode all WGM bits are set to 0.


 The CS bits which sets the pre-scalar N=1 are selected such that CS10 is 1 and CS12,CS11 are 0.

Also for normal mode all COM bits are set to 0 and the force output compare are not required so the FOC bits are set to 0.

2.  Disable ICNC1(Input Capture Noise Canceler 1) and Set ICES1(Input Capture Edge Select 1)

The ICNC1(Input Capture Noise Canceler 1) and ICES1(Input Capture Edge Select 1) are located in the TCCR1B register. To disable the input capture noise canceler, this bit is 0 and the input capture edge select is set to 1 to sample the incoming signal on rising edge.

So the configuration of the TCCR1A and TCCR1B register in C program is,


TCCR1A = 0b00000000;	//COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
TCCR1B = 0b01000001;	//ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10

3. Poll ICF1 flag 

When signal edge is detected by the input capture, the ICF1 flag is set. So we can poll the ICF1 flag which is located in the TIFR(Timer Interrupt Flag Register).

TIFR

This is done in C program in the following way.


while((TIFR & (1<<ICF1)) == 0);	//poll the ICF1 bit

We can then clear the ICF1 flag as follows for next edge detection.


TIFR |= (1<<ICF1);	//clear the ICF1

6. Take action after input capture

After detecting the external signal via edge detection, the next step is to take action. This action could be any application such as DC motor control, reading LM35 temperature sensor data or simply turn on a LED.

In this input capture example, we turn on a LED for 1 second when the push button press is detected. This is done in C program as follows.


PORTC |= LED; 	  //turn on LED on event
_delay_ms(1000);  //LED on for 1 sec
PORTC &= ~LED;	  //turn off LED after 1sec	

C program code for Input Capture

Below is the complete code for this tutorial which uses input capture to detect push press and turns on a LED for 1 second.


#include <avr/io.h>
#include <util/delay.h>

#define ICP (1<<PD6)
#define LED (1<<PC5)


int main(){ 
    DDRC |= LED;	//configure LED pin as output
    DDRD &= ~ICP;	//configure input capture pin as input
    PORTD |= ICP;	//activate input capture pin internal pullup 

//Timer 1 config: no noise canceller, rising edge, normal mode, no prescalar
    TCCR1A = 0b00000000;	//COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
    TCCR1B = 0b01000001;	//ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10

   while (1){
		while((TIFR & (1<<ICF1)) == 0);	//poll the ICF1 bit
		TIFR |= (1<<ICF1);	//clear the ICF1
		PORTC |= LED; 	//turn on LED on event
		_delay_ms(1000);	//LED on for 1 sec
		PORTC &= ~LED;	//turn off LED	after 1sec	
	}
   return 0;
 }

So in this tutorial it was illustrated how to use input capture with ATmega32A microcontroller. The following are input capture example with ATmega328p microcontroller.

Programming ATmega328p Input Capture

Programming ATmega328P Input Capture with Interrupt

Post a Comment

Previous Post Next Post