Dear NXP Support Team,
I am currently working with the S32K142 microcontroller and using six PWM channels via the FTM3 module. The system clock is configured to 80 MHz. My application reads an ADC value from a potentiometer (ranging from 0 to approximately 1900 LSBs) and maps it to the PWM duty cycle.
However, I am experiencing an issue where the duty cycle does not update during runtime, even though the ADC values are changing correctly. As a temporary workaround, I stop the FTM3 timer before writing to the CnV registers and restart it afterwards. This approach works, but it is not ideal for a real-time application.
It seems that the synchronization mechanism is not working as expected. I would like to understand the root cause of this behavior and whether there is a recommended way to update the duty cycle during runtime without stopping the timer.
To support this, I am preparing a minimal example demonstrating the issue. I would appreciate any insights or suggestions you can provide regarding proper PWM synchronization with FTM3 on the S32K142.
Initialisation:
void FTM3_PWM_Init_Basic(void)
{
// Clock aktivieren
PCC->PCCn[PCC_FTM3_INDEX] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC_MASK;
// PTD3 als FTM3_CH5 konfigurieren (ALT2)
PORTD->PCR[3] = PORT_PCR_MUX(2);
// FTM-Modus aktivieren
FTM3->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FTMEN_MASK;
// Timer konfigurieren (noch nicht starten!)
FTM3->SC = 0; // Timer gestoppt
FTM3->MOD = PWM_PERIOD_TICKS;
// Kanal 5 konfigurieren
FTM3->CONTROLS[5].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM3->CONTROLS[5].CnV = PWM_PERIOD_TICKS / 2; // 50% Duty
// PWM-Ausgabe aktivieren
FTM3->SC |= FTM_SC_PWMEN5_MASK;
// Jetzt Timer starten
FTM3->SC |= FTM_SC_CLKS(1) | FTM_SC_PS(0); // System Clock, Prescaler = 1
}
Duty-Update that does not work:
void FTM3_PWM_Update(uint16_t adcValue)
{
uint16_t dutyTicks = (adcValue * PWM_PERIOD_TICKS) / MAX_ADC_VALUE;
// 1. PWM-Ausgabe kurz maskieren, um Glitches zu vermeiden
FTM3->OUTMASK = 0x20; // Maske für CH5 (Bit 5)
// 2. Duty-Cycle in gepuffertes Register schreiben
FTM3->CONTROLS[5].CnV = dutyTicks;
// 3. Synchronisation auslösen → übernimmt CnV und OUTMASK
FTM3->SYNC |= FTM_SYNC_SWSYNC_MASK;
// 4. PWM-Ausgabe wieder aktivieren
FTM3->OUTMASK = 0x00;
FTM3->SYNC |= FTM_SYNC_SWSYNC_MASK;
}
Duty-Update that works:
void FTM3_PWM_Update(uint16_t adcValue)
{
uint16_t dutyTicks = (adcValue * PWM_PERIOD_TICKS) / MAX_ADC_VALUE;
// Timer stoppen
FTM3->SC &= ~FTM_SC_CLKS_MASK;
// CnV schreiben
FTM3->CONTROLS[5].CnV = dutyTicks;
// Timer wieder starten
FTM3->SC |= FTM_SC_CLKS(1) | FTM_SC_PS(0);
}
Thanks and kind regards,
Armin