cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 PWM with variable Frequency

Paul STM32_
Associate
Posted on March 19, 2018 at 11:34

Hi at all,

I am working since some days with STM32 ( + HAL, CubeMX), because I need a Source for a PMW with variable Frequency, where f = 20..200kHz and Duty Cycle 0..100%.

To realize this I started with a regular PWM with a fixed Period. That worked fine.

Example:

int main(void) {

..

Misc...Init

...

MX_TIM2_Init(200); // where 200 is  htim2.Init.Period

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);

__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 100);

}

void MX_TIM2_Init(int period) {

...

}

however when I change the period, then I have to follow the steps:

 HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_1);  // Stop PWM

 MX_TIM2_Init(40);  // re-initialize the Timer2

 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); // Start PWM again

 __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 20); // Set Duty Cuyle

it worked too, but it is slow and needed ca. 1000us. I need a method to switch faster (~100us). There are a lot of tricky ways to use the Timer in STM32, but I am not experienced enough to find the right way.

Can you give me a hint, what could be the most promising way to generate a PWM with a varibale Frequency and a fast way to switch (<100us)  the Frequency?

thanks in advance

Paul

4 REPLIES 4
henry.dick
Senior II
Posted on March 19, 2018 at 13:51

Use ARR to change period, and CCRn to change duty cycle.

See the data sheet.

Paul STM32_
Associate
Posted on March 20, 2018 at 09:55

Thanks to dhenry, I did it with

TIM2->ARR = <value>; // Period

TIM2->CCR1 = <othervalue>; // guess CCR1 means Channel 1, Duty Cycle

it worked, however sometimes it was unpredictable. I guess, when I set CCR1 to a smaller value as CCR1 before and the current counter is larger than the new value of CCR1, the counter runs at its end (32bit) and than it follows the new CCR1 value.

So I came back to my original configuration and I found a mistake in my measurements. I forgot to subtract the runtime of my loop in which i let run my Timer Configuration. Now I found a really good time < 10us. STM32F411 (100MHz)  seems to be fast. :D

best regards, STM32_

Posted on March 20, 2018 at 11:16

'

however sometimes it was unpredictable.'

set the timer to up/down mode.

Posted on March 20, 2018 at 11:17

Thanks to dhenry, I did it with

TIM2->ARR = <value>; // Period

TIM2->CCR1 = <othervalue>; //

guess CCR1 means Channel 1, Duty Cycle

It means Capture-Compare Register, chanel 1. For PWM output modes, it may mean duty.

it worked, however sometimes it was unpredictable. I guess, when I set CCR1 to a smaller value as CCR1

before and the current counter is larger than the new value of CCR1, the counter runs at its end (32bit) and than it follows the new CCR1 value.

This is why you should use register shadowing, both for the CCRx and ARR. Please read the timer chaper in Reference Manual.

JW