I,m using S12ZVC64 for capture square wave's frequency and duty。 The input frequency is between 10Hz and 3000Hz。but 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 */
}