I'm using an STM32F4 to control a stepper motor.

I'm not sure if I need PWM mode or OC Mode or OnePulse Mode. I can generate a fixed frequency PWM wave but since I need a particular acceleration/deceleration, I need to vary the frequency of the wave with a ramp.

Something like: one pulse at 745 Hz; one pulse at 1867 Hz; one pulse at 2459 Hz; one pulse at ...; one pulse at ...; N pulses at ... (constant speed)

Right now in the callback HAL_TIM_PWM_PulseFinishedCallback, I'm issuing new TIMx->ARR and TIMx->CCR1 values based on a given logic.

Here is my code:

void MX_TIM9_Init(void)
TIM_OC_InitTypeDef sConfigOC;

htim9.Instance = TIM9;
htim9.Init.Prescaler = PSC; // Get clock to <freq> Hz
htim9.Init.CounterMode = TIM_COUNTERMODE_UP;
htim9.Init.Period = 1582; // useless since it is varying
htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

sConfigOC.Pulse = htim9.Init.Period / 2; //useless but always 50% of CCR1
HAL_TIM_PWM_ConfigChannel(&htim9, &sConfigOC, TIM_CHANNEL_1);


void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef* htim){
if (htim->Instance == TIM9){
    // logic
    TIM9->ARR = v;
    TIM9->CCR1 = v/2;

int main(void) {

//logic and if needed
HAL_TIM_PWM_Start_IT(&m->htim, TIM_CHANNEL_1);

What I'm noticing is that the wave train is not perfectly shaped as if the Update Event that update the shadow register happens sporadically. If I'm expecting one pulse with 500 Hz and a second of 700 Hz that doesn't happen. Clearly a constant frequency wave at 500 Hz and 700 Hz is generated correctly. I tried to SET-RESET an output to verify at which point the interrupt is called.

When it fails it seems that an interrupt is called when the PWM is still "high."

Is the PWM the right way to do it or should I use OC or OnePulse mode?

  • \$\begingroup\$ perhaps @Community should start a "bounty" to hunt down the person didn't accept his own answer the day after he answered his own question \$\endgroup\$ Sep 3, 2017 at 22:23

2 Answers 2


You can change on the fly freq with TIMx->PSC

  • \$\begingroup\$ Hi, this is almost an answer but should should indicate that a value must be written to this register and elaborate a bit on how that meets his needs. Changing the prescaler (alone) may not meet the actual frequency requirements. The minimum pulse width is missing too. So it may be a mix between several settings. \$\endgroup\$
    – le_top
    May 13, 2020 at 16:22
  • \$\begingroup\$ Hi, I assumed that other things are already written. Absolutely, need an variable to TIMx->PSC=nnn, and duty cycle. \$\endgroup\$
    – Çağlar
    May 14, 2020 at 19:36

The problem was related to the preload registers. As mentioned in en.DM00236305.pdf they are needed in order to have a perfect timing between UEV and register correct loading

  • \$\begingroup\$ I suggest that you corret your corrected program in the anwser so that it can really help other users. \$\endgroup\$
    – le_top
    May 13, 2020 at 16:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.