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

  • \$\begingroup\$ Another way is to defer the CCR1 update until an interrupt occurs when the compare happens. SetServo updates a "New_CCR1" variable and enables the interrupt. \$\endgroup\$
    – user16324
    Feb 6, 2020 at 14:35
  • \$\begingroup\$ @BrianDrummond I was thinking about it. But I was hoping there would be a way without interrupts. \$\endgroup\$
    – Teivaz
    Feb 6, 2020 at 14:37

1 Answer 1


The solution is to update the value synchronously instead of at random time. Perhaps in the overflow interrupt, if no other way is available. You don't say which STM32 you use, but some models have timers that have a preload feature which latch in the actual count from the register when counter starts a new cycle, you should fix your issue by enabling preload mode.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.