16-bit PWM resolution example (4 lines of code)

Post your cool example code here.
Post Reply
AndrewBCN
Posts: 105
Joined: Sun Apr 25, 2021 3:50 pm
Answers: 1
Location: Strasbourg, France

16-bit PWM resolution example (4 lines of code)

Post by AndrewBCN »

As we all know, for backward compatibility with AVR MCU's, the default resolution for PWM output in STM32 Core is 8-bits, this provides a "granularity" of 1/256 = approx. 0.4%. However, since STM32 MCUs in general implement a number of 16-bit timers, we have the option of setting the PWM resolution to a maximum of 16 bits, providing a "granularity" of not quite*, but almost 1/65536 = approx. 0.0015%. Depending on the application this can be very desirable, and it is rather easy to obtain thanks to the excellent STM32 Wire library.
* : see explanation below

The following example uses Timer 4 Channel 4 on an STM32F411CEU6 MCU to generate a 2kHz PWM signal with 16-bit resolution, and all it takes is 4 lines of code.

Code: Select all

  // generate a test 2kHz square wave on PB9 PWM pin, using Timer 4 channel 4
  // PB9 is Timer 4 Channel 4 from Arduino_Core_STM32/variants/STM32F4xx/F411C(C-E)(U-Y)/PeripheralPins_BLACKPILL_F411CE.c
  analogWrite(PB9, 127);      // configures PB9 as PWM output pin at default frequency (1kHz) and resolution (8 bits), 50% duty cycle
  analogWriteFrequency(2000); // default PWM frequency is 1kHz, change it to 2kHz
  analogWriteResolution(16);  // set PWM resolution to 16 bits, default is 8 bits
  analogWrite(PB9, 32767);    // 32767 for 16 bits -> 50% duty cycle so a square wave
A comment on the granularity or real resolution of our PWM output

Now, about the exact "granularity", it is in fact limited by the values in the TIMx->ARR (frequency) and TIMx-> CCRy (duty cycle) registers for the timer x, channel y used.

If we read the register values for the example above, we get:
TIM4->ARR = 48000-1 (because 2kHz = 96MHz / 48000)
and
TIM4->CCR4 = 32767 x 48000/65536 (truncated to the nearest integer, I suppose).

So for these register values in the example above, the real "granularity" is not 1/65536 but somewhat higher 1/48000.
Post Reply

Return to “Code snippets”