Hello, I have initialized PWM, but I can change duty cycle in runtime.
The strange moment, if I put breakpoint on this line (FTM0->CONTROLS[channel].CnV = (FTM0->MOD * duty) / 100;), and step over, after that press continue - dc changed.
If I just stop on this line, and press continue - dc unchanged.
This is my initialization:
/* Select and enable clock for FTM0 */
PCC->PCCn[PCC_FTM0_INDEX] = PCC_PCCn_PCS(1) | PCC_PCCn_CGC_MASK;
/* Set PORTB pins for FTM0 */
PORTD->PCR[15] = PORT_PCR_MUX(2); // FTM0, Channel0
PORTD->PCR[16] = PORT_PCR_MUX(2); // FTM0, Channel1
/* Enable registers updating from write buffers */
FTM0->MODE = FTM_MODE_FTMEN_MASK | FTM_QDCTRL_QUADEN_MASK | FTM_MODE_PWMSYNC(1);
/* Enable sync, combine mode and dead-time for pair channel n=1 and n=2 */
FTM0->COMBINE = FTM_COMBINE_COMP0_MASK | FTM_COMBINE_DTEN0_MASK | FTM_COMBINE_COMP1_MASK | FTM_COMBINE_DTEN1_MASK;
/* Set Modulo in initialization stage (10kHz PWM frequency @112MHz system clock) */
FTM0->MOD = FTM_MOD_VAL();
/* Set CNTIN in initialization stage */
FTM0->CNTIN = 0;
/* Enable high-true pulses of PWM signals */
FTM0->CONTROLS[0].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK) & ~FTM_CnSC_ELSA_MASK;
FTM0->CONTROLS[1].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK) & ~FTM_CnSC_ELSA_MASK;
/* Set channel value in initialization stage */
FTM0->CONTROLS[0].CnV=FTM_CnV_VAL(700); // 50% duty cycle
FTM0->CONTROLS[1].CnV=FTM_CnV_VAL(100); // 50% duty cycle
/* Reset FTM counter */
FTM0->CNT = 0;
/* Insert deadtime (1us) */
FTM0->DEADTIME = FTM_DEADTIME_DTPS(3) | FTM_DEADTIME_DTVAL(7);
/* Clock selection and enabling PWM generation */
FTM0->SC = FTM_SC_PS(1) | FTM_SC_CLKS(1) | FTM_SC_CPWMS_MASK | FTM_SC_PWMEN0_MASK | FTM_SC_PWMEN1_MASK;
}
What am I doing wrong?
Hello,
I tested the source code proposed by danielmartynek,but noticed the following error:
FTM0-> COMBINE | = (1 << 5) | (1 << 10); // SYNCEN0, SYNCEN1
if SYNCEN0, SYNCEN1, it should be FTM0-> COMBINE | = (1 << 5) | (1 << 13);
Here is code for two independent PWM channels ( Thank you very much Peter for your help ) :
PORTD->PCR[0] = PORT_PCR_MUX(2); // FTM0, Channel2
PORTD->PCR[1] = PORT_PCR_MUX(2); // FTM0, Channel3
//Enable registers updating from write buffers
FTM0->MODE = FTM_MODE_FTMEN_MASK;
//Set Modulo in initialization stage (19,5kHz PWM frequency @80MHz system clock)
FTM0->MOD = FTM_MOD_MOD(4096-1); // 12bit D/A - 4096
//Set CNTIN in initialization stage
FTM0->CNTIN = 0;
//Enable high-true pulses of PWM signals
FTM0->CONTROLS[2].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM0->CONTROLS[3].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//Set channel value in initialization stage
FTM0->CONTROLS[2].CnV=FTM_CnV_VAL(2048); // 50% duty cycle
FTM0->CONTROLS[3].CnV=FTM_CnV_VAL(2048); // 50% duty cycle
//Enable reload opportunity when FTM counter reach CNTMAX value
FTM0->SYNC |= FTM_SYNC_CNTMAX_MASK;
//Enable software synchronization
FTM0->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK | FTM_SYNCONF_SWWRBUF_MASK;
//Enables PWM synchronization of registers C2V and C3V
FTM0->COMBINE = FTM_COMBINE_SYNCEN1_MASK;
//Reset FTM counter
FTM0->CNT = 0;
//Clock selection and enabling PWM generation
FTM0->SC |= FTM_SC_CLKS(1) | FTM_SC_PWMEN2_MASK | FTM_SC_PWMEN3_MASK;
..and it works...
Hi,
The update of the duty cycle has to be synchronized.
You may refer to AN5303 Features and Operation Modes of FlexTimer Module on S32K, 4.3. Updating FTM registers
or Section 45.5.12.6, Table 45-11, Figure 45-55 in the RM rev.7.
I modified the code you posted to trigger the synchronization by a software trigger.
/* Enable registers updating from write buffers */
FTM0->MODE = FTM_MODE_FTMEN_MASK;
/* Enable sync, combine mode and dead-time for pair channel n=1 and n=2 */
FTM0->COMBINE = FTM_COMBINE_COMP0_MASK | FTM_COMBINE_DTEN0_MASK | FTM_COMBINE_COMP1_MASK | FTM_COMBINE_DTEN1_MASK;
FTM0->COMBINE |= (1 << 5) | (1 << 10); // SYNCEN0, SYNCEN1
/* Set Modulo in initialization stage (10kHz PWM frequency @112MHz system clock) */
FTM0->MOD = 1000;
/* Set CNTIN in initialization stage */
FTM0->CNTIN = 0;
/* Enable high-true pulses of PWM signals */
FTM0->CONTROLS[0].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK) & ~FTM_CnSC_ELSA_MASK;
FTM0->CONTROLS[1].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK) & ~FTM_CnSC_ELSA_MASK;
/* Set channel value in initialization stage */
FTM0->CONTROLS[0].CnV=FTM_CnV_VAL(700); // 50% duty cycle
FTM0->CONTROLS[1].CnV=FTM_CnV_VAL(100); // 50% duty cycle
/* Reset FTM counter */
FTM0->CNT = 0;
/* Insert deadtime (1us) */
FTM0->DEADTIME = FTM_DEADTIME_DTPS(3) | FTM_DEADTIME_DTVAL(7);
FTM0->SYNCONF |= (1 << 7) | (1 << 9); // SWWRBUF, SYNCMODE
/* Clock selection and enabling PWM generation */
FTM0->SC = FTM_SC_PS(1) | FTM_SC_CLKS(1) | FTM_SC_CPWMS_MASK | FTM_SC_PWMEN0_MASK |
FTM_SC_PWMEN1_MASK;
delay();
FTM0->CONTROLS[0].CnV = 32;
FTM0->CONTROLS[1].CnV = 32;
// Trigger synchronization
FTM0->SYNC = 0x83; // CNTMIN CNTMAX SWSYNC
while(1);
Regards,
Daniel