in independent mode , how to set different channel with phase shift, like 10, 20, 30degree phase shift,
i see there is dead time setting, but phase shift setting,
so i enable the deadtime, but no delay between the two channel waveform
could you help to check how to set phase **bleep**ft with tool and attached project, thanks a lot!
Hi@alice_thanks
Please do not create the same question, you must read the datasheet so that you are familiar
with this mode.
For Phase Shift, you need to use Modified Combine PWM Mode, which meets your needs.
I made a three Pairs phase shift demo for your reference
RTM 4.0.1 + Modified Combine PWM + Insert Dead Time + Same Duty Cycle
hello @Senlent
thanks a lot!, in combine mode , it use first edge and second edge to shift phase in the init state, is that correct ?
that's means PB13 and PTE6 can't don't phase shift ?
Hi@alice_thanks
Please refer to the data sheet, which explains it in detail.
PTB13 and PTE6 belong to two different FTM instances, but this does not mean that phase shifting cannot be achieved. If the counters of FTM0 and FTM3 can be guaranteed to start at the same time, this is still possible.
hello @Senlent
why 10kHz can use FTM_UPDATE_NOW, 100Hz need FTM_WAIT_LOADING_POINTS ?
i see the chart when software trigger use WAIT_LOADING_POINTS
This is just because the currently executed API (FTM_DRV_UpdatePwmChannel) has not succeeded, and this API is executed again.
You can leave the above configuration unchanged and add a longer extension time to achieve the same effect.
hello @Senlent
There should have some problem, ch0-ch1 is dutyCycle = 0x6000,
ch4-ch5 already 0x8000 which means 100% duty cycle, then ch4-ch5 have no pahse shift
same ch0-ch1 is dutyCycle = 0x7000, ch2-ch3 already 0x8000, 100% duty cycle
/* Update PWM channels */
FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM_1, 1U, FTM_PWM_UPDATE_IN_DUTY_CYCLE, 0, dutyCycle, true);
FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM_1, 3U, FTM_PWM_UPDATE_IN_DUTY_CYCLE, 0, dutyCycle+0x1000, true);
FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM_1, 5U, FTM_PWM_UPDATE_IN_DUTY_CYCLE, 0, dutyCycle+0x2000, true);
//delayCycles(0x1FFFU);
Don't waste my time anymore.
Test the demo I provided and read the data sheet before asking questions.
the output waveform is your demo test result, if you observe longer time, 2 circle time, you will see the problem, i attached the vedio
i just double wether is below cause, maybe seems not .
when the dutyCycle < 0x6000,
all the waveform is correct with phase shift,
but dutyCycle > 0x6000
ch5 secondEdge dutyCycle+0x2000 > 0x8000, that will cause ch4-ch5 will not update
if ((firstEdge <= FTM_MAX_DUTY_CYCLE) && (secondEdge <= FTM_MAX_DUTY_CYCLE))
look at here FTM_MAX_DUTY_CYCLE = 0x8000, that means
retStatus = STATUS_ERROR;
it will not update the hwSecondEdge
FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)((chnlPairNum * 2U) + 1U), hwSecondEdge);
if (STATUS_SUCCESS == retStatus)
{
if (true == FTM_DRV_GetDualChnCombineCmd(ftmBase, chnlPairNum))
{
if (true == FTM_DRV_GetDualChnMofCombineCmd(ftmBase, chnlPairNum))
{
/* Check the clock source for FTM counter is disabled or not */
if (FTM_DRV_GetClockSource(ftmBase) == 0U)
{
FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
}
}
else
{
FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
}
/* Modify the initial value in the channel (n+1) match edge */
FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)((chnlPairNum * 2U) + 1U), hwSecondEdge);
}
else
{
/* Channel value is divided by 2 for up down counter mode to keep same duty */
if (true == FTM_DRV_GetCpwms(ftmBase))
{
FTM_DRV_SetChnCountVal(ftmBase, channel, (uint16_t)(hwFirstEdge >> 1U));
}
else
{
FTM_DRV_SetChnCountVal(ftmBase, channel, hwFirstEdge);
}
}
/* Check the type of update for PWM */
if (FTM_PWM_UPDATE_IN_DUTY_CYCLE == typeOfUpdate)
{
if ((firstEdge <= FTM_MAX_DUTY_CYCLE) && (secondEdge <= FTM_MAX_DUTY_CYCLE))
{
/* Calculate DutyCycle based of the previously calculated frequency*/
/* For greater resolution the DutyCycle values are in the range [0. FTM_MAX_DUTY_CYCLE]
* where 0 = 0% or PWM always at Low and FTM_MAX_DUTY_CYCLE = 100% or PWM always HIGH;
* a value of 0x4000 is equivalent of 50% DutyCycle. */
hwFirstEdge = (uint16_t)((ftmPeriod * firstEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
hwSecondEdge = (uint16_t)((ftmPeriod * secondEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
/* adjust DutyCycle if 100% value is to be achieved. */
if (FTM_MAX_DUTY_CYCLE == firstEdge)
{
/* If expected duty is 100% then increase by 1 the value that is to be written
* to Hardware so it will exceed value of period */
hwFirstEdge = (uint16_t)(hwFirstEdge + 1U);
}
}
else
{
retStatus = STATUS_ERROR;
}
}
int main(void)
{
/* Write your local variable definition here */
ftm_state_t ftmStateStruct;
bool increaseDutyCycle = true;
uint32_t dutyCycle = 0UL;
/* Initialize clock module */
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
/* Initialize pins */
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
/* Initialize FTM */
FTM_DRV_Init(INST_FLEXTIMER_PWM_1, &flexTimer_pwm_1_InitConfig, &ftmStateStruct);
/* Initialize FTM PWM */
FTM_DRV_InitPwm(INST_FLEXTIMER_PWM_1, &flexTimer_pwm_1_PwmConfig);
unsigned int FTM0_MOD = FTM0->MOD;
unsigned int Ch0_1_phase_shift = FTM0->CONTROLS[0].CnV;
dutyCycle = Ch0_1_phase_shift;
/* Infinite loop
* - increment or decrement duty cycleU
* - Update channel duty cycle
* - Wait for a number of cycles to make
* the change visible
*/
for ( ;; )
{
if (dutyCycle > (FTM0_MOD))
dutyCycle = 0;
else
dutyCycle++;
FTM0->CONTROLS[1].CnV = FTM_CnV_VAL(dutyCycle);
FTM0->CONTROLS[3].CnV = FTM_CnV_VAL(dutyCycle);
FTM0->CONTROLS[5].CnV = FTM_CnV_VAL(dutyCycle);
delayCycles(0x2FFFU);
}
return exit_code;
}
FTM0->CONTROLS[1].CnV = FTM_CnV_VAL(dutyCycle);
FTM0->CONTROLS[3].CnV = FTM_CnV_VAL(dutyCycle);
FTM0->CONTROLS[5].CnV = FTM_CnV_VAL(dutyCycle);
there is no phase shift, only dutyCycle different as c(n)V is different
dutyCycle = c(n+1)V - c(n)V
when modify
FTM0->CONTROLS[1].CnV = FTM_CnV_VAL(dutyCycle);
FTM0->CONTROLS[3].CnV = FTM_CnV_VAL(dutyCycle-0x1000);
FTM0->CONTROLS[5].CnV = FTM_CnV_VAL(dutyCycle-0x2000);
no output