How to change PWM duty cycle on s32k144?

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

How to change PWM duty cycle on s32k144?

4,286 Views
alexalexandrov
Contributor I

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?

0 Kudos
2 Replies

1,677 Views
MarcinW
Contributor I

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...

0 Kudos

2,572 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

The update of the duty cycle has to be synchronized.

You may refer to AN5303 Features and Operation Modes of FlexTimer Module on S32K4.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

0 Kudos