Skip to main content
Graduate
October 17, 2024
Solved

PWM output high when duty cycle is 0 [STM32G474RET]

  • October 17, 2024
  • 5 replies
  • 2309 views

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:

RiccardoFranceschetto_2-1729155164355.png

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.

    This topic has been closed for replies.
    Best answer by Sarra.S

    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

    5 replies

    Sarra.SAnswer
    ST Employee
    October 17, 2024

    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

    Graduate
    October 17, 2024

    Thanks, but why the pin stays high even if the timer is stopped?

    ST Employee
    October 17, 2024

    When you stop the timer, the last state of the GPIO pin is retained, which in your case is high

    Graduate
    October 17, 2024

    So you suggest to stop the timer and reset the state of the gpio pin, right?

    Thanks for the insights.

    ST Employee
    October 17, 2024

    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

    Graduate
    October 17, 2024

    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);

     

    Super User
    October 17, 2024

    What is

    > i'm shutting of the timer when the SetPower value is at zero.

    ?

    JW

    Graduate
    October 17, 2024
    HAL_TIM_PWM_Stop (&htim5, TIM_CHANNEL_3);

    when the CCR3 value is zero ( the duty is zero)

    Super User
    October 17, 2024

    Why?

    Just don't call that.

    JW