I'm trying to implement a frequency counter using a dsPIC30F4011 I have not used input capture or timer interrupts before so would anyone be able to have a look through my program and spot any obvious mistakes, my readings from the UART seem to be all over the place while reading a signal from a function generator, Ideally I'm looking to read frequencies from 0.5 HZ to 60 HZ, Thanks for your time.
Rich (BB code):
# include <p30f4011.h>
# include <math.h>
# include <stdio.h>
# include<InCap.h>
# include <xc.h>
# include <libpic30.h>
#define LED LATDbits.LATD0
// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
// (units are instruction cycles, Tcy=33.33ns @ 30 MIPS)
_FWDT(WDT_OFF); // Watchdog timer off
_FBORPOR(MCLR_DIS); // Master Clear Pin disabled
/*************Global Variables and Constants*************/
/*Variables used for period calculation*/
unsigned int timePeriod= 0;
unsigned int current_value=0,previous_value=0;
unsigned int new_value=0;
void __attribute__((__interrupt__)) _IC7Interrupt(void);
void __attribute__((__interrupt__, __shadow__)) _T2Interrupt(void);
/****FUNCTION PROTOTYPES****/
void IC7_SETUP(void);
void TIMER2_SETUP (void);
void setup();
/******MAIN BODY******/
int main (void)
{
TRISD=0; // Setting Port D pins as outputs
PORTD=0; // Reset The LED
PORTD=0xff; // Light The LED, to test the PIC is working
TRISB=0x003f; // Setting all PortB as inputs
ADPCFG=0xffff; // Setting the analogue pin as digital inputs
TIMER2_SETUP(); // Calling the Timer Setup Function
IC7_SETUP(); // Calling the Input Setup Function
setup(); // Calling the UART function
while(1)
{
}
return (0);
}
/***SETUP_IC****/
void IC7_SETUP (void)
{
// Register 13-1: ICxCON: Input Capture x Control Register in datasheet //
IC7CONbits.ICM= 0b011; // Input Capture Mode Select (Every rising edge)
IC7CONbits.ICBNE=0; // Input Capture Buffer Empty Status (Read Only)
IC7CONbits.ICOV=0; // Input Capture Overflow Status Flag (Read Only)
IC7CONbits.ICI= 00; // Select Number of Captures per Interrupt bits (00 = Interrupt on every capture event)
IC7CONbits.ICTMR=1; // Input Capture Timer Select bits (1=TMR2 contents are captured on captured event)
IC7CONbits.ICSIDL=0; // Input Capture Module Stop in Idle Control(0=Input capture module will continue to operate in CPU Idle mode)
// Register 6-6: IFS1: Interrupt Flag Status Register 1
IFS1bits.IC7IF = 0; // Input Capture Channel 7 Interrupt Flag Status )0=Interrupt bit is cleared
// Register 6-9: IEC1: Interrupt Enable Control Register 1
IEC1bits.IC7IE = 1; // Input Capture Channel 7 Interrupt Enable bit (1 = Interrupt request enabled)
}
/****INTERRUPT FOR IC7****/
// Capture Interrupt Service Routine
//unsigned int timePeriod= 0;
void __attribute__((__interrupt__, no_auto_psv )) _IC7Interrupt(void)
{
previous_value=current_value;
current_value=IC7BUF;
printf("Current value =%d \n, ",current_value);
printf("Previous value =%d \n, ",previous_value);
float time1 = 0;
float time2 = 0;
float time3 = 0;
float time4 = 0;
float frequency = 0;
if(current_value>previous_value)
{
timePeriod = current_value-previous_value;
printf("timePeriod =%d \n, ",timePeriod);
time1 = timePeriod*pow(33.33,-9);
time2 = pow((float)time2, -9);
frequency = 1/time2;
printf("frequency=%f Hz \n, ",time1);
}
}
/***TIMER_SETUP***/
void TIMER2_SETUP (void)
{
T2CON = 0x00; // Stops the Timer2 and reset control reg.
T2CONbits.TCS=0; // Using Internal Clock (Fosc/4)
T2CONbits.T32=0; // TMR2 and TMR3 form separate 16-bit timer
T2CONbits.TCKPS=0; // Using 1:1 prescale value
T2CONbits.TGATE=0; // Timer Gate Accumulation Disabled
T2CONbits.TSIDL=0; // Continue in Idle Mode*/
TMR2 = 0x00; // Clear contents of the timer register
PR2 = 0xFFFF; // Load the Period register with the value 0xFFFF
IPC1bits.T2IP = 0x01; // Setup Timer2 interrupt for desired priority leve
// (This example assigns level 1 priority)
IFS0bits.T2IF = 0; // Clear the Timer2 interrupt status flag
IEC0bits.T2IE = 1; // Enable Timer1 interrupts
T2CONbits.TON = 1; // Start Timer1 with prescaler settings at 1:1 and
// clock source set to the internal instruction cycle
}
/* Example code for Timer1 ISR*/
void __attribute__((__interrupt__, no_auto_psv, __shadow__)) _T2Interrupt(void)
{
/* Interrupt Service Routine code goes here */
IFS0bits.T2IF = 0; //Reset Timer1 interrupt flag and Return from ISR
}
void setup()
{
// Set up UART
// Default is 8 data bits, 1 stop bit, no parity bit
U1BRG = 48; // 38400 baud @ 30 MIPS
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXISEL = 1; // interrupt when TX buffer is empty
U1STAbits.UTXEN = 1; // Enable TX
}