Hi,
You can directly use the Capture feature of the eTimer module to measure the external signal frequency.
See https://community.freescale.com/docs/DOC-104285 for a possible implementation.
However for such high rates the accuracy is low.
Thus the option will be counting of external signal edges per defined interval, e.g. 1 ms and finaly calculate the frequency.
For this case 2 channels can be used. The first channel is set for Gated-count mode, so the counter will count while the selected secondary input signal is high (or low, if SIPS=1). External pin will be selected as primary count source.
Second eTimer channel will be used to generate the gate signal on its output for the first channel, and for example One-shot mode can be used, thus a measurement is SW triggered.
See Counting mode description of the RM for more info.
BR, Petr
Hi,
Thanks for your sharing code. I'm using the eTimer1 now.
So I adjust some module configuration.
But when I want to capture the pulse.
It's always running the line 'while(!(0x0080 & ETIMER_1.CH[1].STS.R)){}' .
What's wrong with my project? Could you give me some suggestions?
Thanks.
void FdivInit(void)
{
//FDIV PAD_4 GPIO[4] Etimer 1 timer channel 0
//SAT_RX PAD_45 GPIO[45] Etimer 1 timer channel 1
//GPIO
SIUL2.MSCR[4].B.IBE = 1; /* GPIO[4]: Enable pad for input - eTimer1 ch0 */
SIUL2.MSCR[4].B.PUE = 1;
SIUL2.IMCR[27].B.SSS = 1; /* eTimer1 ch0: connected to pad4 */
// SIUL2.MSCR[45].B.IBE = 1; /* GPIO[45]: Enable pad for input - eTimer1 ch1 */
// SIUL2.IMCR[28].B.SSS = 1; /* eTimer1 ch1: connected to pad */
//ETIME
ETIMER_1.ENBL.R = 0x0;
ETIMER_1.CH[0].CTRL1.R = 0x3801;
// Counts only rising edge of the MC_CLK (133MHz in RUN0), divide by 1, count up, count repeatedly, rollover
ETIMER_1.CH[0].COMP1.R = 0xFFFF;
ETIMER_1.CH[0].CCCTRL.R = 0x0264; // compare on COMP1 when counting up, COMP2 when counting down
// CAPT2 on falling edge, CAPT1 on rising edge, 2 entries
// free-running mode
ETIMER_1.CH[0].CTRL3.R = 1;
ETIMER_1.CH[1].CTRL1.R = 0xF001; // cascaded mode, count up, rollover, count repeatedly
ETIMER_1.CH[1].COMP1.R = 0xFFFF;
ETIMER_1.CH[1].CCCTRL.R = 0x0264; // compare on COMP1 when counting up, COMP2 when counting down
// CAPT2 on falling edge, CAPT1 on rising edge, 2 entries
// free-running mode
ETIMER_1.CH[1].CTRL3.R = 1;
ETIMER_1.ENBL.R = 0x0003; //Channel 0 and 1
// ETIMER_1.CH[0].CCCTRL.B.ARM = 1; // starts the input capture process
// ETIMER_1.CH[1].CCCTRL.B.ARM = 1;
}
void PulseFreqCal(void)
{
float freq;
uint32_t counts, edge1,edge2,edge3,edge4 ;
uint32_t capture_ch0[8],capture_ch1[8];
ETIMER_1.CH[0].CCCTRL.B.ARM = 1; // starts the input capture process
ETIMER_1.CH[1].CCCTRL.B.ARM = 1;
while(!(0x0080 & ETIMER_1.CH[1].STS.R)){} // wait for channel 1's capture2 flag
while(!(0x0080 & ETIMER_1.CH[0].STS.R)){}
capture_ch1[0] = ETIMER_1.CH[1].CAPT1.R;
capture_ch1[1] = ETIMER_1.CH[1].CAPT2.R;
capture_ch1[2] = ETIMER_1.CH[1].CAPT1.R;
capture_ch1[3] = ETIMER_1.CH[1].CAPT2.R;
capture_ch0[0] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[1] = ETIMER_1.CH[0].CAPT2.R;
capture_ch0[2] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[3] = ETIMER_1.CH[0].CAPT2.R;
capture_ch1[4] = ETIMER_1.CH[1].CAPT1.R;
capture_ch1[5] = ETIMER_1.CH[1].CAPT2.R;
capture_ch1[6] = ETIMER_1.CH[1].CAPT1.R;
capture_ch1[7] = ETIMER_1.CH[1].CAPT2.R;
capture_ch0[4] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[5] = ETIMER_1.CH[0].CAPT2.R;
capture_ch0[6] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[7] = ETIMER_1.CH[0].CAPT2.R;
edge1 = capture_ch1[0]*65536 + capture_ch0[0]; // save 1st rising edge
edge2 = capture_ch1[1]*65536 + capture_ch0[1]; // save 1st falling edge
edge3 = capture_ch1[2]*65536 + capture_ch0[2]; // save 2nd rising edge
edge4 = capture_ch1[3]*65536 + capture_ch0[3]; // save 2nd falling edge
// calculate period, pulseH, pulseL, freq and duty
if(edge3 > edge1)
{
counts = edge3 - edge1;
}
else
{
counts = (0xFFFFFFFF - edge1 + 1) + edge3;
}
// freq = (float)100000000.0/counts;
ETIMER_1.CH[1].STS.R = 0x00C0; // clear eTimer0 channel 1's capture1/2 flags
ETIMER_1.CH[0].STS.R = 0x00C0; // clear eTimer0 channel 0's capture1/2 flags
}
If the signal is connected to channel 0, then this channel’s input pin should be selected as secondary clock source for both ch0 and ch1.
Try to use
ETIMER_1.CH[0].CTRL1.R = 0x3800;
ETIMER_1.CH[1].CTRL1.R = 0xF000;
Petr
Hi,
Thanks. I correct this line. But the value of CAPT1 is always 0. Actually I'd like to use only the etimer channel 0 to capture the frequency of the signal. It counts the rising edge.
How should I configure it?
Hi Petr,
My project is working now . But there is a new problem that the frequency of signal is too high. I couldn't get the exact frequency of the signal by capturing double rising edges. So I'd like to capture a thousand times of rising edges and count the total time. How could I make it work.
Regards,
Ron
Yes, that is a drawback of this method I pointed to in the first reply. For the high input rates the accuracy will be low.
I also outlined option for counting external edges over defined time. See the first reply.
BR, Petr
Following your instructions, I have tried some methods to configure the registers. It's really a difficult problem for me to make it work now. Could you help me, please?
Best Regards
Ron
uint32_t counts;
float freq,
void eTimer_Init(void)
{
ETIMER_1.ENBL.R = 0x0; // disable Timer1 channels
ETIMER_1.CH[0].CTRL1.R = 0x6011; // Counts only rising edge of ch0 input while secondary (ch1 output) is high,
// count up, count repeatedly, rollover
ETIMER_1.CH[1].CTRL1.R = 0x1FC0; // counts rising edge of MCclock/128, count till compare then stop and reinit
ETIMER_1.CH[1].CTRL2.R = 0x8009; // output enable, assert while counter is active, clear if stopped
ETIMER_1.CH[1].COMP1.R = 16625; // generate 16ms pulse on output, assuming MCclock=133MHz
ETIMER_1.CH[1].CCCTRL.R = 0x0200; // compare with COMP1 if counting up, with COMP2 if counting down
ETIMER_1.ENBL.R = 0x0003; // Enable Timer1 channel 0/1
}
void main (void)
{
....
eTimer_Init();
while(1)
{
ETIMER_1.CH[1].CTRL1.B.CNTMODE = 1; // start measurement
while(!(0x0002 & ETIMER_1.CH[1].STS.R)){}; // wait for channel compare flag
counts = ETIMER_1.CH[0].CNTR.R;
ETIMER_1.CH[0].CNTR.R = 0;
ETIMER_1.CH[1].STS.R = 2;
freq = counts/0.016;
}
}
Frequency resolution is given by measuring window, ▲fx = 1/Tn, here ▲fx= 1/.016 = 62.5Hz
Petr
Petr,
Thank you very much. It could work now.
BR,
Ron
Hi Petr,
You're right. The accuracy is low. I review your reply again. But I'm not clear how to use these two channels to capture this signal. Could you please write a very simple project to function well for me?
Thanks a lot
Regards,
Ron
Hi Petr,
I'm using Etimer1 Channel 0 to capture the pulse on the MPC5775K. The GPIO is PAD_4. And I only want to count the rising edge. I don't understand the CAPT 4-deep FIFO.The below part is my test code. I adjust some lines to adapt my own hardware platform. But it couldn't work. The value of CAPT is always 0. Could you correct it for me? GPIO? Etimer? Thanks.
void EtimerCapture(void)
{
//FDIV PAD_4 GPIO[4] Etimer 1 timer channel 0
//GPIO
SIUL2.MSCR[4].B.IBE = 1; /* GPIO[4]: Enable pad for input - eTimer1 ch0 */
SIUL2.IMCR[27].B.SSS = 1; /* eTimer1 ch0: connected to pad4 */
//ETIMER
ETIMER_1.ENBL.R = 0x0;
ETIMER_1.CH[0].CTRL1.R = 0x3800; // Counts only rising edge of the MC_CLK (133MHz in RUN0), divide by 1, count up, count repeatedly, rollover
ETIMER_1.CH[0].COMP1.R = 0xFFFF;
ETIMER_1.CH[0].CCCTRL.R = 0x0264; // compare on COMP1 when counting up, COMP2 when counting down
// CAPT2 on falling edge, CAPT1 on rising edge, 2 entries
// free-running mode
ETIMER_1.CH[0].CTRL3.R = 1;
ETIMER_1.ENBL.R = 0x0001; //Channel 0
ETIMER_1.CH[0].CCCTRL.B.ARM = 1;
while(!(0x0080 & ETIMER_1.CH[0].STS.R)){}
short capture_ch0[4],capture_ch1[4];
capture_ch0[0] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[1] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[2] = ETIMER_1.CH[0].CAPT1.R;
capture_ch0[3] = ETIMER_1.CH[0].CAPT1.R;
capture_ch1[0] = ETIMER_1.CH[0].CAPT2.R;
capture_ch1[1] = ETIMER_1.CH[0].CAPT2.R;
capture_ch1[2] = ETIMER_1.CH[0].CAPT2.R;
capture_ch1[3] = ETIMER_1.CH[0].CAPT2.R;
ETIMER_1.CH[0].STS.R = 0x00C0;
}