Skip to main content
Visitor II
March 25, 2025
Question

TIM13 and TIM14 PWM output issues STM32H562

  • March 25, 2025
  • 9 replies
  • 1281 views

Hi All,

I have a project that is using the STM32H562. I am having an issue using tim13 and tim14 to generate PWM outputs going to LEDs. The project uses timers tim2, tim3, tim4, tim13, and tim14 for a range of different PWM peripherals. For all of the timer instances that aren't tim13 and tim14, the PWM configures and works as expected, but I am unable to get any PWM output signal on the channels controlled by tim13 and tim14. Neither the autogenerated INIT functions or my application code to update the pulse width value return any errors from the HAL functions, and I can see the value of the registers being updated with the new pulse value, but there is no output on those pins. I have verified to some extent the hardware, because I am able to toggle those LED pins by configuring them as standard GPIO outputs and driving them high to see the LEDs illuminate. Any suggestions or information would be greatly appreciated! I can provide more information upon request. Thanks! 

    This topic has been closed for replies.

    9 replies

    Graduate II
    March 25, 2025

    Would suggest showing code, especially pin and TIM initialization code.

    Ideally minimal/single function rather than CUBE spread it everywhere and obfuscated. Perhaps config TIM in lower frequency toggle mode rather than PWM

    Enumerate the pins in use.

    Perhaps inspect signals with a scope rather than LEDs / EYEs

    Dump RCC, GPIO and TIM registers related to implementation

    dlewisAuthor
    Visitor II
    April 1, 2025

    Hi, thanks for the reply! I'll add a couple more details and then get back to you with some simplified code to demonstrate the issue.

    We did use a scope to check the output pins for PWM signal and it also demonstrated that the drivers were not behaving in the expected way as well. 
    Here is the TIM3 auto generated INIT as an example of a PWM peripheral/timer that is working as expected

    /* TIM3 init function */
    void MX_TIM3_Init(void)
    {
     /* USER CODE BEGIN TIM3_Init 0 */
    
     /* USER CODE END TIM3_Init 0 */
    
     TIM_ClockConfigTypeDef sClockSourceConfig = {0};
     TIM_MasterConfigTypeDef sMasterConfig = {0};
     TIM_OC_InitTypeDef sConfigOC = {0};
    
     /* USER CODE BEGIN TIM3_Init 1 */
    
     /* USER CODE END TIM3_Init 1 */
     htim3.Instance = TIM3;
     htim3.Init.Prescaler = 3;
     htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim3.Init.Period = 1000;
     htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
     if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
     {
     Error_Handler();
     }
     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
     if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
     {
     Error_Handler();
     }
     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
     if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &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(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN TIM3_Init 2 */
    
     /* USER CODE END TIM3_Init 2 */
     HAL_TIM_MspPostInit(&htim3);
    }

    Below are the TIM13 and TIM14 generated INITs for the pwm instances that aren't working

    /* TIM13 init function */
    void MX_TIM13_Init(void)
    {
    
     /* USER CODE BEGIN TIM13_Init 0 */
    
     /* USER CODE END TIM13_Init 0 */
    
     TIM_OC_InitTypeDef sConfigOC = {0};
    
     /* USER CODE BEGIN TIM13_Init 1 */
    
     /* USER CODE END TIM13_Init 1 */
     htim13.Instance = TIM13;
     htim13.Init.Prescaler = 3;
     htim13.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim13.Init.Period = 1000;
     htim13.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim13.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
     if (HAL_TIM_Base_Init(&htim13) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_Init(&htim13) != 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(&htim13, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN TIM13_Init 2 */
    
     /* USER CODE END TIM13_Init 2 */
     HAL_TIM_MspPostInit(&htim13);
    
    }
    /* TIM14 init function */
    void MX_TIM14_Init(void)
    {
    
     /* USER CODE BEGIN TIM14_Init 0 */
    
     /* USER CODE END TIM14_Init 0 */
    
     TIM_OC_InitTypeDef sConfigOC = {0};
    
     /* USER CODE BEGIN TIM14_Init 1 */
    
     /* USER CODE END TIM14_Init 1 */
     htim14.Instance = TIM14;
     htim14.Init.Prescaler = 3;
     htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim14.Init.Period = 1000;
     htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
     if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_Init(&htim14) != 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(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN TIM14_Init 2 */
    
     /* USER CODE END TIM14_Init 2 */
     HAL_TIM_MspPostInit(&htim14);
    
    }

    Below are some functions being used to start PWM instances and update pulse widths. These functions work for all PWM instances not on TIM13 or TIM14 so far

    //Called directly after generated inits for each instance and channel
    void Pwm_Instance_Start(TIM_HandleTypeDef *htim, uint32_t channel)
    {
     HAL_TIM_PWM_Start(htim, channel);
    }
    
    //Called in Freertos tasks to update LED brightness. 
    //These calls are wrapped in mutexesto prevent faults
    void Update_Pwm_Duty_Cycle(uint16_t new_pulse_width, TIM_HandleTypeDef *htim, uint32_t channel)
    {
     TIM_OC_InitTypeDef sConfigOC = {0};
     sConfigOC.OCMode = TIM_OCMODE_PWM1;
     sConfigOC.Pulse = new_pulse_width;
     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    
    
     if (HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, channel) != HAL_OK)
     {
    	Error_Handler();
     }
    }


     Let me know what other information/code may be helpful as well!

    Super User
    April 1, 2025

    As @Tesla DeLorean said above, read out and post TIM and related GPIO and RCC registers content.

    JW

    dlewisAuthor
    Visitor II
    April 14, 2025

    Hi, apologies for the delayed response. Attached is a ZIP with photos of some of the register values I captured during some testing. Let me know if other specific registers at specific times would be useful to see.


    Super User
    April 14, 2025

    These look OK.

    Can you please check/post also the relevant GPIO registers content.

    JW

    dlewisAuthor
    Visitor II
    April 23, 2025

    Hi, apologies again for a late response. Here is the register values for GPIO port D.

    dlewis_0-1745434166789.png

     

    Super User
    April 28, 2025

    According to the STM32H562 datasheet, there is no TIM13 nor TIM14 pin at GPIOD.

    JW

    dlewisAuthor
    Visitor II
    April 29, 2025

    My apologies, I was looking at the port for the wrong PWM peripheral pin I was using. Here is the port values for GPIOA which should be the correct port.

    dlewis_0-1745949796380.png

     

    Technical Moderator
    April 30, 2025

    Hello @dlewis 

    In your configuration you missed to assign a value to pulse

    sConfigOC.Pulse = 0; // in your settings
    sConfigOC.Pulse = 20; // for example

     PWM signal frequency is determined by the value of the TIMx_ARR register and a duty cycle determined by the value of the TIMx_CCRx register. The later takes the value of pulse parameter. It must be non zero otherwise no signal outputs.

     /* Set the Capture Compare Register value */
     TIMx->CCR1 = OC_Config->Pulse;

    This is a test involving TIM13, TIM14 and TIM1 channel 1.

    CMYL_0-1746023727721.png

    Best Regards

    Younes

    dlewisAuthor
    Visitor II
    April 30, 2025

    Hi CMYL,

    In my project I have the pulse set to 0 initially, but it is updated during runtime when the application needs to use the PWM. I have confirmed that the pulse value is correctly being set, but I did not include register values showing that here. All of the 12 or so PWM signals I am using are set to 0 pulse by default and then updated as needed. In one of my comments or post above it should show the functions I created to update the pulse during runtime. This method works for 10 of the 12 PWMs but the 2 mentioned in the post title do not output anything even though the pulse is being set. 

    Technical Moderator
    April 30, 2025

    Thanks @dlewis 

    I will check according to pulse update function.

    Technical Moderator
    April 30, 2025

    Hi @dlewis 

    I started from 0 as pulse period as you suggested, then I changed the periods for TIM13 and TIM14 as follow in accordingly in the while(1).

     MX_GPIO_Init();
     MX_TIM13_Init();
     MX_TIM14_Init();
     /* USER CODE BEGIN 2 */
     HAL_TIM_PWM_Start(&htim13, TIM_CHANNEL_1);
     HAL_TIM_PWM_Start(&htim14, TIM_CHANNEL_1); 
     /* USER CODE END 2 */
     HAL_Delay(4000); /* no output signal as pulse = 0*/
     while (1)
     {
     period1 = (period1 + 100) % 900;
     sConfigOC.Pulse = period1;
     HAL_TIM_PWM_ConfigChannel(&htim13, &sConfigOC, TIM_CHANNEL_1);
    
     period2 = (period2 + 200)%900;
     sConfigOC.Pulse = period2;
     HAL_TIM_PWM_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1;
     
     HAL_Delay(3000); /* delay to follow changes*/
     } /* while 1*/
     /* USER CODE END 3 */
    }

     I can see that the wide of the pulse is changing using a logic analyzer. 

    CMYL_1-1746038326018.png

    Can you add the other timers and check if there is any issues?

    Best regards

     

    dlewisAuthor
    Visitor II
    May 14, 2025

    Hi @CMYL 

    I tried using a similar method to you by ignoring the rtos and manually controlling the PWM of TIM13 and TIM14 in the main while(). This successfully demonstrated PWM for the 2 problematic pins as visible on the connected RGBW LED on our pcb. This seems to be consistent to me with the fact that those 2 pins could be toggled as GPIO outputs to turn on the LEDs, but the issue still persists where those 2 pins alone do not output any PWM when being used in an application where all of the other PWM peripherals are also being used. 

    I am going to try manually adjusting the order of timer configurations and also give tim13 and tim14 an initial pulse length using the IOC gui to see if that makes a difference for some reason. 

    Any other advice or feedback would be appreciated! I can share more of my code if that would help debug as well. Thanks!

    ST Employee
    May 15, 2025

    Hello @dlewisI tested the PWM output of all five timers simultaneously using a Nucleo-H563, and everything appears to be functioning correctly on my end:

    SarraS_0-1747316010099.png

    When I tried using only TIM13 and TIM14 outputs, I encountered an issue where only the second timer initiated with HAL_TIM_PWM_Start was generating an output. However, rearranging the order of instructions—starting PWM TIM14 before TIM13—resolved the problem!

    SarraS_1-1747316700473.png

     

    then, when I reverted to the original order (starting TIM13 before TIM14) it continued to work, which is quite puzzling!

    It would be interesting if you could try this on your end! while I try to further investigate the order behavior. 

    Thank you

     

    dlewisAuthor
    Visitor II
    May 19, 2025

    Hi @Sarra.S 

    I tried rearranging the order of which HAL_TIM_PWM_Start is used for each instance/channel and this did not seem to make any difference in results for me.

    Super User
    May 20, 2025

    Hi @dlewis ,

    at this point, as it appears to be hard to reproduce the problem, you may want to prepare a minimal but complete compilable example exhibiting the problem, and post it together with the binary (.elf).

    JW