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