2
\$\begingroup\$

I'm trying to use the input capture module on a PIC32MX250F128B to measure the frequency of a square wave. The results I'm getting are both inconsistent and incorrect. All I'm trying to do here is measure the frequency of the input square wave by reading the capture value at every falling edge interrupt. Then I reset Timer2 and read the capture value again at the next interrupt.

Here's my ISR:

void __ISR(_INPUT_CAPTURE_4_VECTOR, ipl1) Capture4(void) {
    mPORTBToggleBits(BIT_10);
    capture_value = IC4BUF; 
    mIC4ClearIntFlag();
    TMR2 = 0;
}

Here's my module configurations:

IC4Rbits.IC4R = 0;     // Assign peripheral pin RPA0 to IC4
mPORTASetPinsDigitalIn(BIT_0);
IC4CONbits.C32 = 0;    // 16-bit source timer
IC4CONbits.ICTMR = 1;  // Use Timer2
IC4CONbits.ICI = 0;    // Interrupt every capture event
IC4CONbits.ICM = 2;    // Simple Capture Event mode - every falling edge
IFS0bits.IC4IF = 0;    // Clear interrupt flag
IFS0bits.IC4IE = 1     // Enable IC interrupt
IFS0bits..IC4IP = 1;   // Set interrupt priority to 1
IC4CONbits.ON = 1;     // Enable IC module

T2CONbits.ON = 0;      // Disable while config
TCONbits.SIDLE  = 0;   // Continue in idle mode
TCONbits.TCS = 0;      // Use internal clock
TCONbits.TCKPS = 0;    // Set 1:1 prescale
TCONbits.TGATE = 0;    // Disable gated time accumulation
PR2 = 0xFFFF;          // set period register
TMR2 = 0;              // start counting at zero
T2CONbits.ON = 1;      // enable module

You'll notice the first line of the ISR toggles a digital output pin; I added this so I could monitor the activity to see if the interrupt was ever called. The interrupt does get called and I've viewed it on an oscilloscope. I would expect the ISR to be called consistently in line with the falling edges of the input square wave but this is not the case. Instead, the ISR is called inconsistently at seemingly random intervals. Also, the values being read from IC4BUF don't correlate at all with any adjustments to the input signal's frequency.

Clearly I'm missing something here. If you have any suggestions or can point out any obvious errors that I've made, that would be greatly appreciated. Also, I'm open to alternative methods for accomplishing the task of measuring the input frequency. I chose this route with the Input Capture because it seemed to make the most sense. Thanks!

\$\endgroup\$
  • \$\begingroup\$ What range of frequencies are you aiming to measure, and what is the clock speed of your PIC? \$\endgroup\$ – brhans Mar 30 '15 at 18:29
  • \$\begingroup\$ Is capture_value declared as volatile? \$\endgroup\$ – Roger Rowland Mar 30 '15 at 18:55
  • \$\begingroup\$ The PIC is clocking at 48 MHz. I'm anticipating inputs ranging from 0.1 - 100 KHz \$\endgroup\$ – JBrown Mar 30 '15 at 19:05
  • \$\begingroup\$ @RogerRowland, yes I've tried with capture_value declared as volatile, no change \$\endgroup\$ – JBrown Mar 30 '15 at 23:23
1
\$\begingroup\$

Check this command: IFS0bits.IC4IE = 1. Here IEC0 register should be used IFS0 is used to check the flag bits which get SET when any interrupt occurs. So, modify your command as follows:

IEC0bits.IC4IE = 1

(If it still does not work then check your datasheet for the location of IC4IE bit.)

IFS0bits..IC4IP = 1 : this command is also wrong , you have to use IPC0 register for setting the priority of the Input Capture.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.