I have set up stm32 timer to work as PWM to control the servo drive. The control code looks like this:
static void setServo(uint8_t value) {
const uint16_t timerValue = servoToTimerValue(value);
TIM21->CCR1 = timerValue;
}
static const uint16_t s_minServoTimerValue = 258;
static uint16_t servoToTimerValue(uint8_t value) {
return s_minServoTimerValue + value;
}
The concern I have is when I change the CCR1
value there might be a situation when the PWM won't detect the match because it is already skipped the new value but have not reached the old value.
Consider following scenario:
- compare register
CCR1
= 500 - counter register is at
CNT
= 400 - the new compare register would be
CCR1
= 300
The timer won't find a match in this cycle and will result in 100% duty cycle this iteration. How to I avoid it? Is it a legit concern at all?
I have come up with the following logic to mitigate this case:
static void setServo(uint8_t value) {
const uint16_t timerValue = servoToTimerValue(value);
if ((timerValue <= TIM21->CNT) && (TIM21->CNT > TIM21->CCR1)) {
GPIOA->BRR = GPIO_PIN_2;
}
TIM21->CCR1 = timerValue;
}
What would be the proper way to reset PWM's channel pin?
My setup is following:
- Fcpu = 16 MHz
- Timer prescaler = 62 => Timer frequency 258 kHz
- Timer period = 5160 ticks ~> 20 ms
- Timer match is within range 258-516 ticks ~> 1-2 ms
MCU: stm32l011f4