I am using Input capture mode of MC9S12XHZ512 for calculating frequency and duty cycle of square wave from 1KHz to 10KHz , I have attached image of setting i have done in codewarrior.
My problem is that when I try to display frequency on my LCD display I am getting random charter on , I also have problem with interrupt input capture mode I have enable input capture mode in codewarrior , but i'm not able to find it in program , I want to write my display and calculation code in interrupt sub routine of input capture mode. I have posted my code below.
I'm using 16MHz crystal
LCD_Cmd(0x80);
// TM=65535*(TC0/16000000);
// TM=1/TM;
t[i]=TC0;
i++;
if(i==2) {
i=0;
time_interval=(t[1]-t[0]);
time_interval=(float)(0.0000000625*time_interval);
frequency= 1/time_interval;
sprintf(buffer,"%d",frequency);
for(j=0;j<5;j++)
{
LCD_Data(buffer[j]);
}
}
Hi,
i am not a fan of the PE SW solutions.
i would like t show you how to measure frequency with own setup. I think you you understand how to set the PE then you are also able to set the registers yourself and you have everything under your control.
//------------------------------------------------------------------------------
// Frequency Measurement
//------------------------------------------------------------------------------
#include <hidef.h> /* common defines and macros */
#include <mc9s12xa512.h> /* derivative information */
#include <stdio.h> /* include string functions */
#pragma LINK_INFO DERIVATIVE "mc9s12xa512"
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Local types definitions
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define UBYTE unsigned char
#define SBYTE char
#define UWORD unsigned int
#define UDWORD unsigned long int
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// PROGRAM DEFINITION
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define BUSCLOCK 20000000UL // Hz
#define TIMER_PRESCALER 2 // 1,2,4,8,16,32,64,128 - smaller values give more precise values but
// it generates timer overflow more frequently
#define MAX_OVERFLOWS 1000L // maximum allowed number of overflows
// when overflows counter reaches this value it sends message
// PERIOD BETWEEN TWO EDGES IS TO WIDE over the SCI
// this value gives time interval:
// T = TIMER_PRESCALER * MAX_OVERFLOWS / BUSCLOCK
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// 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 functions definitions
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
static void Tim0_Init(void);
void SCI0_Setup(void); // set SCI0 communications parameters
void sendValue(void); // send value over the SCI0
void PLL_Init(UBYTE synr, UBYTE refdv);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// GLOBAL VARIABLES
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
static UDWORD udwPeriod; // calcualted period - depends on BUSCLK and timer setup =
// = number of bus periods between two pulses
static UWORD uwCh2ovfCnt; // the number of main timer overflows between two pulses on Ch2
static UWORD uwTimerOldValue=0;
static UWORD uwTimerNewValue=0;
SBYTE str[200];
//----------------------------
typedef union uFlags
{ 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;
}tFlags;
static volatile tFlags Flags; // general purpose flags
#define WHEEL1_OVF_CNT_STOPS_FLAG Flags.bit.f0
#define NEW_VALUE_PREPARED Flags.bit.f1
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// MAIN
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void main(void)
{
UWORD j,k;
PLL_Init(4,3); // 20MHz BUSCLK from 16MHz OSCCLK
Tim0_Init(); // timer and channels initialization
SCI0_Setup(); // SCI communication parameters setup
asm CLI; // enable all interrupts
// variables initialization
DDRB =0xFF;
WHEEL1_OVF_CNT_STOPS_FLAG = TRUE; // set flag
for(;;) // main program loop
{
if(NEW_VALUE_PREPARED) sendValue(); // send measured value over SCI
}
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Module: void PLL_Init(UBYTE synr, UBYTE refdv)
// Description: The function initalizes PLL
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void PLL_Init(UBYTE synr, UBYTE refdv)
{
CLKSEL &= 0x7F;
REFDV = refdv;
SYNR = synr;
while(!(CRGFLG_LOCK));
CLKSEL_PLLSEL = 1;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Send Measured Value
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void sendValue(void)
{
static float f;
UBYTE i;
if(WHEEL1_OVF_CNT_STOPS_FLAG) // Have overflows counter reached maximum value?
{
sprintf(str,"%s","PERIOD BETWEEN TWO RISING EDGES IS TO WIDE\n\r");
}
else
{
// calculate time between two edges
f = (((float)TIMER_PRESCALER)*((float)udwPeriod))/((float)BUSCLOCK);
// prepare text to be sent
sprintf(str,"f = %-10.3f [Hz]; T = %-10.6f [s]; count value = %-10.0f\n\r",1/f,f,(float)udwPeriod);
}
i=0;
while(str[i]!='\0') // send message
{
while(!SCI0SR1_TC); // wait while TC=0 - transmition in progress
SCI0DRL=str[i];
i++;
}
NEW_VALUE_PREPARED =FALSE; // clear flag = value has been sent
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Module: void Tim0_Init(void)
// Description: The function sets timer and channels
// Channel2 - input capture on both edges in queue mode
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
static void Tim0_Init(void)
{
TSCR2 = TSCR2_TOI_MASK | PRESCALER; // timer ovf. int. enable; prescaller= given by definition
uwTimerOldValue = 0; // set initial value
TCTL4 = 0x10; // channel 2 input capture on rising edge
ICSYS = ICSYS_BUFEN_MASK; // input capt. and hold. registers enabled, interrupt on capture
ICOVW = ICOVW_NOVW2_MASK; // related capture register can be overwritten after every new capture
TIE = TIE_C2I_MASK; // enable Ch2 interrupt
TSCR1 = 0xE0; // enable timer, stop during freeze and wait
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Module: void Tim0ch0_ISR(void)
// Description: The function serves capture channel 0 interrupt
// Channel1 - input capture on both edges in queue mode
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#pragma CODE_SEG NON_BANKED
interrupt 10 void Tim0ch2_ISR(void)
{
unsigned int ovfs;
uwTimerNewValue = TC2; // read new captured value and clear flag
ovfs = uwCh2ovfCnt; // save number of overflows to temporary variable
uwCh2ovfCnt = 0; // clear number of overflows
TFLG1 = TIE_C2I_MASK; // clear interrupt flag
PORTB=~PORTB; // show (PT0) incomming signal on port B
//----- Ch2 period calculation ---------
if(!ovfs) // Did edges appear within one timer period?
{
udwPeriod = (UDWORD)(uwTimerNewValue - uwTimerOldValue);
}
else // some number of overflows has appeared between two edges
{
udwPeriod = (UDWORD)( ~uwTimerOldValue+1 ); // time in the first period
udwPeriod+= (UDWORD)( uwTimerNewValue); // time in the last period
udwPeriod+= (UDWORD)((UDWORD)((ovfs-1)) * (UDWORD)(65536)); // time given by overflows
}
uwTimerOldValue = uwTimerNewValue; // prepare new old value
NEW_VALUE_PREPARED = TRUE; // information for main routine
WHEEL1_OVF_CNT_STOPS_FLAG = FALSE; // clear flag
}
#pragma CODE_SEG DEFAULT
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Module: void Tim0ovf_ISR(void)
// Description: Main timer overflov service routine
// The number of overflows of channel 2 capture is accumulated here
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#pragma CODE_SEG NON_BANKED
interrupt 16 void Tim0ovf_ISR(void)
{
uwCh2ovfCnt++; // count overflows
if(uwCh2ovfCnt>MAX_OVERFLOWS)
{
uwCh2ovfCnt = 0;
WHEEL1_OVF_CNT_STOPS_FLAG = TRUE;
sendValue(); // send message to the PC each overflow of the timer overflows_counter
}
else
{ WHEEL1_OVF_CNT_STOPS_FLAG = FALSE;
}
TFLG2_TOF = 1; // clear interrupt flag of main timer
}
#pragma CODE_SEG DEFAULT
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#pragma CODE_SEG DEFAULT
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Module: void SCI0_Setup(void)
// Description: 8 data bits + 1 stop bit with speed 9600 bps.
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void SCI0_Setup(void) //SCI0 is used fo PC Master communication
{
/*---------------------------------------------------------------------------*/
/* define serial protocol for SCI0: */
/* 8 data + 1 stop bit; 9600 Bd; enable Rx interrupt, disable Tx interrupt */
/*------------------------------------------------------*/
/* set serial communication baud rate (9600 Bd) */
/*------------------------------------------------------*/
/*SCI baud rate= SCI Module Clock / (16 * SBR) // IREN=0*/
/*SCI baud rate= SCI Module Clock / (32 * SBR) // IREN=1*/
SCI0BDH = 0x00; /* prescaller value (depends on module clock frequency) */
SCI0BDL = 0x82; /* prescaller = 0x82 (BUS=20MHz) */
/*------------------------------------------------------*/
/* set serial protocol (1+8+1) */
/*------------------------------------------------------*/
SCI0CR1 = 0x44; /* loops sciswai rsrc m wake ilt pe pt */
/* 0-loops disabled */
/* 1-SCI dis. in wait mode */
/* 0-RxTx intern. connected if loops=1 */
/* 0-1 start+8 data+1 stop bit */
/* 0-IDLE mark wake up */
/* 1-idle char. bit count begins after stop bit */
/* 0-parity fction disabled */
/* 0 - odd parity */
/*------------------------------------------------------*/
/* enable transmitter, receiver and Rx full interrupt */
/*------------------------------------------------------*/
SCI0CR2 = 0x2C; /* tie tcie rie ilie te re rwu sbk */
/* 0-Tx empty intr disabled */
/* 0-Tx complete intr disabled */
/* 1-Rx full intr enabled */
/* 0-idle line intr disabled */
/* 1-transmitter enabled */
/* 1-receiver enabled */
/* 0-normal operation */
/* 0-no break characters */
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@