dsPIC Frequency counter

Thread Starter

D8666

Joined Nov 15, 2013
16
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
}
 
Top