cancel
Showing results for 
Search instead for 
Did you mean: 

TIM2 PWM Output goes to zero unexpectedly

Eric5
Associate

I am using the STM32F207ZG MCU, and I started a new project in STM32CubeIDE. I wrote the following code, which changes the state of TIM2 PWM output CH1:

 

 /* USER CODE BEGIN 2 */

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);


  TIM2->ARR = 48000;
  TIM2->CCR1 = 16000;

  HAL_Delay(3000);

  TIM2->CCR1 = 3200;

  HAL_Delay(3000);

  TIM2->ARR = 8000;


  /* USER CODE END 2 */

 

 

I expected the last line (TIM2->ARR = 8000) affect the period of the PWM output but not change the pulse width. However, after the last line executes, the PWM output goes to zero on my oscilloscope. Is this expected behavior?

If I use TIM3, the behavior is as I would expect.

 

Below are some screenshots of my configuration in the .ioc file:

Eric5_0-1724102789980.png

Eric5_1-1724102821067.png

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Lead III

Set the timer clock source to Internal clock. Set the preload option for ARR and timer channel. Set the initial period to the desired value in timer config tab, before starting the timer. Note that TIM2 is a 32-bit timer, so its initial period is over 4 billion ticks.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

View solution in original post

2 REPLIES 2
gbm
Lead III

Set the timer clock source to Internal clock. Set the preload option for ARR and timer channel. Set the initial period to the desired value in timer config tab, before starting the timer. Note that TIM2 is a 32-bit timer, so its initial period is over 4 billion ticks.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Thanks gbm. Your solution worked for me.

 

Specifically, setting the preload enable for ARR fixed the issue.

 

For anyone seeing a similar issue in the future, here's an explanation of why the output for the 32-bit timer was "going to zero":

 

Without the preload option enabled, updates to ARR take place immediately. In the example code that I posted, I was changing TIM2->ARR from 48000 to 8000. When doing this, there is a 5/6 chance that the CNT value of TIM2 (that is, the timer's counter) is greater than 8000. If that's the case, then when ARR is set to 8000, and CNT exceeds 8000, the timer will continue counting upwards until it overflows back to zero, which takes 4 minutes 28 seconds for a 32-bit timer with a clock source of 16 MHz. (2^32 / 16000000 seconds). CNT is reset to 0 whenever CNT = ARR, so updates to ARR must ensure that we never have CNT > (new ARR value being written), otherwise you'd need to wait for CNT to overflow before the timer starts working again. Enabling ARR preload ensures that you never run into CNT > ARR.

 

The reason I did not see the issue on the 16-bit timer is because it only takes the 16-bit CNT value 4 milliseconds to overflow, and so there would have been a period of 4ms where the output of that timer was constantly zero.