Skip to content

Commit 00e51f4

Browse files
author
Laurent MEUNIER
committed
[STM32F0] Handle higher range pwm periods
As first reported on STM32F3 family in #1682, we need to cope with periods in the seconds range as well. This is fixed here in the same way as was done for STM32F3 by using the pre-scaler.
1 parent 7dc0ce3 commit 00e51f4

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

hal/targets/hal/TARGET_STM/TARGET_STM32F0/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ extern "C" {
4242
struct pwmout_s {
4343
PWMName pwm;
4444
PinName pin;
45+
uint32_t prescaler;
4546
uint32_t period;
4647
uint32_t pulse;
4748
};

hal/targets/hal/TARGET_STM/TARGET_STM32F0/pwmout_api.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
7575
obj->pin = pin;
7676
obj->period = 0;
7777
obj->pulse = 0;
78+
obj->prescaler = 1;
7879

7980
pwmout_period_us(obj, 20000); // 20 ms per default
8081
}
@@ -101,7 +102,7 @@ void pwmout_write(pwmout_t* obj, float value) {
101102

102103
// Configure channels
103104
sConfig.OCMode = TIM_OCMODE_PWM1;
104-
sConfig.Pulse = obj->pulse;
105+
sConfig.Pulse = obj->pulse / obj->prescaler;
105106
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
106107
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
107108
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
@@ -265,18 +266,39 @@ void pwmout_period_us(pwmout_t* obj, int us) {
265266
// Update the SystemCoreClock variable
266267
SystemCoreClockUpdate();
267268

268-
TimHandle.Init.Period = us - 1;
269-
TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
269+
/* To make it simple, we use to possible prescaler values which lead to:
270+
* pwm unit = 1us, period/pulse can be from 1us to 65535us
271+
* or
272+
* pwm unit = 500us, period/pulse can be from 500us to ~32.76sec
273+
* Be careful that all the channels of a PWM shares the same prescaler
274+
*/
275+
if (us > 0xFFFF) {
276+
obj->prescaler = 500;
277+
} else {
278+
obj->prescaler = 1;
279+
}
280+
TimHandle.Init.Prescaler = ((SystemCoreClock / 1000000) * obj->prescaler) - 1;
281+
282+
if (TimHandle.Init.Prescaler > 0xFFFF)
283+
error("PWM: out of range prescaler");
284+
285+
TimHandle.Init.Period = (us - 1) / obj->prescaler;
286+
if (TimHandle.Init.Period > 0xFFFF)
287+
error("PWM: out of range period");
288+
270289
TimHandle.Init.ClockDivision = 0;
271290
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
272-
HAL_TIM_PWM_Init(&TimHandle);
273291

274-
// Set duty cycle again
275-
pwmout_write(obj, dc);
292+
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
293+
error("Cannot initialize PWM");
294+
}
276295

277296
// Save for future use
278297
obj->period = us;
279298

299+
// Set duty cycle again
300+
pwmout_write(obj, dc);
301+
280302
__HAL_TIM_ENABLE(&TimHandle);
281303
}
282304

0 commit comments

Comments
 (0)