Skip to content

Commit 6dc9501

Browse files
author
Laurent MEUNIER
committed
[STM32L4] 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 6eab29c commit 6dc9501

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

hal/targets/hal/TARGET_STM/TARGET_STM32L4/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_STM32L4/pwmout_api.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
7777
obj->pin = pin;
7878
obj->period = 0;
7979
obj->pulse = 0;
80+
obj->prescaler = 1;
8081

8182
pwmout_period_us(obj, 20000); // 20 ms per default
8283
}
@@ -104,7 +105,7 @@ void pwmout_write(pwmout_t* obj, float value)
104105

105106
// Configure channels
106107
sConfig.OCMode = TIM_OCMODE_PWM1;
107-
sConfig.Pulse = obj->pulse;
108+
sConfig.Pulse = obj->pulse / obj->prescaler;
108109
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
109110
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
110111
sConfig.OCFastMode = TIM_OCFAST_ENABLE;
@@ -168,22 +169,39 @@ void pwmout_period_us(pwmout_t* obj, int us)
168169

169170
SystemCoreClockUpdate();
170171

171-
TimHandle.Init.Period = us - 1;
172-
TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
173-
TimHandle.Init.ClockDivision = 0;
174-
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
175-
TimHandle.Init.RepetitionCounter = 0;
172+
/* To make it simple, we use to possible prescaler values which lead to:
173+
* pwm unit = 1us, period/pulse can be from 1us to 65535us
174+
* or
175+
* pwm unit = 500us, period/pulse can be from 500us to ~32.76sec
176+
* Be careful that all the channels of a PWM shares the same prescaler
177+
*/
178+
if (us > 0xFFFF) {
179+
obj->prescaler = 500;
180+
} else {
181+
obj->prescaler = 1;
182+
}
183+
TimHandle.Init.Prescaler = ((SystemCoreClock / 1000000) * obj->prescaler) - 1;
184+
185+
if (TimHandle.Init.Prescaler > 0xFFFF)
186+
error("PWM: out of range prescaler");
187+
188+
TimHandle.Init.Period = (us - 1) / obj->prescaler;
189+
if (TimHandle.Init.Period > 0xFFFF)
190+
error("PWM: out of range period");
191+
192+
TimHandle.Init.ClockDivision = 0;
193+
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
176194

177195
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
178196
error("Cannot initialize PWM\n");
179197
}
180198

181-
// Set duty cycle again
182-
pwmout_write(obj, dc);
183-
184199
// Save for future use
185200
obj->period = us;
186201

202+
// Set duty cycle again
203+
pwmout_write(obj, dc);
204+
187205
__HAL_TIM_ENABLE(&TimHandle);
188206
}
189207

0 commit comments

Comments
 (0)