* : 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
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.