STM32 PWM output


This paper will introduce the output PWM through the timer of STM32. If you are not familiar with the timer, you can see the previous article《Detailed explanation of STM32 basic timer》, the basic functions of the timer will not be explained in detail.

01. Introduction to PWM

Definition of PWM: pulse width modulation (PWM) is referred to as pulse width modulation for short. Generally speaking, PWM is a digital coding method for analog signal level. Through the use of high-resolution counter, the duty cycle of square wave is modulated to encode the level of a specific analog signal. The PWM signal is still digital because at any given time, the full amplitude DC power supply is either fully on or completely off. The voltage or current source is added to the analog load in a repetitive pulse sequence of on or off. When the DC power supply is connected, it is added to the load, and when it is disconnected, it is disconnected. Any analog value can be encoded using PWM as long as the bandwidth is sufficient.

Duty cycle definition: duty cycle is the time of high level occupying the whole cycle, as shown in the figure below:

The first PWM wave has a period of 10ms and a high-level time of 4ms, so the duty cycle is 40%. Similarly, the second PWM wave is 60% and the third PWM wave is 80%.

PWM frequency:   The PWM frequency is the reciprocal of the whole cycle, so the PWM cycle in the above figure is 1 / 0.01, that is, 100Hz. Changing the frequency of PWM is realized by changing the whole cycle. Therefore, by changing the total time of high and low levels and the proportion of high levels in the total cycle, PWM waves with any frequency and any duty cycle can be realized.

Uses and advantages of PWM: motor speed regulation, power modulation, PID regulation, communication, etc. it has simple configuration and strong anti-interference ability. The signals from the processor to the controlled system are in digital form without digital to analog conversion. And keeping the signal in digital form can minimize the impact of noise. Only when the noise is strong enough to change logic 1 to logic 0 or logic 0 to logic 1, can it affect the digital signal, which is the main reason why PWM is used for communication.

02. Pin reuse of stm32

STM32 has no special PWM pin, so it uses the multiplexing mode of IO port. First confirm the output pin of PWM function and use timer 9. It can be seen from the following block diagram that timer9 has only two output channels, so timer9 can only output two PWM channels.

In the alternate function mapping picture in the stm32f207 data manual, the two channels of timer9 can be multiplexed into pa2, PA3, pe5 and pE6 respectively.

03. STM32 output PWM principle

Part ① in the figure below, in《Detailed explanation of STM32 basic timer》As explained, the shadow register is also《STM32 shadow register》It will not be repeated below. This paper will focus on the explanation of acquisition / comparison channel in part ②, in which the PWM of STM32 is realized by comparison channel.

Pulse Width Modulation mode allows you to generate a signal with afrequency determined by the value of the TIMx_ARR register and a dutycycle determined by the value of the TIMx_CCRx register。

Excerpt from stm32f207 reference manual

The pulse width modulation mode can generate a signal whose frequency is determined by timx_ ARR   The register value determines its duty cycle, which is determined by timx_ CCRx   Determined by register value.

As can be seen from the figure below, when the values of CCR register and CNT counter are the same, action will be generated (change the GPIO level corresponding to the channel). When CNT overflows, the overload value is controlled by timx_ Determined by the value of the ARR register. So timx_ The ARR register value determines the cycle, while timx_ The ccrx register value determines how long the CNT overflow will take action (change the GPIO level corresponding to the channel), that is, determines the duty cycle.

Take the up count as an example. The overload value is arr and the comparison value is crrx

As can be seen from the above figure:

  1. Segment 0-t1, timer counter timx_ CNT value is less than ccrx value, output low level.

  2. T1-T2 segment, timer counter timx_ When CNT value is greater than ccrx value, high level is output.

When timx_ When the CNT value reaches arr, the timer overflows and counts up again… This process is completed in this PWM cycle.

The figure above illustrates more vividly

  1. The signal frequency is determined by   TIMx_ ARR   Determined by register value.

  2. The duty cycle is determined by   TIMx_ CCRx   Determined by register value.

STM32 output PWM process:

1. First, configure GPIO and timer. Refer to the code for details. Refer to detailed explanation of STM32 basic timer for timer configuration.

2. Capture / compare channel enables the compare channel.

As shown in the figure above, ① the register name is: capture / compare1register. You can choose to input capture from ② or output from ③, that is, the PWM output function we need. Select capture channel or comparison channel. No specific description is found in the block diagram, but in timx_ The control bit of ccmr1 register cc1s [1:0] is enabled.

3. After enabling the output, it is necessary to configure the PWM output

①TIMx_ Oc1m [2:0] bit of ccmr1 register sets the output mode controller

110: PWM mode 1111: PWM mode 2.

② Counter value timx_ The CNT compares with the channel 1 capture comparison register CCR1, and outputs the effective level and invalid level through the comparison result.

OC1REF=0   Invalid level, oc1ref = 1 invalid level.

③ The signal generated by the output mode controller. TIMx_ The cc1p bit of the CCER register sets the input / capture channel 1 output polarity.

0: active at high level, 1: active at low level.

④TIMx_ CCER: cc1e bit controls the output enable circuit, and the signal is output to the corresponding pin.

0: off, 1: on.

First, PWM mode 1 and PWM mode 2 are introduced:

Mode 1

When counting up, once timx_ CNTTIMx_ When CCR1, channel 1 is invalid level (oc1ref = 0), otherwise it is effective level (oc1ref = 1).

Mode 2

When counting up, once timx_ CNTTIMx_ When CCR1, channel 1 is the effective level, otherwise it is the invalid level.

TIMx_ CNT>TIMx_ When CCR1, channel 1 is the effective level, otherwise it is the invalid level.

PWM output high and low levels are controlled by timx_ Ccmr1: oc1m bit and timx_ CCER: determined by cc1p bit.

To sum up:

Mode 1:


Cnt > CCR is invalid level / / (oc1ref = 0)

Mode 2:


Cnt > CCR is the effective level / / (oc1ref = 1)


0: high level active

1: Low level active

04. STM32 output PWM configuration

After analyzing the principle, the process of generating PWM by STM32 is analyzed below.

1. First, set GPIO to multiplex output

/* GPIOE clock enable */
/* GPIOE Configuration: TIM9 CH2 (PE6)*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOE, &GPIO_InitStructure); 
/* Connect TIM9 pins to AF3 */  

2. Configure the timer to count up and configure the timer frequency

/* TIM9 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
/* Compute the prescaler value */
PrescalerValue = (uint16_t) ((SystemCoreClock) / 2000000) - 1;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 1000-1;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);

3. Configure PWM output

The above analysis process is troublesome. St provides a standard peripheral library. We only need to configure Tim_ Ocinittypedef structure.

TIM_OCInitTypeDef  TIM_OCInitStructure;
/* PWM Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 100-1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM9, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);

TIM_ Ocinittypedef struct resolution

typedef struct

Where Tim_ Pulse can be set during initialization. After setting, it can also be updated again through the following interface.

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1)

4. Enable timer

TIM_ARRPreloadConfig(TIM9, ENABLE);
/* TIM9 enable counter */

Use timer9 to output PWM waveform

Keil and IAR project code open source address:

Click to view the album where this article is located,Stm32f207 tutorial

Recommended Today

Android master notes – start optimization

The only way to start and open the app, the first experience, is related to core data such as user retention and conversion rate; Start analysis startup type Android vitals can monitor the application cold, hot and warm startup time. Via ADB shell am start – w Execute the command to start and print the […]