Etimer Pulse Capture

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

Etimer Pulse Capture

2,035 Views
ronliu
Contributor IV

Hi,

I'm working in the MPC5775K.  I'd like to use the ETIMER module to capture the frequency of a 2.5MHz signal. I want to get the number of the signal in 1ms. How could I make it? Thanks.

Best Regard.

Ron

Labels (1)
Tags (2)
0 Kudos
12 Replies

1,411 Views
PetrS
NXP TechSupport
NXP TechSupport

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

0 Kudos

1,411 Views
ronliu
Contributor IV

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
}

0 Kudos

1,411 Views
PetrS
NXP TechSupport
NXP TechSupport

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

0 Kudos

1,411 Views
ronliu
Contributor IV

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?

0 Kudos

1,411 Views
PetrS
NXP TechSupport
NXP TechSupport

see attached example I created and tested on the MPC5775K EVB. It works well.

BR, Petr

0 Kudos

1,410 Views
ronliu
Contributor IV

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

0 Kudos

1,411 Views
PetrS
NXP TechSupport
NXP TechSupport

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

0 Kudos

1,411 Views
ronliu
Contributor IV

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

0 Kudos

1,411 Views
PetrS
NXP TechSupport
NXP TechSupport

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

1,411 Views
ronliu
Contributor IV

Petr,

Thank you very much. It could work now.

BR,

Ron

0 Kudos

1,411 Views
ronliu
Contributor IV

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

0 Kudos

1,411 Views
ronliu
Contributor IV

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;
}

0 Kudos