mirror of https://github.com/ARMmbed/mbed-os.git
[STM32F4] 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
parent
ce5ee179cd
commit
ab45ef0378
|
@ -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;
|
||||||
uint8_t channel;
|
uint8_t channel;
|
||||||
|
|
|
@ -94,6 +94,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
|
||||||
}
|
}
|
||||||
|
@ -121,7 +122,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;
|
||||||
|
@ -240,26 +241,45 @@ void pwmout_period_us(pwmout_t* obj, int us)
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimHandle.Init.Period = us - 1;
|
/* To make it simple, we use to possible prescaler values which lead to:
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
// TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx
|
// TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx
|
||||||
if (APBxCLKDivider == RCC_HCLK_DIV1)
|
if (APBxCLKDivider == RCC_HCLK_DIV1)
|
||||||
TimHandle.Init.Prescaler = (uint16_t)((PclkFreq) / 1000000) - 1; // 1 us tick
|
TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq) / 1000000) * obj->prescaler) - 1; // 1 us tick
|
||||||
else
|
else
|
||||||
TimHandle.Init.Prescaler = (uint16_t)((PclkFreq * 2) / 1000000) - 1; // 1 us tick
|
TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq * 2) / 1000000) * obj->prescaler) - 1; // 1 us tick
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
|
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
|
||||||
error("Cannot initialize PWM\n");
|
error("Cannot initialize PWM\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +296,7 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
|
||||||
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
|
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
|
||||||
{
|
{
|
||||||
float value = (float)us / (float)obj->period;
|
float value = (float)us / (float)obj->period;
|
||||||
|
printf("pwmout_pulsewidth_us: period=%d, us=%d, dc=%d%%\r\n", obj->period, us, (int) (value*100));
|
||||||
pwmout_write(obj, value);
|
pwmout_write(obj, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue