The specific application scenarios are as follows: two PWMs are required, and the periods of the two PWMs are the same; but the period, duty cycle, and phase shift are all adjustable.
My program is initialized as follows. Set Ch2/3/6/7 of FTM0 to Combine Mode, where Ch2/3 forms one output, Ch6/7 forms one output, and Ch6 serves as the trigger source of LPTMR to trigger LPTMR counting.
void FTM0_Init(void)
{
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable clock for FTM0 during configuration */
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_PCS_MASK;
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_PCS(6); /* Source clock SPLLDIV1_CLK=80M, refer to Peripheral module clocking(Clocking Gating) */
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable clock for FTM0 register */
FTM0->OUTINIT = 0x00; /* Channel n output initialization value,channel 0& channel6=0 */
FTM0->MODE = FTM_MODE_WPDIS(1) /* WPDIS=1b,write protect to registers disabled (default) */
| FTM_MODE_INIT(1); /* When a 1 is written to INIT bit the channels output is initialized according to the state of their corresponding bit in the OUTINIT register */
FTM0->CNTIN = FTM_CNTIN_INIT(0); /*Set CNTIN in initialization stage */
/* Clear TOF */
if((FTM0->SC & FTM_SC_TOF_MASK)== FTM_SC_TOF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 0 */
(void)FTM0->SC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->SC &= ~FTM_SC_TOF_MASK; /* Bit9=0,clear the timer overflow flag */
}
/* Clear RF */
if((FTM0->SC & FTM_SC_RF_MASK)== FTM_SC_RF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 0 */
(void)FTM0->SC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->SC &= FTM_SC_RF_MASK; /* Bit7=0,clear the reload flag */
}
/* Clear CHF */
if((FTM0->CONTROLS[2].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 2 */
(void)FTM0->CONTROLS[2].CnSC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->CONTROLS[2].CnSC &= ~FTM_CnSC_CHF_MASK; /* Bit7=0,clear the channel interrupt flag */
}
if((FTM0->CONTROLS[3].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 3 */
(void)FTM0->CONTROLS[3].CnSC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->CONTROLS[3].CnSC &= ~FTM_CnSC_CHF_MASK; /* Bit7=0,clear the channel interrupt flag */
}
if((FTM0->CONTROLS[6].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 6 */
(void)FTM0->CONTROLS[6].CnSC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->CONTROLS[6].CnSC &= ~FTM_CnSC_CHF_MASK; /* Bit7=0,clear the channel interrupt flag */
}
if((FTM0->CONTROLS[7].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)
{ /* CHF = 1, set by hardware when an event occurs on channel 7 */
(void)FTM0->CONTROLS[7].CnSC; /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */
FTM0->CONTROLS[7].CnSC &= ~FTM_CnSC_CHF_MASK; /* Bit7=0,clear the channel interrupt flag */
}
/* Enable combine mode for channel pair CH2/CH3 and CH6/CH7 */
FTM0->COMBINE = FTM_COMBINE_COMBINE1_MASK| FTM_COMBINE_COMBINE3_MASK|FTM_COMBINE_SYNCEN1_MASK|FTM_COMBINE_SYNCEN3_MASK;
FTM0->CONTROLS[2].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[3].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[6].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/
FTM0->CONTROLS[7].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/
FTM0->EXTTRIG = FTM_EXTTRIG_CH6TRIG(1); /* Enables the generation of the trigger when the FTM counter is equal to C6V */
}
It stands to reason that in my settings, both MOD and CnV can be updated when the counter changes from MOD to CNTIN, but during actual testing, I found that only MOD will be updated;
Currently, MOD and CnV can only be updated by pausing FTM0_CLKS(as follows), but this will cause the PWM output to pause, as shown in the waveform below.
void FTM0_SetPeriodDutyAndPhsShft(uint16 Period, uint16 Duty1, uint16 Duty2, uint16 Phase)
{
if((Duty1 < Period)&&(Duty1 + Phase <= Period)) /* phase range: 0~50 degree */
{
FTM0_DisablePwmOutput();
FTM0->MOD = FTM_MOD_MOD(Period-1);
FTM0->CONTROLS[2].CnV=FTM_CnV_VAL(0);/* Set as base */
FTM0->CONTROLS[3].CnV=FTM_CnV_VAL(Duty1);
FTM0->CONTROLS[6].CnV=FTM_CnV_VAL(Period/2-Phase);
FTM0->CONTROLS[7].CnV=FTM_CnV_VAL(Period/2-Phase + Duty2);
FTM0_EnablePwmOutput();
}
else
{
/* Should report error*/
}
}
If I want to control the updates of the FTM's MOD and CnV registers smoothly without stopping the PWM output, is there any recommended method?
Solved! Go to Solution.
Hi @yumi,
What is the content of MOD, INIT and CnV before and after the update?
Is a loading point selected?
BR, Daniel
Hello @yumi,
You need to set FTMEN and SYNCMODE which I don't see in the code you posted.
The MOD and CnV synchronization is similar.
Have a look at RM, Section 47.5.13.4 MOD register synchronization.
There is the whole flowchart.
Can you follow the FTM Initialization Procedure (RM, Section 47.8) step by step?
Thank you,
Regards,
Daniel
So the problem is:
The update method you suggested me to use is the 3rd method in Table 47-10/11, which is CLKS[1:0] != 0:0 and FTMEN = 1, then MOD is updated by MOD register synchronization in 47.5.13.4, and C(n)V and C(n+1)V register synchronization in 47.5.13.6.
So why don't you suggest me to use the 2nd method in Table 47-10/11, which is CLKS[1:0] != 0:0 and FTMEN = 0? Actually I am not sure what TPM is.
The FTMEN = 0 mode can be used as well.
But with FTMEN = 1, we can update the PWM using triggers.
Regarding TPM, have a look at AN5303 Features and Operation Modes of FlexTimer Module on S32K
https://www.nxp.com/docs/en/application-note/AN5303.pdf
I changed my initiation software as follows, but the PWM update is still not very smooth.
Could you please give me some advice?
void FTM0_Init(void)
{
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable clock for FTM0 during configuration */
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_PCS_MASK;
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_PCS(6); /* Source clock SPLLDIV1_CLK=80M, refer to Peripheral module clocking(Clocking Gating) */
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable clock for FTM0 register */
FTM0->POL = 0x00000000; /* Polarity for all channels is active high (default)*/
FTM0->CNTIN = FTM_CNTIN_INIT(0); /* Set CNTIN in initialization stage */
FTM0->OUTINIT = 0x00; /* Channel n output initialization value */
FTM0->MODE = FTM_MODE_WPDIS(1) /* WPDIS=1b,write protect to registers disabled (default) */
| FTM_MODE_INIT(1); /* When a 1 is written to INIT bit the channels output is initialized according to the state of their corresponding bit in the OUTINIT register */
FTM0->SC &= ~FTM_SC_CLKS_MASK; /* Disable the clock*/
/* Enable combine mode for channel pair CH2/CH3 and CH6/CH7 */
FTM0->COMBINE = FTM_COMBINE_COMBINE1_MASK| FTM_COMBINE_COMBINE3_MASK|FTM_COMBINE_SYNCEN1_MASK|FTM_COMBINE_SYNCEN3_MASK;
FTM0->CONTROLS[2].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[3].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[6].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/
FTM0->CONTROLS[7].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/
FTM0->EXTTRIG = FTM_EXTTRIG_CH6TRIG(1); /* Enables the generation of the trigger when the FTM counter is equal to C6V */
/* Select synchronization for Output Mask */
/* SWSYNC=0(software trigger is not selected), TRIG2/1/0=0(Trigger 0/1/2 are disabled),*/
/* SYNCHOM=1(OUTMASK register is updated with the value of its buffer only by the PWM synchronization), */
/* REINIT=0(FTM counter continues to count normally) ,CNTMAX=0(The maximum loading point is disabled), */
/*CNTMIN=0(The minimum loading point is disabled) */
FTM0->SYNC = FTM_SYNC_SYNCHOM(1);
/* Write to SYNCONF */
FTM0->SYNCONF = FTM_SYNCONF_SWOM(1) /* The software trigger activates the OUTMASK register synchronization */
| FTM_SYNCONF_SWWRBUF(1) /* The software trigger activates MOD, HCR, CNTIN, and CV registers synchronization */
| FTM_SYNCONF_SWRSTCNT(1) /* The software trigger activates the FTM counter synchronization */
| FTM_SYNCONF_SYNCMODE(1); /* Enhanced PWM synchronization is selected */
FTM0->MODE = FTM_MODE_FTMEN(1);
FTM0->SC |= FTM_SC_CLKS(1) /* Clock Selection, FTM system clock*/
| FTM_SC_PWMEN2_MASK /* PWMEN2 = 1b, Enable channel 2 PWM output */
| FTM_SC_PWMEN3_MASK /* PWMEN3 = 1b, Enable channel 3 PWM output */
| FTM_SC_PWMEN6_MASK /* PWMEN6 = 1b, Enable channel 6 PWM output */
| FTM_SC_PWMEN7_MASK; /* PWMEN7 = 1b, Enable channel 7 PWM output */
}
Hi @yumi,
What is the content of MOD, INIT and CnV before and after the update?
Is a loading point selected?
BR, Daniel
I selected a loading point, then the problem was solved.