Hi,NXP
look the file ,6 Measure signal parameters:
void eTimer_Init(uint8_t EtimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.R = 0x0; // disable Timer0 channels
/* Configure the channel */
// pETIMERn->CH[DspiNumber].CTRL1.R = 0x38C1;//0x2001;//0x3801; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x18;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT1MODE = 2;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT2MODE = 1;
pETIMERn->CH[DspiNumber].CTRL1.B.LENGTH = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.ONCE = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 1;
pETIMERn->CH[DspiNumber].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber].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
/*
pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
pETIMERn->CH[DspiNumber].CCCTRL.B.CFWM = 2;
pETIMERn->CH[DspiNumber].CTRL3.R = 1;
pETIMERn->CH[DspiNumber].CTRL3.B.ROC = 3;
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber); // Enable Timer0 channel 1
pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1; // starts the input capture process
//pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
*/
}
void eTimer_EnableChannal(uint8_t eTimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(eTimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber); // Enable Timer0 channel 1
}
void eTimer_Value(uint8_t EtimerN,uint8_t DspiNumber)
{
uint32_t counts;
uint32_t capture_ch[4];
uint8_t eTimerSTS = 0;
float freq,period,duty,pulseH,pulseL;
volatile struct ETIMER_tag *pETIMERn;
eTimer_Channal.duty = 0;
eTimer_Channal.Freq = 0;
eTimer_Channal.Period = 0;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1;
while((pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0))
{ //(pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0)
// Delayms(100);
// if(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R)) eTimerSTS = 1;
}
pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 0; // stop the input capture process
pETIMERn->CH[DspiNumber].STS.B.ICF1 = 0x1;
pETIMERn->CH[DspiNumber].STS.B.ICF2 = 0x1;
capture_ch[0] = pETIMERn->CH[DspiNumber].CAPT1.R; //First rising edge
capture_ch[1] = pETIMERn->CH[DspiNumber].CAPT2.R; //First falling edge
capture_ch[2] = pETIMERn->CH[DspiNumber].CAPT1.R; //Second rising edge
capture_ch[3] = pETIMERn->CH[DspiNumber].CAPT2.R; //Second falling edge
counts = capture_ch[2] - capture_ch[0];
eTimer_Channal.Freq = (float)(100000000.0/counts);
eTimer_Channal.Period = (counts / (float)100000.0)*1000000;
counts = capture_ch[1] - capture_ch[0];
pulseH = (counts /100000.0)*1000000;
// eTimer_Channal.duty = pulseH/period*100;
eTimer_Channal.duty = ((uint16_t)((capture_ch[1] - capture_ch[0])*1000)/(uint16_t)(capture_ch[2] - capture_ch[0]));
PWM:25Hz
why I get the duty fail
clipping
Hi,Pert
Thank you very much!
In the Example-MPC5744P-eTimer-frequency_measurement-v1_0-GHS614,
channal 0 input,why I need konw" while(!(0x0080 & ETIMER_0.CH[1].STS.R))"
while(!(0x0080 & ETIMER_0.CH[1].STS.R)){} // wait for channel 1's capture2 flag
while(!(0x0080 & ETIMER_0.CH[0].STS.R)){}
Hi,Petr
void eTimer_Init(uint8_t EtimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.R = 0x0; // disable Timer0 channels
/* Configure the channel */
// pETIMERn->CH[DspiNumber].CTRL1.R = 0x3804; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 1;
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x1F;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber].CCCTRL.R = 0x0264;
pETIMERn->CH[DspiNumber].CTRL3.R = 1;
// pETIMERn->CH[DspiNumber+1].CTRL1.R = 0xF004; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 3;
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x10+DspiNumber;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber+1].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber+1].CCCTRL.R = 0x0264;
pETIMERn->CH[DspiNumber+1].CTRL3.R = 1;
/*
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x1F;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT1MODE = 2;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT2MODE = 1;
pETIMERn->CH[DspiNumber].CCCTRL.B.CFWM = 2;
pETIMERn->CH[DspiNumber].CTRL1.B.LENGTH = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.ONCE = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 1;*/
// pETIMERn->CH[DspiNumber].COMP1.R = 0xFFFF;
// pETIMERn->CH[DspiNumber].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
// pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
// pETIMERn->CH[DspiNumber].CTRL3.R = 1;
// pETIMERn->CH[DspiNumber].CTRL3.B.ROC = 3;
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber)||(1<<(DspiNumber+1)); // Enable Timer0 channel 1
// pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1; // starts the input capture process
//pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
}
void eTimer_EnableChannal(uint8_t eTimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(eTimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber); // Enable Timer0 channel 1
}
void eTimer_Value(uint8_t EtimerN,uint8_t DspiNumber)
{
double counts[2];
uint32_t capture_ch[4],capture_ch1[4],edge[5];
uint8_t eTimerSTS = 0;
double freq,period,duty,pulseH,pulseL;
volatile struct ETIMER_tag *pETIMERn;
eTimer_Channal.duty = 0;
eTimer_Channal.Freq = 0;
eTimer_Channal.Period = 0;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1;
pETIMERn->CH[DspiNumber+1].CCCTRL.B.ARM = 1;
while(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R))
{ //(pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0)
// Delayms(100);
// if(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R)) eTimerSTS = 1;
}
while(!(0x0080 & pETIMERn->CH[DspiNumber+1].STS.R))
{ //(pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0)
// Delayms(100);
// if(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R)) eTimerSTS = 1;
}
// pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 0; // stop the input capture process
// pETIMERn->CH[DspiNumber].STS.B.ICF1 = 0x1;
// pETIMERn->CH[DspiNumber].STS.B.ICF2 = 0x1;
capture_ch[0] = pETIMERn->CH[DspiNumber].CAPT1.R; //First rising edge
capture_ch[1] = pETIMERn->CH[DspiNumber].CAPT2.R; //First falling edge
capture_ch[2] = pETIMERn->CH[DspiNumber].CAPT1.R; //Second rising edge
capture_ch[3] = pETIMERn->CH[DspiNumber].CAPT2.R; //Second falling edge
capture_ch1[0] = pETIMERn->CH[DspiNumber+1].CAPT1.R; //First rising edge
capture_ch1[1] = pETIMERn->CH[DspiNumber+1].CAPT2.R; //First falling edge
capture_ch1[2] = pETIMERn->CH[DspiNumber+1].CAPT1.R; //Second rising edge
capture_ch1[3] = pETIMERn->CH[DspiNumber+1].CAPT2.R; //Second falling edge
edge[1] = capture_ch1[0]*65536 + capture_ch[0]; // save 1st rising edge
edge[2] = capture_ch1[1]*65536 + capture_ch[1]; // save 1st falling edge
edge[3] = capture_ch1[2]*65536 + capture_ch[2]; // save 2nd rising edge
edge[4] = capture_ch1[3]*65536 + capture_ch[3]; // save 2nd falling edge
if(edge[3]>edge[1])
{
counts[0] = edge[3] - edge[1];
}
else
{
counts[0] = (0xFFFFFFFF - edge[1] +1) + edge[3];
}
eTimer_Channal.Freq = (float)100000000.0/counts[0];
eTimer_Channal.Period = counts[0] / (float)100000.0;
if(edge[2]>edge[1])
{
counts[1] = edge[2] - edge[1];
}
else
{
counts[1] = (0xFFFFFFFF - edge[1] +1) + edge[2];
}
pulseH = counts[1] / (float)100000.0;
pulseL = eTimer_Channal.Period-pulseH;
eTimer_Channal.duty = counts[1]*100/counts[0];//pulseH/eTimer_Channal.Period *100;
pETIMERn->CH[DspiNumber].STS.R = 0x00C0; // clear eTimern channel n's capture1/2 flags
pETIMERn->CH[DspiNumber+1].STS.R = 0x00C0; // clear eTimern channel n's capture1/2 flags
}
I get duty fail.
eTimer1 ,channal4;
Clipping
you have wrong setting for cascaded channel, it should be
// pETIMERn->CH[DspiNumber+1].CTRL1.R = 0xF004; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber+1].CTRL1.B.CNTMODE = 7;
pETIMERn->CH[DspiNumber+1].CTRL1.B.PRISRC = 0x10+DspiNumber;
pETIMERn->CH[DspiNumber+1].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber+1].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber+1].CCCTRL.R = 0x0264;
pETIMERn->CH[DspiNumber+1].CTRL3.R = 1;
Also as you are using prescaler=128, you need to add this into relevant calculations.
BR, Petr
Hi,
If the channel is counting MC_CLK/1 (100MHz) and you measure 25Hz PWM signal, then expected counts per period will be 100e6 / 25 = 4 000 000 counts. The eTimer has just 16bit counter, thus for low frequency input signal you have to handle counter overflows or use slower internal counting clock (this way you will lose the precision).
Another possibility could be usage of cascaded counters, which serves overflow counting in HW.
The example using cascaded counters is here: https://community.nxp.com/docs/DOC-104285
BR, Petr
Hi, Petr
Thank You!
void eTimer_Init(uint8_t EtimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.R = 0x0; // disable Timer0 channels
/* Configure the channel */
// pETIMERn->CH[DspiNumber].CTRL1.R = 0x3804; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 1;
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x1F;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber].CCCTRL.R = 0x0264;
pETIMERn->CH[DspiNumber].CTRL3.R = 1;
// pETIMERn->CH[DspiNumber+1].CTRL1.R = 0xF004; // Counts only rising edge of the MC_CLK (100MHz in RUN0), divide by 1, count up, count repeatedly, rollover
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 3;
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x10+DspiNumber;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber+1].COMP1.R = 0xFFFF;
pETIMERn->CH[DspiNumber+1].CCCTRL.R = 0x0264;
pETIMERn->CH[DspiNumber+1].CTRL3.R = 1;
/*
pETIMERn->CH[DspiNumber].CTRL1.B.PRISRC = 0x1F;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT1MODE = 2;
pETIMERn->CH[DspiNumber].CCCTRL.B.CPT2MODE = 1;
pETIMERn->CH[DspiNumber].CCCTRL.B.CFWM = 2;
pETIMERn->CH[DspiNumber].CTRL1.B.LENGTH = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.ONCE = 0;
pETIMERn->CH[DspiNumber].CTRL1.B.SECSRC = DspiNumber;
pETIMERn->CH[DspiNumber].CTRL1.B.CNTMODE = 1;*/
// pETIMERn->CH[DspiNumber].COMP1.R = 0xFFFF;
// pETIMERn->CH[DspiNumber].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
// pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
// pETIMERn->CH[DspiNumber].CTRL3.R = 1;
// pETIMERn->CH[DspiNumber].CTRL3.B.ROC = 3;
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber)||(1<<(DspiNumber+1)); // Enable Timer0 channel 1
// pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1; // starts the input capture process
//pETIMERn->CH[DspiNumber].CCCTRL.B.ONESHOT = 1;
}
void eTimer_EnableChannal(uint8_t eTimerN,uint8_t DspiNumber)
{
volatile struct ETIMER_tag *pETIMERn;
switch(eTimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->ENBL.B.ENBL |= (1<<DspiNumber); // Enable Timer0 channel 1
}
void eTimer_Value(uint8_t EtimerN,uint8_t DspiNumber)
{
double counts[2];
uint32_t capture_ch[4],capture_ch1[4],edge[5];
uint8_t eTimerSTS = 0;
double freq,period,duty,pulseH,pulseL;
volatile struct ETIMER_tag *pETIMERn;
eTimer_Channal.duty = 0;
eTimer_Channal.Freq = 0;
eTimer_Channal.Period = 0;
switch(EtimerN)
{ //choose base eTimer address
case 0 : pETIMERn = &ETIMER_0; break;
case 1 : pETIMERn = &ETIMER_1; break;
case 2 : pETIMERn = &ETIMER_2; break;
default: pETIMERn = &ETIMER_0; break;
}
pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 1;
pETIMERn->CH[DspiNumber+1].CCCTRL.B.ARM = 1;
while(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R))
{ //(pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0)
// Delayms(100);
// if(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R)) eTimerSTS = 1;
}
while(!(0x0080 & pETIMERn->CH[DspiNumber+1].STS.R))
{ //(pETIMERn->CH[DspiNumber].STS.B.ICF1 == 0x0)||(pETIMERn->CH[DspiNumber].STS.B.ICF2 == 0x0)
// Delayms(100);
// if(!(0x0080 & pETIMERn->CH[DspiNumber].STS.R)) eTimerSTS = 1;
}
// pETIMERn->CH[DspiNumber].CCCTRL.B.ARM = 0; // stop the input capture process
// pETIMERn->CH[DspiNumber].STS.B.ICF1 = 0x1;
// pETIMERn->CH[DspiNumber].STS.B.ICF2 = 0x1;
capture_ch[0] = pETIMERn->CH[DspiNumber].CAPT1.R; //First rising edge
capture_ch[1] = pETIMERn->CH[DspiNumber].CAPT2.R; //First falling edge
capture_ch[2] = pETIMERn->CH[DspiNumber].CAPT1.R; //Second rising edge
capture_ch[3] = pETIMERn->CH[DspiNumber].CAPT2.R; //Second falling edge
capture_ch1[0] = pETIMERn->CH[DspiNumber+1].CAPT1.R; //First rising edge
capture_ch1[1] = pETIMERn->CH[DspiNumber+1].CAPT2.R; //First falling edge
capture_ch1[2] = pETIMERn->CH[DspiNumber+1].CAPT1.R; //Second rising edge
capture_ch1[3] = pETIMERn->CH[DspiNumber+1].CAPT2.R; //Second falling edge
edge[1] = capture_ch1[0]*65536 + capture_ch[0]; // save 1st rising edge
edge[2] = capture_ch1[1]*65536 + capture_ch[1]; // save 1st falling edge
edge[3] = capture_ch1[2]*65536 + capture_ch[2]; // save 2nd rising edge
edge[4] = capture_ch1[3]*65536 + capture_ch[3]; // save 2nd falling edge
if(edge[3]>edge[1])
{
counts[0] = edge[3] - edge[1];
}
else
{
counts[0] = (0xFFFFFFFF - edge[1] +1) + edge[3];
}
eTimer_Channal.Freq = (float)100000000.0/counts[0];
eTimer_Channal.Period = counts[0] / (float)100000.0;
if(edge[2]>edge[1])
{
counts[1] = edge[2] - edge[1];
}
else
{
counts[1] = (0xFFFFFFFF - edge[1] +1) + edge[2];
}
pulseH = counts[1] / (float)100000.0;
pulseL = eTimer_Channal.Period-pulseH;
eTimer_Channal.duty = counts[1]*100/counts[0];//pulseH/eTimer_Channal.Period *100;
pETIMERn->CH[DspiNumber].STS.R = 0x00C0; // clear eTimern channel n's capture1/2 flags
pETIMERn->CH[DspiNumber+1].STS.R = 0x00C0; // clear eTimern channel n's capture1/2 flags
}
I fail to get duty. (eTimer1,channal4);
Clipping