About input capture question

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

About input capture question

393 Views
qianoocheng
Contributor I

    I,m using S12ZVC64 for capture square wave's frequency and duty。 The input frequency is between 10Hz and 3000Hzbut it not work.just use PT5 as single input , when  The input frequency is 1000Hz, if dubug the code,it just join in the interrupt one time.

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */


#define TIMER_PRESCALER 1 // 1,2,4,8,16,32,64,128
#define MAX_OVERFLOWS 1000L // max. allowed number of TIM overflows
#define NEW_VALUE_PREPARED Flags.bit.f0 // info for sending data
#define FREQUENCY_TOO_LOW Flags.bit.f1 // mesured frequency is lower thannot measurablelower than
#define FIRST_EDGE 1
#define SECOND_EDGE 0
#define STOP_MEASUREMENT 3
#define TIM0_Channel5_VEC_OFF 0x1B8
#define TIM0_Overflow_VEC_OFF 0x1AC

#define SET_INTERRUPT_PRIORITY(vec_off, priority) \
INT_CFADDR= (vec_off/4) & 0xF8; \
INT_CFDATA_ARR[(vec_off/4) & 0x03]= (priority)

//----- DEPENDENT DEFINITIONS -----
#if TIMER_PRESCALER==1
#define PRESCALER 0
#endif
#if TIMER_PRESCALER==2
#define PRESCALER 1
#endif
#if TIMER_PRESCALER==4
#define PRESCALER 2
#endif
#if TIMER_PRESCALER==8
#define PRESCALER 3
#endif
#if TIMER_PRESCALER==16
#define PRESCALER 4
#endif
#if TIMER_PRESCALER==32
#define PRESCALER 5
#endif
#if TIMER_PRESCALER==64
#define PRESCALER 6
#endif
#if TIMER_PRESCALER==128
#define PRESCALER 7
#endif
//

/*******************************************************************************
* Local types
******************************************************************************/
typedef unsigned char UBYTE;
typedef char SBYTE;
typedef unsigned int UWORD;
typedef int SWORD;
typedef unsigned long ULONG;
typedef long SLONG;
typedef union Flags
{
UBYTE byte;
struct
{
UBYTE f0 :1;
UBYTE f1 :1;
UBYTE f2 :1;
UBYTE f3 :1;
UBYTE f4 :1;
UBYTE f5 :1;
UBYTE f6 :1;
UBYTE f7 :1;
} bit;
} FLAGS;
static void IOC5_Init(void);
static void PLL_Init(void);
void GPIO_Init(void);
/*******************************************************************************
* Local variables
******************************************************************************/
static ULONG period; // calcualted period between two rising edges
static UWORD ch0ovfCnt; // the number of main timer overflows between

volatile FLAGS Flags; // general purpose flags
// rising edges
static UWORD tFirstEdge = 0; // value of the timer when period starts
static UWORD tSecondEdge= 0; // value of the timer when period finishes
//static UBYTE mPhase;
static UBYTE mPhase = STOP_MEASUREMENT;
static UWORD Fre;

static void PLL_Init(void){
//USE External Power 0x06 not use:0x05
CPMUVREGCTL = 0x06; //Internal voltage regulator for VDDX domain
//CPMUVREGCTL = 0x05; //Internal voltage regulator for VDDX domain

CPMUCLKS_PLLSEL = 1; //FBUS = FPLL/2. FBUS = 16MHz,
CPMUREFDIV_REFFRQ = 0x00; //Reference clock between 2MHZ and 6MHZ.
CPMUREFDIV_REFDIV = 0x3; //FREF=8/(1+3) = 2MHZ
//00: 32MHz <= fVCO <= 48MHz
//01: 48MHz < fVCO <= 64MHz
CPMUSYNR_VCOFRQ = 0x00; //FVCO is between 48MHZ and 80MHZ
CPMUSYNR_SYNDIV = 0x7; //FVCO = 2xFREFx(SYNDIV+1) = FVCO = 2x2x(7+1) = 32MHZ
CPMUPOSTDIV_POSTDIV = 0x1;//FPLL = FVCO/(POSTDIV+1). FPLL = 32MHZ/(0+1) FPLL = 32MHz

CPMUOSC_OSCE = 1;//External oscillator enable. 8MHZ. FREF=FOSC/(REFDIV+1)
while (!CPMUIFLG_LOCK) {} // Wait for LOCK.
CPMUIFLG = 0xFF;// clear CMPMU int flags - not needed but good practice


//浣胯兘RTI 涓柇
// Source IRCLOCK 1M
//0x80:1ms 0x81:2ms 0x82:5ms 0x83: 10ms 0x84:20ms
CPMURTI=0x80; // 璁剧疆RTICTL涓?0101 1001 婧㈠嚭鍛ㄦ湡涓?(9+1)*2^(15)/(32M)= 10*2^15/(32M)
CPMUINT_RTIE=1; // 鍏佽鍦ㄦ瘡涓懆鏈熺粨鏉熶骇鐢熶腑鏂?
}

static void IOC5_Init(void){

PERT_PERT5 = 1; // an internal pull resitor enable
PPST_PPST5 = 0; // an internal pull up connected
TIM0TIOS_IOS5 = 0x00; //指定通道5为输入捕捉方式
TIM0TCTL3_EDG5A = 0x01;
TIM0TCTL3_EDG5B = 0x0;

//TIM1 16M
//32M/2 = 8M
TIM0TSCR2_PR = 0x01; // 16M/ 1^1 = 16M
TIM0TIE_C5I = 0x0; // 允许通道5定时中断
TIM0TSCR2_TOI = 0;
TIM0TSCR1 = 0x60;
}

#pragma CODE_SEG NON_BANKED
interrupt VectorNumber_Vtim0ch5 void vectorNumber_Vtim0ch5(void){
unsigned int ttt, tof;
tof = TIM0TFLG2_TOF; // check whether additional TOF appeared
ttt = TIM0TC5; // get TCNT value
if( mPhase == FIRST_EDGE )
{
// what happens if ovfs happened while going to this interrupt?...solution
if( tof )
{ // a new period has already started
if( ttt < 32768 ) TIM0TFLG2_TOF = 1; // clear ovf interrupt flag
}
ch0ovfCnt = 0; // reset overflows counter
//--------------------------
tFirstEdge = ttt; // get first edge value
mPhase = SECOND_EDGE; // set configuration to get second edge
TIM0TFLG1_C5F = 1; // clear interrupt flag from PT5
return; // go back to wait for second edge
}
else
{
// what happens if ovfs happened while going to this interrupt?...solution
if( tof )
{ // a new period has already started
if( ttt < 32768 ) ch0ovfCnt++;
}
//--------------------------

tSecondEdge = ttt; // read new captured value and clear flag
// stop measurement
TIM0TSCR2_TOI = 0; // disable ovf interrupt
TIM0TIE_C5I = 0; // disable Ch5 interrupt
TIM0TFLG1_C5F = 1; // clear interrupt flag from PT5
}
// Ch0 period calculation
if( !ch0ovfCnt ) // Did edges appear within one timer period?
{
period = ( ULONG ) ( tSecondEdge - tFirstEdge );
}
else // some number of overflows has appeared between two edges
{
// time given by overflows period=....
period = ( ULONG ) ( ~tFirstEdge + 1 ); // time in the first period
period += ( ULONG ) ( tSecondEdge ); // time in the last period
period += ( ULONG ) (( ULONG ) ( ch0ovfCnt - 1 ) * ( ULONG ) ( 65536 ));
}
NEW_VALUE_PREPARED = TRUE; // information for main routine
}
#pragma CODE_SEG DEFAULT

#pragma CODE_SEG NON_BANKED
interrupt VectorNumber_Vtim0ovf void TIM0_Overflow_ISR(void) {

ch0ovfCnt++; // count overflows

if( ch0ovfCnt > MAX_OVERFLOWS )
{
ch0ovfCnt = 0;
FREQUENCY_TOO_LOW = TRUE;
// stop measurement
TIM0TSCR2_TOI = 0; // disable ovf interrupt
TIM0TIE_C5I = 0; // disable Ch5 interrupt
TIM0TFLG1_C5F = 1; // clear interrupt flag from PT5
NEW_VALUE_PREPARED = TRUE; // information for main routine
}
else
{
FREQUENCY_TOO_LOW = FALSE;
}
TIM0TFLG2_TOF = 0x1;

}
#pragma CODE_SEG DEFAULT
void GPIO_Init(void){

//=== GPIO INIT ================
DDRT_DDRT5 = 0; // PT5 input port
PERT_PERT5 = 1; // Pull resistor enabled at PT5
PPST_PPST5 = 1; // Pull down selected at PT5

DDRS_DDRS6 = 1; // output port
PTS_PTS6 = 0; // output port
}
void main(void) {
PLL_Init();
GPIO_Init();
FREQUENCY_TOO_LOW = TRUE; // set flag
NEW_VALUE_PREPARED = FALSE; // set flag
SET_INTERRUPT_PRIORITY(TIM0_Channel5_VEC_OFF, 7); // max priority
SET_INTERRUPT_PRIORITY(TIM0_Overflow_VEC_OFF, 6); // less priority than IC0
IOC5_Init();

TIM0TSCR2_TOI = 1;
TIM0TIE_C5I = 0x01; // 允许通道2定时中断
EnableInterrupts;
/* include your code here */

for(;;) {
// __RESET_WATCHDOG(); /* feeds the dog */

FREQUENCY_TOO_LOW = FALSE; // clear flag
NEW_VALUE_PREPARED = FALSE; // set flag
ch0ovfCnt = 0; // clear number of ovfs interrupts
TIM0TFLG1_C5F = 1; // clear interrupt flag from PT0
TIM0TFLG2_TOF = 0x1; // clear interrupt TOV flag
mPhase = FIRST_EDGE; // prepare processing of a first edge
TIM0TSCR1_TEN = 1; // run timer
TIM0TIE_C5I = 1; // enable Ch5 interrupt
TIM0TSCR2_TOI = 1; // enable ovf interrupt
while( !NEW_VALUE_PREPARED ) // wait for measurement
{
}

if(FREQUENCY_TOO_LOW){
Fre=0;
}
else Fre=period/16000000;

asm nop;                    // only for debug purposes for brkpnt
} /* loop forever */
/* please make sure that you never leave main */

}

0 Kudos
1 Reply

258 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

I have just run your code, disabled the RTI interrupt because you don't have the routine in the code and it works. 

Both the variable tFirstEdge and tSecondEdge get updated.

Do you have any update? Have you solved it already?

Regards,

Daniel

0 Kudos