How to use PWM in STM32F103C8T6? STM32 PWM Tutorial

This article will demonstrate how to use PWM on the STM32F103C8T6 MCU-based STM32 Blue Pill Board. We will regulate the speed of a small 5V DC Fan using Pulse Width Modulation (PWM) in the STM32 MCU. PWM can also be used to adjust the brightness of an LED.

Here, there have been numerous PWM-related projects. We are aware that all microcontrollers operate in the digital realm and that direct access to or production of analog signals is not possible. PWM, or Pulse Width Modulation, is a method for generating analog signals through digital means.

This is accomplished by cycling a digital Output pin between HIGH and LOW at a specific frequency to generate a square wave. However, this pure square wave is useless. To take advantage of the digital controls, the HIGH and LOW times of the square wave can be varied within a fixed time period.

By adjusting the width of the ON and OFF periods of the square wave, it is possible to replicate voltages between 0 V and 1 V. (5 V or 3.3 V). The duration of the pulse’s ON time is known as the Pulse Width or simply Pulse Width. This approach is known as Pulse Width Modulation since we are altering or “modulating” this width.

The ratio of the ON time to the overall Time Period of a single Pulse is referred to as the PWM Signal’s Duty Cycle.

Duty Cycle = ON Time / (ON Time + OFF Time)

Both the ON and OFF times for a signal with a 50 percent duty cycle are equal. Consequently, the output is a square wave with an average voltage of 2.5 V. (if VDD is 5V). If the duty cycle is increased to 100 percent, the maximum ON duration is reached (i.e. the ON pulse occupies the whole length of the pulse). As a result, the signal outputs a full 5V.

By regulating the duty cycle, accurate voltage levels may be generated at the output of the PWM signal, which can then be used to regulate the speed of a Motor, modify the brightness of an LED, fix the position of a Servo Motor, and many other things.

PWM in STM32F103C8T6

 STM32 Blue Pill board includes 15 PWM-capable pins. The STM32F103C8T6 PWM has a 16-bit resolution, hence the maximum counter value is 216, which is equal to 65535.

Therefore, if the counter value is set to 65535, a 100 percent duty cycle can be achieved. When an LED and a DC Fan are linked, both the LED’s brightness and the fan’s speed are at their maximum.

For a duty cycle of 50 percent, the counter value must be set to 32767. This will result in a reduction of half the maximum brightness and speed.

The figure below depicts the PWM Signal for various Duty Cycles and the counter values that must be recorded in Arduino’s analogWrite function.

Components Required

  • STM32F103C8T6 MCU based STM32 Blue Pill
  • 5V DC Motor
  • LED
  • 10KΩ Potentiometer
  • 220Ω Resistor
  • ULN2003
  • Connecting wires
  • USB to UART Converter (if programming through UART)
  • 16×2 LCD Display (Optional)
  • 10KΩ Potentiometer (Optional)

What is PWM (Pulse with Modulation)?

Pulse-width modulation (PWM)  is a modulation procedure or technique used in most communication systems to encode the amplitude of a signal into the pulse width or length of another signal, usually a carrier signal, for transmission. Although PWM is employed in communications, its primary function is to control the power provided to various types of electrical equipment, particularly inertial loads like AC/DC motors.


STM32F103C8T6 Discovery Board was designed as a development board that is similar to Arduino in terms of advanced capabilities and accessibility. The STM32 Discovery Board enables the development of high-reliability applications by utilizing an advanced performance microcontroller known as the Arm Cortex-M4 32-bit core. I think you’re familiar with ARM Architecture. It provides versatility and customization, allowing you to experiment with libraries, communication protocols, GPIO pins, and so on.

Circuit Diagram

The following image shows the circuit diagram of the project.

How to use PWM in STM32F103C8T6 Circuit Diagram

Connections Explained

Since we must regulate the speed of a DC Motor, which is a high-current device, we should not connect the Motor directly to the STM32 MCU, but rather via a Motor Driver. You can utilize Motor Driver ICs such as L293D or L298N, but we can also use the Darlington Array IC ULN2003.

The limitation of driving a Motor with a ULN2003 IC is that the direction of rotation cannot be reversed. Pins 1 to 7 are Inputs (IN1 to IN7), and Pins 10 to 16 are Outputs (OUT7 through OUT1).

Since only one motor is being controlled, the motor’s negative terminal is linked to the OUT1 Pin, while the IN1 Pin is connected to PWM Pin PA8. The motor’s positive terminal is connected to an external 5V power source.

The anode of the LED is connected to another PWM Pin PA9, while the cathode is connected to GND via a 220 resistor in series.

A 10K POT is connected to ADC Pin PA0 in order to adjust the analog voltage input, which is then transformed to PWM Signal. The remaining two POT terminals are wired to 3.3V and GND.

A 16×2 LCD Display can be used to display the ADC and Duty Cycle Value values. If you have followed my tutorial on interfacing a 16×2 LCD with the STM32F103C8T6 chip, you can easily implement this.

Programming STM32 Blue Pill for PWM

First, the pins PA0, PA8, and PA9 are respectively set to POT, Motor PWM, and LED PWM. Initialize the pins as INPUTS and OUTPUTS according to their function, such that the POT pin is an INPUTS while the Motor Pin and LED Pin are OUTPUTS.

Now, retrieve the value of the potentiometer using the analogRead ADC function. This value should be stored in a variable. Using a second variable, map the ADC range of 0 to 4095 to the PWM Duty Cycle Range of 0 to 65535. This will ensure that the PWM signals have a complete voltage range.

Using the analogWrite function, generate PWM signals for both the LED and the Motor with the mapped value as the duty cycle value.


const int potPIN = PA0;

const int ledPIN = PA9;

const int motorPIN = PA8;

void setup()


pinMode(potPIN, INPUT);

pinMode(ledPIN, OUTPUT);

pinMode(motorPIN, OUTPUT);


void loop()


int adcValue = analogRead(potPIN);

int dutyCycle = map(adcValue, 0, 4095, 0, 65535);

analogWrite(ledPIN, dutyCycle);

analogWrite(motorPIN, dutyCycle);



Hope this blog helps you to understand how to use PWM (Pulse Width Modulation) in the STM32 (STM32F103C) microcontroller. We, MATHA ELECTRONICS  will come back with more informative blogs.

Leave a Reply

Your email address will not be published.