Hi,
You may refer to the document below.
S12ZVL-TIM-FrequencyMeasurement-V1_0-CW106-TIC-EXAMPLE
Regards,
Daniel
Hello Daniel. Firstly, thank you very much for your replay.
I tried to import the code to my project. But I couldnt make it work. I cant see an interrupt on TIM0_Channel0_ISR().
Can you pleae have a look on my code? I tested the code on TRK-S12ZVH128 board.
My main file is as follows.
/******************************************************************************
* S12ZVH128 Cluster Reference Design *
* *
* Created on: 05/03/2012 *
* Author: B34981 *
* Version: 0.2 *
* *
* This Reference Design resembles a Low-End cluster with the following *
* features: *
* - 160 Segment LCD *
* - 4 Stepper motors with Return-to-Zero detection *
* - Real Time Counter on LCD *
* - Dynamic backlighting (dimmable from Analog Input) *
* - CAN Communications *
* - Simple Sound Generation *
* *
******************************************************************************/
#include "derivative.h" /* include peripheral declarations */
int kk = 0, ii = 0;
#define BUSCLOCK 4000000UL // Hz
#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
//----- 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
#define SET_INTERRUPT_PRIORITY(vec_off, priority) \
INT_CFADDR= (vec_off/4) & 0xF8; \
INT_CFDATA_ARR[(vec_off/4) & 0x03]= (priority);
#define TIM0_Channel0_VEC_OFF 0x1CC
#define TIM0_Overflow_VEC_OFF 0x1AC
//interrupt void TIM0_Channel0_ISR(void); // 0x1CC
/*******************************************************************************
* 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;
/*******************************************************************************
* Local function prototypes
******************************************************************************/
static void CPMU_Init( void );
static void Delay( ULONG delay );
static void TIM0_Init( void ); // timer module initialization
static void SendValue( void );
void SCI0_Init(void);
void SCI0_Send_String(SBYTE *ptr);
/*******************************************************************************
* Local variables
******************************************************************************/
static ULONG period; // calcualted period between two rising edges
static UWORD ch0ovfCnt; // the number of main timer overflows between
// 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 = STOP_MEASUREMENT;
volatile FLAGS Flags; // general purpose flags
interrupt VectorNumber_Vtim0ch0 void TIM0_Channel0_ISR( void )
{
unsigned int ttt, tof;
PTP_PTP0 = 1;
PTP_PTP0 = 0;
tof = TIM0TFLG2_TOF; // check whether additional TOF appeared
ttt = TIM0TC0; // 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 = 0B10000000; // clear ovf interrupt flag
TIM0TFLG2 = 0B10000000; // 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 = 0B00000001; // clear interrupt flag from PT0
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_C0I = 0; // disable Ch0 interrupt
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
}
// 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
}
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_C0I = 0; // disable Ch0 interrupt
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
NEW_VALUE_PREPARED = TRUE; // information for main routine
}
else
{
FREQUENCY_TOO_LOW = FALSE;
}
TIM0TFLG2 = 0B10000000; // clear ovf interrupt flag
}
static void TIM0_Init( void )
{
PERT_PERT0 = 1; // an internal pull resitor enable
PPST_PPST0 = 0; // an internal pull up connected
TIM0TSCR2 = PRESCALER; // tim disabled; prsc=1
TIM0TCTL4 = 0B00000001; // channel 0 inp. capture on rising edge
TIM0TSCR2_TOI = 0; // stop ovf interrupt counter
TIM0TIE_C0I = 0; // disable Ch0 interrupt
TIM0TSCR1 = 0B01100000; // enable timer, stop in freeze mode
// stop in wait mode
}
static void SendValue( void )
{
if( FREQUENCY_TOO_LOW ) // Have overflows counter reached maximum value?
{
ODO_Mode(000); // print zero to LCD if period is too low
}
else
{
// calculate time between two edges
//f = period / BUSCLOCK;
ODO_Mode(period);
}
//----------------------------
//----------------------------
NEW_VALUE_PREPARED = FALSE; // clear flag = value has been sent
}
void main(void) {
EnableInterrupts;
CPMUCOP_CR = 0x0; /* Disable COP */
PLL_Init(); /* Initialise the PLL to increase operating frequency */
GPIO_Init(); /* Configures inputs, outputs, pull-ups and KBI interrupts*/
LCD_Init(); /* Configures the LCD controller for 4x40 operation */
TIM1_Init(); /* Configures one TIM periodic interrupt for stepper control */
//Scheduler_Init(); /* Execute the Scheduler... never returns */
//=== GPIO INIT ================ for input capture
DDRT_DDRT0 = 0; // PT0 input port
PERT_PERT0 = 1; // Pull resistor enabled at PT0
PPST_PPST0 = 1; // Pull down selected at PT0
//=== TIM0 INIT ================
FREQUENCY_TOO_LOW = TRUE; // set flag
NEW_VALUE_PREPARED = FALSE; // set flag
SET_INTERRUPT_PRIORITY(TIM0_Channel0_VEC_OFF, 7); // max priority
SET_INTERRUPT_PRIORITY(TIM0_Overflow_VEC_OFF, 6); // less priority than IC0
TIM0_Init(); // timer and channels initialization
//=== ENABLE INTERRUPTS ========
TIM0TSCR2_TOI = 1; // start ovf interrupt counter
TIM0TIE_C0I = 1; // enable Ch0 interrupt
EnableInterrupts;
for( ;; )
{
// start measurement
FREQUENCY_TOO_LOW = FALSE; // clear flag
NEW_VALUE_PREPARED = FALSE; // set flag
ch0ovfCnt = 0; // clear number of ovfs interrupts
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
TIM0TFLG2 = 0B10000000; // clear interrupt TOV flag
mPhase = FIRST_EDGE; // prepare processing of a first edge
TIM0TSCR1_TEN = 1; // run timer
TIM0TIE_C0I = 1; // enable Ch0 interrupt
TIM0TSCR2_TOI = 1; // enable ovf interrupt
while( !NEW_VALUE_PREPARED ) // wait for measurement
{
}
SendValue(); // send measured value
asm nop; // only for debug purposes for brkpnt
}
}
Hi,
The code is not complete, PLL_Init and GPIO_Init functions are called but not defined.
You want to use PT0 as input (Timer1, ch0) so you call TIM1_Init() but only TIM0_Init() is defined.
Also, you have interrupt routines only for Timer 0, not for Timer1.
Regards,
Daniel
Hi again,
PLL_Init and GPIO_Init were defined in another c file. I moved them to main.c. Also added timer1.
Can you please have a look on this revised file. Thank you very much.
/******************************************************************************
* S12ZVH128 Cluster Reference Design *
* *
* Created on: 05/03/2012 *
* Author: B34981 *
* Version: 0.2 *
* *
* This Reference Design resembles a Low-End cluster with the following *
* features: *
* - 160 Segment LCD *
* - 4 Stepper motors with Return-to-Zero detection *
* - Real Time Counter on LCD *
* - Dynamic backlighting (dimmable from Analog Input) *
* - CAN Communications *
* - Simple Sound Generation *
* *
******************************************************************************/
#include "derivative.h" /* include peripheral declarations */
int kk = 0, ii = 0;
UINT16 u16_testPer = 1200;
#define BUSCLOCK 16000000UL // Hz
#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
//----- 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
#define SET_INTERRUPT_PRIORITY(vec_off, priority) \
INT_CFADDR= (vec_off/4) & 0xF8; \
INT_CFDATA_ARR[(vec_off/4) & 0x03]= (priority);
#define TIM0_Channel0_VEC_OFF 0x1CC
#define TIM0_Overflow_VEC_OFF 0x1AC
//interrupt void TIM0_Channel0_ISR(void); // 0x1CC
/*******************************************************************************
* 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;
/*******************************************************************************
* Local function prototypes
******************************************************************************/
static void CPMU_Init( void );
static void Delay( ULONG delay );
static void TIM0_Init( void ); // timer module initialization
static void SendValue( void );
void SCI0_Init(void);
void SCI0_Send_String(SBYTE *ptr);
/*******************************************************************************
* Local variables
******************************************************************************/
static ULONG period; // calcualted period between two rising edges
static UWORD ch0ovfCnt; // the number of main timer overflows between
// 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 = STOP_MEASUREMENT;
volatile FLAGS Flags; // general purpose flags
interrupt VectorNumber_Vtim0ch0 void TIM0_Channel0_ISR( void )
{
unsigned int ttt, tof;
PTP_PTP0 = 1;
PTP_PTP0 = 0;
tof = TIM0TFLG2_TOF; // check whether additional TOF appeared
ttt = TIM0TC0; // 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 = 0B10000000; // clear ovf interrupt flag
TIM0TFLG2 = 0B10000000; // 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 = 0B00000001; // clear interrupt flag from PT0
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_C0I = 0; // disable Ch0 interrupt
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
}
// 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
}
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_C0I = 0; // disable Ch0 interrupt
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
NEW_VALUE_PREPARED = TRUE; // information for main routine
}
else
{
FREQUENCY_TOO_LOW = FALSE;
}
TIM0TFLG2 = 0B10000000; // clear ovf interrupt flag
}
static void TIM0_Init( void )
{
PERT_PERT0 = 1; // an internal pull resitor enable
PPST_PPST0 = 0; // an internal pull up connected
TIM0TSCR2 = PRESCALER; // tim disabled; prsc=1
TIM0TCTL4 = 0B00000001; // channel 0 inp. capture on rising edge
TIM0TSCR2_TOI = 0; // stop ovf interrupt counter
TIM0TIE_C0I = 0; // disable Ch0 interrupt
TIM0TSCR1 = 0B01100000; // enable timer, stop in freeze mode
// stop in wait mode
}
static void SendValue( void )
{
if( FREQUENCY_TOO_LOW ) // Have overflows counter reached maximum value?
{
ODO_Mode(000); // print zero to LCD if period is too low
}
else
{
// calculate time between two edges
//f = period / BUSCLOCK;
ODO_Mode(period);
}
//----------------------------
//----------------------------
NEW_VALUE_PREPARED = FALSE; // clear flag = value has been sent
}
/*******************************************************************************
* @brief PLL_Init - Clock configurations (32 MHz from 8 MHz OSC)
* @param none
* @return none
********************************************************************************/
void PLL_Init(void)
{
//WD Disable...
CPMUCLKS_PLLSEL = 0x1; // FBUS = FPLL/2. FBUS = 32MHz,
CPMUREFDIV_REFDIV = 0x1; // FREF = FOSC/(REFDIV+1) = 8/(1+1) = 4MHZ
CPMUREFDIV_REFFRQ = 0x1; // Reference clock between 2MHZ and 6MHZ.
CPMUSYNR_SYNDIV = 0x7; // FVCO = 2xFREFx(SYNDIV+1) = FVCO = 2x4x(7+1) = 64MHZ
CPMUSYNR_VCOFRQ = 0x1; // FVCO is between 48MHZ and 80MHZ
CPMUPOSTDIV_POSTDIV = 0x0; // FPLL = FVCO/(POSTDIV+1). FPLL = 64MHZ/(0+1) FPLL = 64MHz
CPMUOSC_OSCE = 0x1; // 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
}
void TIM1_Init(){
TIM1TIOS_IOS1 = 1; // TIMCH0 as output compare
TIM1TIE_C1I = 1; // TIMCH0 interrupt enable
TIM1TFLG1_C1F = 1; // Clear interrupt flag
TIM1TC1 = u16_testPer; // Interrupt period
TIM1TSCR2_PR = 0; // Clock Prescaler FBUS/2^PR
TIM1TSCR1_PRNT = 1; // Precision Timer enable
TIM1TSCR1_TEN = 1; // TIM enable
}
void main(void) {
//EnableInterrupts;
CPMUCOP_CR = 0x0; /* Disable COP */
PLL_Init(); /* Initialise the PLL to increase operating frequency */
LCD_Init(); /* Configures the LCD controller for 4x40 operation */
TIM1_Init(); /* Configures one TIM periodic interrupt for stepper control */
//Scheduler_Init(); /* Execute the Scheduler... never returns */
//=== GPIO INIT ================ for input capture
DDRT_DDRT0 = 0; // PT0 input port
PERT_PERT0 = 1; // Pull resistor enabled at PT0
PPST_PPST0 = 1; // Pull down selected at PT0
//=== TIM0 INIT ================
FREQUENCY_TOO_LOW = TRUE; // set flag
NEW_VALUE_PREPARED = FALSE; // set flag
SET_INTERRUPT_PRIORITY(TIM0_Channel0_VEC_OFF, 7); // max priority
SET_INTERRUPT_PRIORITY(TIM0_Overflow_VEC_OFF, 6); // less priority than IC0
TIM0_Init(); // timer and channels initialization
//=== ENABLE INTERRUPTS ========
TIM0TSCR2_TOI = 1; // start ovf interrupt counter
TIM0TIE_C0I = 1; // enable Ch0 interrupt
EnableInterrupts;
for( ;; )
{
// start measurement
FREQUENCY_TOO_LOW = FALSE; // clear flag
NEW_VALUE_PREPARED = FALSE; // set flag
ch0ovfCnt = 0; // clear number of ovfs interrupts
TIM0TFLG1 = 0B00000001; // clear interrupt flag from PT0
TIM0TFLG2 = 0B10000000; // clear interrupt TOV flag
mPhase = FIRST_EDGE; // prepare processing of a first edge
TIM0TSCR1_TEN = 1; // run timer
TIM0TIE_C0I = 1; // enable Ch0 interrupt
TIM0TSCR2_TOI = 1; // enable ovf interrupt
while( !NEW_VALUE_PREPARED ) // wait for measurement
{
}
SendValue(); // send measured value
asm nop; // only for debug purposes for brkpnt
}
}
Hi,
IOC0_0 is a function of PT0 on S12ZVL but PU0 on S12ZVH.
Do you measure the signal at PU0?
Regards,
Daniel
Thank you very much Daniel, that was my problem. I configured IOC1_0 and measure the signal at PT0. Thanks.