[STM32F1] 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.
pull/2103/head
Laurent MEUNIER 2016-06-29 11:00:20 +02:00
parent 00e51f4fe2
commit ce5ee179cd
2 changed files with 27 additions and 6 deletions

View File

@ -42,6 +42,7 @@ extern "C" {
struct pwmout_s { struct pwmout_s {
PWMName pwm; PWMName pwm;
PinName pin; PinName pin;
uint32_t prescaler;
uint32_t period; uint32_t period;
uint32_t pulse; uint32_t pulse;
}; };

View File

@ -58,6 +58,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
obj->pin = pin; obj->pin = pin;
obj->period = 0; obj->period = 0;
obj->pulse = 0; obj->pulse = 0;
obj->prescaler = 1;
pwmout_period_us(obj, 20000); // 20 ms per default pwmout_period_us(obj, 20000); // 20 ms per default
} }
@ -86,7 +87,7 @@ void pwmout_write(pwmout_t* obj, float value)
// Configure channels // Configure channels
sConfig.OCMode = TIM_OCMODE_PWM1; sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.Pulse = obj->pulse; sConfig.Pulse = obj->pulse / obj->prescaler;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH; sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE; sConfig.OCFastMode = TIM_OCFAST_DISABLE;
@ -193,18 +194,37 @@ void pwmout_period_us(pwmout_t* obj, int us)
// Update the SystemCoreClock variable // Update the SystemCoreClock variable
SystemCoreClockUpdate(); SystemCoreClockUpdate();
TimHandle.Init.Period = us - 1; /* To make it simple, we use to possible prescaler values which lead to:
TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 us tick * pwm unit = 1us, period/pulse can be from 1us to 65535us
* or
* pwm unit = 500us, period/pulse can be from 500us to ~32.76sec
* Be careful that all the channels of a PWM shares the same prescaler
*/
if (us > 0xFFFF) {
obj->prescaler = 500;
} else {
obj->prescaler = 1;
}
TimHandle.Init.Prescaler = ((SystemCoreClock / 1000000) * obj->prescaler) - 1;
if (TimHandle.Init.Prescaler > 0xFFFF)
error("PWM: out of range prescaler");
TimHandle.Init.Period = (us - 1) / obj->prescaler;
if (TimHandle.Init.Period > 0xFFFF)
error("PWM: out of range period");
TimHandle.Init.ClockDivision = 0; TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&TimHandle); HAL_TIM_PWM_Init(&TimHandle);
// Set duty cycle again
pwmout_write(obj, dc);
// Save for future use // Save for future use
obj->period = us; obj->period = us;
// Set duty cycle again
pwmout_write(obj, dc);
__HAL_TIM_ENABLE(&TimHandle); __HAL_TIM_ENABLE(&TimHandle);
} }