cancel
Showing results for 
Search instead for 
Did you mean: 

How to Properly Configure and Trigger a Soft Break on TIM1 in STM32

simon_EQUIUM
Associate

Hello everyone,

I'm working on a motor control project using an STM32 microcontroller (TIM1 and TIM8 timers), and I need to implement a soft Break to safely stop the PWM signals with proper transitions (respecting Dead Time and setting the outputs to 0V in low-impedance mode). However, the methods I've tried so far don't seem to work as expected. Here's what I want to achieve:

  1. When stopping the motor, ensure all PWM outputs go to 0V in low-impedance mode.
  2. Respect the configured Dead Time during the transition to avoid cross-conduction.
  3. Optionally, use a software-triggered Break (TIM_BDTR_BKE) to achieve this cleanly.

My Current Setup

  1. Initialization Code (PWM Start):

 

 

 

 

 

HAL_StatusTypeDef motor_pwm_init(uint8_t motor_i) {
    HAL_StatusTypeDef status = HAL_OK;

    TIM1->CCR2 = VALUE_MAX_TIMER_PWM;
    TIM1->CCR1 = VALUE_MAX_TIMER_PWM;
    TIM8->CCR2 = VALUE_MAX_TIMER_PWM;
    TIM8->CCR1 = VALUE_MAX_TIMER_PWM;

    if (motor_i == MOTOR_1) {
        status |= HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
        status |= HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
        status |= HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
        status |= HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
    } else if (motor_i == MOTOR_2) {
        status |= HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
        status |= HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_1);
        status |= HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2);
        status |= HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_2);
    }
    return status;
}

 

 

 

 

 

  • Stop code :

 

 

 

 

 

HAL_StatusTypeDef motor_pwm_stop(uint8_t motor_i) {
    HAL_StatusTypeDef status = HAL_OK;

    if (motor_i == MOTOR_1) {
        status |= HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
        status |= HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
        status |= HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
        status |= HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
    } else if (motor_i == MOTOR_2) {
        status |= HAL_TIM_PWM_Stop(&htim8, TIM_CHANNEL_1);
        status |= HAL_TIMEx_PWMN_Stop(&htim8, TIM_CHANNEL_1);
        status |= HAL_TIM_PWM_Stop(&htim8, TIM_CHANNEL_2);
        status |= HAL_TIMEx_PWMN_Stop(&htim8, TIM_CHANNEL_2);
    }
    return status;
}
​

 

 

 

 

 

  • I added the following lines to configure OSSI/OSSR and attempted to trigger the Break with TIM_BDTR_BKE:

 

 

 

 

 

htim1.Instance->BDTR |= TIM_BDTR_OSSI; // Set off-state in Idle
htim1.Instance->BDTR |= TIM_BDTR_OSSR; // Set off-state after Break
htim1.Instance->BDTR |= TIM_BDTR_BKE;  // Trigger Break
​

 

 

 

 

 

 

Observed Issues

  1. Activating TIM_BDTR_BKE does not seem to have any effect; the PWM outputs continue to run as if nothing happened.
  2. OSSI/OSSR do not seem to control the state of the outputs when the timer is off or after attempting the Break.
  3. Using HAL_TIM_PWM_Stop does stop the PWM channels, but it doesn't ensure transitions with Dead Time, which risks cross-conduction in my H-bridge.
    simon_EQUIUM_0-1734362306173.png

     

What I Tried

  • Ensured MOE is enabled (TIM_BDTR_MOE).
  • Verified that the timer is properly initialized and running.
  • Used a debugger to check the values in the BDTR register, and the BKE bit appears to be set correctly.

How can I configure TIM1 to respect the Dead Time when stopping the PWM signals? Is triggering a soft Break (TIM_BDTR_BKE) supposed vto work without an external signal? If yes, what additional configurations are required?

Any help or guidance would be greatly appreciated! Thank you in advance.

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @simon_EQUIUM,

Thank you for your feedback.
Refer to Advanced-control timers chapter on Reference manual documentation.
As mentioned in "Using the break function" chapter, "Break events can also be generated by software using BG and B2G bits in the TIMx_EGR register."

If you agree with the answer, please accept it by clicking on 'Accept as solution'.
Best regards.
GMA

View solution in original post

2 REPLIES 2
simon_EQUIUM
Associate

Ok, I have found the solution.

To stop the motor by software you have to use the lines :

htim1.Instance->EGR |= TIM_EGR_BG;


And to restart the motor :

	    htim1.Instance->BDTR &= ~TIM_BDTR_MOE;
	    status |= HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
	    status |= HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
	    osDelay(1);
	    status |= HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
	    status |= HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);

	    htim1.Instance->BDTR |= TIM_BDTR_MOE;

I don't know why, but I have to place a osDelay before PWMN because I want to active in a first time the low side of my channel. Without this delay, the high side start before the low side and the bootstrap capacitor can't be charged.



Hello @simon_EQUIUM,

Thank you for your feedback.
Refer to Advanced-control timers chapter on Reference manual documentation.
As mentioned in "Using the break function" chapter, "Break events can also be generated by software using BG and B2G bits in the TIMx_EGR register."

If you agree with the answer, please accept it by clicking on 'Accept as solution'.
Best regards.
GMA