This tutorial is about how to generate pwm (pulse width modulation) signal with stm32f103 microcontroller using its internal hardware timers. The initialization code of the Stm32f103 microcontroller components/peripherals is generated using the stmcubemx ide and the code is written and compiled in the MDK-ARMv6 keil ide. A simple LED is derived from a fixed PWM signal output. The LED dims and blinks according to the duty cycle and frequency that a particular PWM pin is outputting. A single PWM signal is generated/output in the tutorial, but you can generate multiple PWM signals with the same method and settings.
I will output a pwm (pulse width modulation) signal of 1 Hz frequency and 50% duty cycle using timer-4 of the stm32f103 microcontroller. Timer-4 channel-1 is used to output the signal. Channel 1 corresponds to pin PB6 of the stm32f103 microcontroller. An LED is connected to PB6 where the pwm output can be seen. The frequency of 1 Hz in the time domain is T=1/f > T=1/1 Hz > T=1 s. So the frequency of 1 Hz translates to 1 if my duty cycle is 50%, so the led on pin PB6 will blink at a rate of half a second.
How to generate desired/specific PWM frequency? Derivation of formulas and calculations.
Timer tick frequency The timer tick frequency is the frequency at which the timer completes its instruction cycle.
Counter frequency Counter Frequency is the frequency at which we want our timer tick counter to increase.
|
Stm32f103 Pwm (Pulse Width Modulation) Frequency Calculation Formula
|
PWM Resolution
|
Stm32f103 pwm formula for Prescaller value
|
Replacing the counter frequency with its formula in the timer prescaler value equations produces the equation given on the left side. It is now easy to determine the prescaler value.
|
Stmcube-Mx code initialization steps and MDK-ARM keil code generation
I assume you are familiar with the process of creating the stmcube mx project and know the necessary steps. If not, make a simple tutorial
- Introduction to stmcube-mx keil MDK-ARM v5

Timers 3 and 4 are independent and do not collide with any other peripheral functions. So it's good to use them. I'm using Timer 4 in the project/tutorial.
I'm using the internal clock source, so select this checkbox in the timer settings. I am using timer 4, channel 1 for pwm output, so I selected channel 1. Channel 1 corresponds to PB6 of stm32f103 microcontroller. The settings diagram is provided on the right side.

Calculation of values for 1 Hz frequency and 50% duty cycle pwm signal output
In the final timer settings, it is time to enter the Counter Period/Pwm Resolution (Steps), the Prescaler value and the required Pulse. Pulse is the required duty cycle and in our case it is 50%. Let's solve the upper formula according to the pwm calculation formula given above.
Values given:
Timer input clock = 0.0625 MHz or 62500 Hz
Required frequency = 1 Hz (in time domain 1 second)
Counter period/Pwm resolution (steps) = 3906 (I chose a random value)
Counter frequency = required frequency * Counter period
Counter frequency = 1 Hz * 3906 = 3906 Hz
Timer prescaler value = (timer input clock/counter frequency)-1
Timer prescaler value = (62,500 Hz / 3,906 Hz) – 1 = 15
Now we have the Presaller Timer value, Counter Period/Pwm Resolution (Steps) and they are also in the 16-bit range. Now enter the values into timer setting 4. I selected the counter to be in UP mode (counting from 0 to 3906). Pulse is the duty cycle, in our case it is 50%, so 3906*50% > 3906*0.5 = 1953.


