PWM (Pulse Width Mod) in STM32

Pulse Width Modulation is one of the important functions of timer. PWM is a technique to control analogue circuits with digital output from microcontroller.

As you all know that an Analogue signal is the one whose value varies continuously with time whereas digital signals can only be either high or low. PWM is used for generating an analogue signal using a digital source.

PWM consist of two main components:-
1.) Duty cycle
2.) Frequency

  • Duty cycle describes the amount of time, the signal is in HIGH state as a percentage of total time, it takes to complete one cycle.
  • Frequency describes how fast the PWM completes a cycle and therefore how fast it switches between HIGH and LOW.

By cycling a digital signal ON and OFF at a fast enough rate and at a certain duty cycle, the output will appear like a constant voltage analogue signal. For eg: To create a 2V signal from a digital source which is either HIGH(5V) or low (0). We can use PWM with duty cycle of 40% here. This 40% duty cycle would yield an average voltage of 5×0.4=2V.

Duty cycle of 25%

Duty cycle of 75%

CubeMX Setup

  • Note here that the APB2 Timer Clock is running at 72 MHz
  • We are going to use the Timer 1, and it is connected to APB2.
  • So the Timer 1 clock is also same as APB2 Timer clock, and that is 72 MHz

  • Select the PWM channel for the Timer
  • Set the Clock source as internal clock
  • Pin PA8 is set as the PWM output Pin

As I mentioned above that Timer 1 clock is at 72 MHz. Using the Prescalar of 72 will bring the clock down to 1 Mhz.

Further using the ARR of 100 will set the PWM Frequency = 10 KHz. This is shown in the image below

Why do we need to use -1 ?

This is the setup as per the registers in STM32. The Prescalar Register and the ARR Registers are setup in a way, that they add a 1 to the value.

So whatever value we enter for the PSC, 1 will be added to that value. This is why we enter 1 less than the actual value.

Some Insight into the Code

 TIM1->CCR1 = 30;
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  • Here we will set the value in the Capture Compare Register (CCR).
  • Since I am using Channel 1, the Register is CCR1.
  • And we will start the Timer in PWM mode

The value set in the CCR decides the width of the pulse. The formula to calculate the duty cycle is shown below


Duty cycle 30%, freq = 10 KHz

Check out the Video Below

You can buy me a coffee Sensor by clicking DONATE OR Just click DOWNLOAD to download the code

Notify of

Oldest Most Voted
Inline Feedbacks
View all comments

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add to your ad blocking whitelist or disable your adblocking software.