2024-10-17 02:08 AM
Hi, i'm implementing a PWM signal using STM32, the problem i'm facing is that when i set the duty cycle of the pulse to zero... i get the pin to stay high, even if i disable the timer associated with the PWM output.
This are my setting:
My APB2 Bus is set to 170 MHz, i scaled that down to 1 Mhz with prescaler then to 100Hz with ARR.
This is the timer init function :
static void MX_TIM5_Init(void)
{
/* USER CODE BEGIN TIM5_Init 0 */
/* USER CODE END TIM5_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM5_Init 1 */
/* USER CODE END TIM5_Init 1 */
htim5.Instance = TIM5;
htim5.Init.Prescaler = 170-1;
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
htim5.Init.Period = 9999;
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim5, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim5) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim5, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
__HAL_TIM_DISABLE_OCxPRELOAD(&htim5, TIM_CHANNEL_3);
/* USER CODE BEGIN TIM5_Init 2 */
/* USER CODE END TIM5_Init 2 */
HAL_TIM_MspPostInit(&htim5);
}
I want to have a minimum of 100 ms for 1% of the duty cycle, the value of SetPower is 1/100, so i calculate the CCR3 value as follows:
Compare_register = (SetPower*(htim5.Init.Period+1))/100; // CCR3
TIM5->CCR3 = Compare_register;
i'm shutting of the timer when the SetPower value is at zero.
In debugging monitoring the htim5.ChannelState[2], i see it busy when is outputting signal with duty>0 then ready when duty = 0;
My question is why the channel stays high when the timer is stopped.
Solved! Go to Solution.
2024-10-17 02:54 AM
Hello @Riccardo Franceschetto,
When you set the duty cycle to zero, the output compare register (CCR) is set to zero, which means the PWM signal will not generate any pulses, but the output can remain in a high state depending on the configuration of the output compare mode.
You are usingTIM_OCMODE_PWM1, so the output is set high when the counter is less than the compare value and set low when the counter is equal to or greater than the compare value. If the compare value is zero, the output will remain high which is the case
Try to manually set the the output pin to low when the duty cycle is zero
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-10-17 02:54 AM
Hello @Riccardo Franceschetto,
When you set the duty cycle to zero, the output compare register (CCR) is set to zero, which means the PWM signal will not generate any pulses, but the output can remain in a high state depending on the configuration of the output compare mode.
You are usingTIM_OCMODE_PWM1, so the output is set high when the counter is less than the compare value and set low when the counter is equal to or greater than the compare value. If the compare value is zero, the output will remain high which is the case
Try to manually set the the output pin to low when the duty cycle is zero
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-10-17 02:56 AM
Thanks, but why the pin stays high even if the timer is stopped?
2024-10-17 02:59 AM
When you stop the timer, the last state of the GPIO pin is retained, which in your case is high
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-10-17 03:02 AM
So you suggest to stop the timer and reset the state of the gpio pin, right?
Thanks for the insights.
2024-10-17 03:07 AM
yes, I suggest to modify the Compare register calculation:
When the duty cycle is zero, stop the timer and manually set the GPIO pin to low
When the duty cycle is non-zero, start the timer and configure the GPIO pin for PWM output
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-10-17 03:28 AM - edited 2024-10-17 05:24 AM
I cant use the classic HAL_GPIO_WritePin(LOOP_EN_micro_GPIO_Port,LOOP_EN_micro_Pin , GPIO_PIN_RESET) right?
LOOP_EN_micro is the label i gave to the TIM5_CH3 in the IOC configurator.
or do i have to initialize the pin to gpio and then re initialize as pwm output?
EDIT: i solved like this:
#define LOOP_EN_ON HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3); \
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
GPIO_InitStruct.Pin = LOOP_EN_micro_Pin; \
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; \
GPIO_InitStruct.Pull = GPIO_NOPULL; \
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; \
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5; \
HAL_GPIO_Init(LOOP_EN_micro_GPIO_Port, &GPIO_InitStruct);
#define LOOP_EN_OFF HAL_TIM_PWM_Stop (&htim5, TIM_CHANNEL_3); \
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
GPIO_InitStruct.Pin = LOOP_EN_micro_Pin; \
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;; \
GPIO_InitStruct.Pull = GPIO_NOPULL; \
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; \
HAL_GPIO_Init(LOOP_EN_micro_GPIO_Port, &GPIO_InitStruct); \
HAL_GPIO_WritePin(LOOP_EN_micro_GPIO_Port,LOOP_EN_micro_Pin , GPIO_PIN_RESET);
2024-10-17 05:22 AM
What is
> i'm shutting of the timer when the SetPower value is at zero.
?
JW
2024-10-17 05:26 AM
HAL_TIM_PWM_Stop (&htim5, TIM_CHANNEL_3);
when the CCR3 value is zero ( the duty is zero)
2024-10-17 05:58 AM
Why?
Just don't call that.
JW