Skip to content

Commit 0cdcb9b

Browse files
author
Laurent MEUNIER
committed
[STM32F7] 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 ab45ef0 commit 0cdcb9b

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

hal/targets/hal/TARGET_STM/TARGET_STM32F7/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
uint8_t channel;

hal/targets/hal/TARGET_STM/TARGET_STM32F7/pwmout_api.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
6969
obj->pin = pin;
7070
obj->period = 0;
7171
obj->pulse = 0;
72+
obj->prescaler = 1;
7273

7374
pwmout_period_us(obj, 20000); // 20 ms per default
7475
}
@@ -96,7 +97,7 @@ void pwmout_write(pwmout_t* obj, float value)
9697

9798
// Configure channels
9899
sConfig.OCMode = TIM_OCMODE_PWM1;
99-
sConfig.Pulse = obj->pulse;
100+
sConfig.Pulse = obj->pulse / obj->prescaler;
100101
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
101102
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
102103
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
@@ -192,25 +193,44 @@ void pwmout_period_us(pwmout_t* obj, int us)
192193
return;
193194
}
194195

195-
TimHandle.Init.Period = us - 1;
196+
/* To make it simple, we use to possible prescaler values which lead to:
197+
* pwm unit = 1us, period/pulse can be from 1us to 65535us
198+
* or
199+
* pwm unit = 500us, period/pulse can be from 500us to ~32.76sec
200+
* Be careful that all the channels of a PWM shares the same prescaler
201+
*/
202+
if (us > 0xFFFF) {
203+
obj->prescaler = 500;
204+
} else {
205+
obj->prescaler = 1;
206+
}
207+
196208
// TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx
197209
if (APBxCLKDivider == RCC_HCLK_DIV1)
198-
TimHandle.Init.Prescaler = (uint16_t)((PclkFreq) / 1000000) - 1; // 1 µs tick
210+
TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq) / 1000000) * obj->prescaler) - 1; // 1 us tick
199211
else
200-
TimHandle.Init.Prescaler = (uint16_t)((PclkFreq * 2) / 1000000) - 1; // 1 µs tick
212+
TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq * 2) / 1000000) * obj->prescaler) - 1; // 1 us tick
213+
214+
if (TimHandle.Init.Prescaler > 0xFFFF)
215+
error("PWM: out of range prescaler");
216+
217+
TimHandle.Init.Period = (us - 1) / obj->prescaler;
218+
if (TimHandle.Init.Period > 0xFFFF)
219+
error("PWM: out of range period");
220+
201221
TimHandle.Init.ClockDivision = 0;
202222
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
203223

204224
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
205225
error("Cannot initialize PWM\n");
206226
}
207227

208-
// Set duty cycle again
209-
pwmout_write(obj, dc);
210-
211228
// Save for future use
212229
obj->period = us;
213230

231+
// Set duty cycle again
232+
pwmout_write(obj, dc);
233+
214234
__HAL_TIM_ENABLE(&TimHandle);
215235
}
216236

0 commit comments

Comments
 (0)