Recording a Periodic Signal using Input Capture Feature of Timers/Counters

 

COMSATS UNIVERSITY ISLAMABAD

MICROPROCESSOR SYSTEMS AND INTERFACING

 

LAB REPORT #10

 

SUBMITTED TO:

SIR KHIYAM IFTIKHAR

SUBMITTED BY: -

S/NO

NAME

REG NO

1

JUNAID AHMAD

CIIT/FA19-BEE-089/ISB

2

IBRAR AHMAD

CIIT/FA19-BEE-083/ISB

3

JARRAR MALIK

CIIT/FA19-BEE-087/ISB

 

 

DATE:

10-12-2021

 

Lab # 10 Recording a Periodic Signal using Input Capture Feature of Timers/Counters

Pre-Lab:

 

Input Capture:

In many applications, we are interested in measuring the elapsed time or the frequency of an external event using a microcontroller. Using the hardware and functional units discussed in the previous sections, we now present a procedure to accomplish the task of computing the frequency of an incoming periodic signal. Figure 10.1 shows an incoming periodic signal to our microcontroller.

 

In Lab:

 

Task 1:

The expected input signal is a periodic pulse train. The task is to find the frequency/time period and duty cycle of this signal. The frequency of this signal is expected to be less than 4 KHz. The given code configures Atmega328P interrupt subsystem to work with external interrupts and input capture of Timer1. It also performs the necessary calculations to find the frequency and duty cycle of the input signal and displays it on a terminal. You will have to understand the code and then configure Timer1 for input capture.

CODE:

/*

 * lab10task1.c

 *

 * Created: 11/26/2021 9:05:24 AM

 * Author : AEGON

 */

 

#include <inttypes.h>

#include <stdlib.h>

#include <avr/io.h>

#include <avr/interrupt.h> // Add the necessary ones

#define F_CPU 16000000UL

#include <util/delay.h>

#include <string.h>

#include <math.h>

/****************** Definitions for UART *********************/

#include "debug_prints.c"

#define BAUD0 9600 // Baud Rate for UART

#define MYUBRR (F_CPU/8/BAUD0-1) // U2X = 1

/*********************************************************************

************/

/****************** Global Variables ************************/

unsigned char icp_low = 0;

unsigned char icp_high = 0;

unsigned int input_capt_counter=0;

unsigned int rising1 = 0;

unsigned int rising2 = 0;

unsigned int falling1 = 0;

unsigned char capture_complete=0;

float sig_freq = 0;

float sig_dc = 0;

/************************************************************/

#define TRUE 1

#define FALSE 0

/*************** Function Prototypes here ********************/

void timer_init(void); // Function to initialize Timer1 for Input Capture

void display_counter_values(void);

void display_signal_parameters(void);

void calculate_signal_param(void);

// ***********************************************************

// Main program

//

int main(void)

{

       DDRB&=(1<<PB0);

       // Set PB0 (ICP1) for input

       PORTB|= (1<<PB0);

       // Activate internal pull-up

 

       UART0_init(MYUBRR);

       printSerialInt(MYUBRR);

       printSerialStrln("");

       printSerialStr("F_CPU = ");

       printSerialInt((int)(F_CPU/1000000));

       printSerialStrln("MHz");

       printSerialStrln("Lab 10: Input Capture");

       timer_init();

       //******* Write Code For This ********//

       EICRA|=(1<<ISC01); //Set interrupt sense control bits to falling edge for INT0

       EIMSK|=(1<<INT0);//Enable INT0 locally

       SREG=(1<<7);// Enable interrupts globally

       int i=0;

       while(1)

{

       if(capture_complete == TRUE)

       {

              display_signal_parameters(); // display frequency and duty cycle

              capture_complete = FALSE;

              for(i=0; i<8; i++) // wait for 2 seconds

              _delay_ms(250);

             

              printSerialStrln("Press the button ..");

       }

}

}

/* This function will setup Timer1 for Input Capture Mode.

if Fclk = 16MHz, and prescaler = 8, then 1 count = 0.5us. 2000

counts will fit a Time period of 1ms (f = 1 KHz). 500 Counts

will fit a Time period of 0.25 ms (f = 4 KHz).

*/

void timer_init(void) // Write code for this function

{

       ACSR &= ~(1<<ACIC); // Disconnect the Analog Comparator output from the Input Capture Unit

       TCCR1A=0x00;// Normal Mode, OC1A and OC1B disconnected.

       TCCR1B|=(1<<ICES1);

       TCCR1B|=(1<<CS11);// Initially capture rising edge. Pre scaler = 8

       TCNT1L = 0;

       TCNT1H = 0;

       TIMSK1|=(1<<ICIE1);// Enable interrupt of Timer 1 input capture

 

       // Enable interrupt of Timer 1 input capture

}

/* Interrupt Service Routine for INT0. When the user presses

the button, the ISR clears TCNT1, capture_complete, rising1,

rising2 and falling1 global variables. Then it turns on the

interrupts for Timer1 Input Capture. */

 

ISR(INT0_vect)

{

       //printSerialStrln("Processing External Interrupt 0: ");

       rising1 = 0;

       rising2 = 0;

       falling1 = 0;

       capture_complete = FALSE;

       input_capt_counter = 0;

       sig_freq = 0;

       sig_dc = 0;

       TCCR1B |= (1<<ICES1); // for rising edge on ICP1

       TCNT1 = 0; // clear the free running counter of Timer 1

       TIMSK1 |= (1<<ICIE1); // Enable interrupt of Timer 1 input capture

}

/* ISR for Input Capture of Timer1. You need to write

code and complete this function*/

ISR(TIMER1_CAPT_vect)

{

       //printSerialStrln("Processing Timer Interrupt: ");

       icp_low = ICR1L;

       icp_high = ICR1H;

       input_capt_counter ++;

       //printSerialInt((int)input_capt_counter);

       //printSerialStrln("");

       if(input_capt_counter == 2)

       { rising1=(ICR1H<<8)|(ICR1L);// Record the counter value on first Rising Edge

       }

       if(input_capt_counter == 3)

       {

               rising2=(ICR1H<<8)|(ICR1L); // Record the counter value on second Rising Edge

              TCCR1B&=~(1<<ICES1); // Change the polarity of sensing

              TIFR1=(1<<ICF1);// Clear ICF flag as prescribed in the Datasheet Page 157 Section 20.9.3

       }

 

if(input_capt_counter == 4)

{

       falling1=(ICR1H<<8)|(ICR1L);// Record the counter value on first Falling Edge

       TIMSK1&=~(1<<ICIE1);// disable further interrupts of Timer 1 input capture

       capture_complete = TRUE; // capture is complete at this point

       calculate_signal_param(); // calculate the Frequency and Duty Cycle of the Input Signal

}

}

 

/** This function displays the values of the

captured edges 'rising1', 'rising2', and

'falling1'.

*/

void display_counter_values()

{

       printSerialStr("Rising 1: ");

       printSerialLong((long int) rising1);

       printSerialStrln("");

       printSerialStr("Rising 2: ");

       printSerialLong((long int) rising2);

       printSerialStrln("");

       printSerialStr("Falling 1: ");

printSerialLong((long int) falling1);

printSerialStrln("");

}

/** Function to display the Frequency and Duty Cycle

of the Captured signal.*/

void display_signal_parameters(void)

{

       printSerialStr("Frequency = ");

       printSerialFloat(sig_freq);

       printSerialStrln(" Hz");

       printSerialStr("Duty Cycle = ");

       printSerialFloat(sig_dc);

       printSerialStrln(" %");

}

/** This function is called after all the required edges

are captured and saved in global variables 'rising1',

'rising2', and 'falling1'. It calculates the input signal

frequency and its duty cycle and saves them in corresponding

variables.*/

void calculate_signal_param(void)

{

       { printSerialStrln("Calculating Signal Parameters ... ");

             

                      sig_freq = 2000000/(rising2-rising1);   //Here Prescalar = 8 so Ftimer == F_CPU/8

                     sig_dc = 100.0* (falling1 - rising2)/(rising2-rising1); // ON-Time/ Total Time * 100 %

             

      

       //Complete this function

 

display_counter_values();

display_signal_parameters();

}

}

PROTEUS -SIMULATION:






Critical Analysis / Conclusion:

 

In this lab experiment we studied about some important features of Timers and counters we used timer 1 which is 16 bit timer, we also learned how to calculate the duty cycle of wave if its frequency is given , In the lab task I got to know how to configure the ATtmega 328p with virtual instrument and oscilloscope. I also understood the code and performed the proteus simulations in which I gave pulse input to ATmega 328p and observed the output pulses of frequency 4kHz on oscilloscope at channel A.

Post a Comment

Post a Comment (0)

Previous Post Next Post