incap_freqmeasure.c - Uses IC1 to measure period, uses averaging mode.ΒΆ
//Measures square wave frequency using input capture and Timer2
#include "pic24_all.h"
#include <stdio.h>
uint8_t getPeriodAdjust (uint8_t ICMbits) {
if (ICMbits == IC_EVERY_16_RISE_EDGE) return 16;
else if (ICMbits == IC_EVERY_4_RISE_EDGE) return 4;
else return 1;
}
volatile uint8_t u8_captureFlag = 0;
volatile uint16_t u16_lastCapture;
volatile uint16_t u16_thisCapture;
volatile uint32_t u32_period;
void _ISRFAST _IC1Interrupt() {
_IC1IF = 0;
u16_thisCapture = IC1BUF; //always read the buffer to prevent overflow
if (u8_captureFlag == 0) {
u32_period = (uint32_t) computeDeltaTicks(u16_lastCapture,u16_thisCapture,PR2);
u32_period = ticksToNs (u32_period, getTimerPrescale(T2CONbits));
//adjust period if necessary
#if (defined(__dsPIC33E__) || defined(__PIC24E__))
u32_period = u32_period/getPeriodAdjust(IC1CON1bits.ICM);
#else
u32_period = u32_period/getPeriodAdjust(IC1CONbits.ICM);
#endif
u8_captureFlag = 1;
}
u16_lastCapture = u16_thisCapture;
}
void configInputCapture1(void) {
CONFIG_RB13_AS_DIG_INPUT();
CONFIG_IC1_TO_RP(RB13_RP); //map IC1 to RP13/RB13
#ifdef IC1CON1
IC1CON1 = IC_TIMER2_SRC | //Timer2 source
IC_INT_1CAPTURE | //Interrupt every capture
IC_EVERY_16_RISE_EDGE; //capture every 16th edge
cascade off, sync mode, sync to timer 2
IC1CON2 = IC_IC32_OFF| IC_SYNC_MODE | IC_SYNCSEL_TIMER2;
#endif
#ifdef IC1CON
IC1CON = IC_TIMER2_SRC | //Timer2 source
IC_INT_1CAPTURE | //Interrupt every capture
IC_EVERY_16_RISE_EDGE; //capture every 16th edge
#endif
_IC1IF = 0;
_IC1IP = 1; //pick a priority
_IC1IE = 1; //enable
}
void configTimer2(void) {
T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
| T2_32BIT_MODE_OFF
| T2_SOURCE_INT
| T2_PS_1_64 ; //1 tick = 1.6 us at FCY=40 MHz
PR2 = 0xFFFF; //maximum period
TMR2 = 0; //clear timer2 value
_T2IF = 0; //clear interrupt flag
T2CONbits.TON = 1; //turn on the timer
}
int main (void) {
uint32_t u32_maxPeriodNs;
float f_freqkhz;
configBasic(HELLO_MSG);
configTimer2();
configInputCapture1();
#ifdef IC1CON1
u32_maxPeriodNs = ticksToNs (65536, getTimerPrescale(T2CONbits))/getPeriodAdjust(IC1CON1bits.ICM);
#else
u32_maxPeriodNs = ticksToNs (65536, getTimerPrescale(T2CONbits))/getPeriodAdjust(IC1CONbits.ICM);
#endif
printf("Maximum period is %ld ns\n",u32_maxPeriodNs);
while (1) {
outString("Capturing\n");
while (!u8_captureFlag) doHeartbeat();
f_freqkhz = (1.0/(((double)u32_period) *1.0e-9))/1000.0;
printf("Period: %ld ns, Freq: %6.2f kHz\n",u32_period,(double)f_freqkhz);
u8_captureFlag = 0;
DELAY_MS(500); //do not flood uart
}
}