How to Properly Configure and Trigger a Soft Break on TIM1 in STM32
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:
- When stopping the motor, ensure all PWM outputs go to 0V in low-impedance mode.
- Respect the configured Dead Time during the transition to avoid cross-conduction.
- Optionally, use a software-triggered Break (TIM_BDTR_BKE) to achieve this cleanly.
My Current Setup
-
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
- Activating TIM_BDTR_BKE does not seem to have any effect; the PWM outputs continue to run as if nothing happened.
- OSSI/OSSR do not seem to control the state of the outputs when the timer is off or after attempting the Break.
- 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.
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.
