文章目录
一、简介
1.PWM基础概念与原理
PWM的本质是一种对模拟信号电平进行数字编码的方法。它通过调节占空比(高电平时间占整个周期的比例)来改变输出信号的有效值。
- 频率:信号周期的倒数,决定了PWM波的更新速度
- 占空比:决定输出电压或功率的有效值
占空比变化动图:

假设高电平为5V、低电平则为0V,那么要输出不同的模拟电压就要用到PWM。通过改变IO口输出的方波的占空比,从而获得使用数字信号模拟成的模拟电压信号。
电压是以一种脉冲序列被加到模拟负载上去的,接通时是高电平1,断开时是低电平0。接通时直流供电输出,断开时直流供电断开。通过对接通和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值5V的模拟电压。
比方说,占空比为50%那就是高电平时间一半,低电平时间一半。在一定的频率下,就可以得到模拟的2.5V输出电压。那么75%的占空比,得到的电压就是3.75V,如下图所示。

2.STM32的PWM硬件架构
例如STM32F407作为高性能Cortex-M4内核MCU,其PWM功能完全由定时器外设实现,而非软件模拟。该芯片集成14个定时器,按功能层级划分为三类:
| 定时器类型 | 数量 | PWM通道数 | 典型应用场景 | 关键特性 |
|---|---|---|---|---|
| 高级定时器(TIM1/TIM8) | 2 | 各4通道 | 电机FOC控制、三相逆变 | 死区插入、互补输出、刹车功能 |
| 通用定时器(TIM2-TIM5, TIM9-TIM14) | 10 | TIM2-TIM5各4通道;TIM9-TIM14各2通道 | LED调光、伺服控制、音频生成 | 独立捕获/比较、编码器接口 |
| 基本定时器(TIM6/TIM7) | 2 | 0 | 简单延时、SysTick替代 | 仅更新中断 |
所有支持PWM输出的定时器均基于同一硬件结构:16位自动重装载计数器(ARR)、16位捕获/比较寄存器(CCR)、预分频器(PSC)及输出比较单元。其工作流程如下:
- 计数器从0开始递增,直至等于ARR值后清零(向上计数模式)
- 当计数器值等于CCR值时,触发输出电平翻转(取决于极性配置)
- PSC对APB时钟进行分频,决定计数器基准频率
由此导出两个核心参数的计算公式:
- PWM频率 :f_pwm = f_apb / [(PSC + 1) × (ARR + 1)]
- 占空比 :D = (CCR + 1) / (ARR + 1)
若APB1时钟为84 MHz,需生成1 kHz PWM(周期1 ms),则:
PSC = 83 → 计数器时钟 = 84 MHz / 84 = 1 MHz
ARR = 999 → 周期 = 1000 × 1 μs = 1 ms
若需50%占空比,则CCR = 499


二、库函数
1.GPIO引脚映射
c
/**
* @brief Changes the mapping of the specified pin.
* @param GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F405xx/407xx and STM32F415xx/417xx devices
* x can be (A..I) to select the GPIO peripheral for STM32F42xxx/43xxx devices.
* x can be (A, B, C, D and H) to select the GPIO peripheral for STM32F401xx devices.
* @param GPIO_PinSource: specifies the pin for the Alternate function.
* This parameter can be GPIO_PinSourcex where x can be (0..15).
* @param GPIO_AFSelection: selects the pin to used as Alternate function.
* This parameter can be one of the following values:
.......................................................
* @arg GPIO_AF_TIM14: Connect TIM14 pins to AF9
.......................................................
* @retval None
*/
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
2.定时器通道1配置
c
/**
* 通道1:TIM_OC1Init
* 通道2:TIM_OC2Init
* 通道3:TIM_OC3Init
* 通道4:TIM_OC4Init
*/
/**
* @brief Initializes the TIMx Channel1 according to the specified parameters in
* the TIM_OCInitStruct.
* @param TIMx: where x can be 1 to 14 except 6 and 7, to select the TIM peripheral.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure that contains
* the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
3.定时器通道1比较值
c
/**
* 通道1:TIM_SetCompare1
* 通道2:TIM_SetCompare2
* 通道3:TIM_SetCompare3
* 通道4:TIM_SetCompare4
*/
/**
* @brief Sets the TIMx Capture Compare1 Register value
* @param TIMx: where x can be 1 to 14 except 6 and 7, to select the TIM peripheral.
* @param Compare1: specifies the Capture Compare1 register new value.
* @retval None
*/
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1)
{
/* Check the parameters */
assert_param(IS_TIM_LIST1_PERIPH(TIMx));
/* Set the Capture Compare1 Register value */
TIMx->CCR1 = Compare1;
}
三、PWM1和PWM2模式
1.PWM模式
PWM模式1:在向上计数时,当 CNT < CCR 时输出有效电平,否则为无效电平。
PWM模式2:与模式1相反,当 CNT < CCR 时输出无效电平。
计数模式:支持向上计数、向下计数和中心对齐模式(用于产生频率相同、相位可调的PWM)。

TIMx_CNT 由TIM_TimeBaseStructure.TIM_Period决定;TIMx_CCR1由TIM_SetComparex(x:1、2、3、4)函数决定;有效状态由TIM_OCInitStructure.TIM_OCPolarity决定;
频率值:由计数值决定
占空比:由比较值决定
要设置的比较值=(TIM_Period+1)*占空比

四、pwm调光
移动设备调光有两种方式,分别是DC调光与PWM调光,以下是DC调光与PWM调光的描述。
1.DC调光是一种调节亮度的方式
为了让用户在不同光线条件下正常观看手机上的内容,屏幕需要相应地改变亮度。其中一种调节亮度的方式就叫"DC调光"。DC调光的原理非常简单,就是通过提高或降低电路功率来改变屏幕的亮度。功率 = 电压 x 电流,所以改变电压或电流都能改变屏幕亮度。
2.PWM调光是另一种调节亮度的方式
iPhone14的PWM调光频率是480Hz,属于低频PWM。现在市面上的安卓机大多采用高频PWM调光,高于欧盟标准的1200Hz,或者采用类DC调光。
首先,PWM调光是一种常见的屏幕调光方式,其原理是通过快速开关屏幕背光灯的电流来控制亮度。低频PWM调光频率较低,可能会造成屏幕频闪,从而影响用户的视觉体验。而高频PWM调光频率更高,可以有效减少屏幕频闪的问题。因此,一些安卓手机采用高频PWM调光就是为了减少频闪问题。
在PWM调光屏幕上,调节亮度并不靠改变功率,而是靠屏幕的亮、灭交替。PWM调光屏幕点亮时并不是持续发光的,而是在不停地点亮、熄灭屏幕。当亮、灭交替够快时,肉眼就会认为手机一直在亮。
在屏幕亮、灭的过程中,灭屏状态持续时间越长,屏幕给肉眼的观感就是亮度越低。点亮的时间越长,灭屏时间就相应减少,屏幕就会变亮。
亮、灭交替的速度越低,对人眼造成不利影响的可能性就越大。但这并不是绝对的,因为每个人对于"闪烁"的敏感程度不同。比如看同一块PWM屏幕,有人没事,有人就会感到疲劳。如果你属于眼睛十分敏感的那部分人,你可能就需要使用高频PWM调光手机,甚至DC调光手机了。
五、常见问题与解答
1.PWM占空比的概念?PWM除了占空比还有什么要素?
占空比是指高电平在一个周期内所占的时间比例,通常用百分比表示。除了占空比,PWM的关键要素还包括频率(或周期)和极性。频率决定了信号的刷新速度,极性定义了高电平是有效电平还是无效电平
2.如何在STM32中生成PWM波,以及如何计算其频率和占空比?
- 生成机制:利用定时器的比较输出功能,当计数器(CNT)与比较寄存器(CCR)匹配时,翻转或设置输出电平

3.高级定时器和通用定时器的PWM功能有什么区别?
- 通道数:高级定时器(如TIM1)能产生7路PWM输出(3对互补+1路普通),而通用定时器最多产生4路
- 特殊功能:高级定时器支持互补输出和死区时间插入,这是驱动H桥或三相逆变电路所必需的功能,用于防止上下桥臂直通短路。同时,它还具备刹车功能,能在紧急情况下强制关闭PWM输出,保护电路
4.如何动态修改PWM的占空比和频率?
- 修改占空比:直接修改捕获比较寄存器(CCR)的值。在库函数中通常调用 TIM_SetComparex() (标准库) 或__HAL_TIM_SET_COMPARE()(HAL宏)
- 修改频率:修改自动重装载寄存器(ARR)的值。调用 TIM_SetAutoreload() (标准库) 或 __HAL_TIM_SET_AUTORELOAD() (HAL宏) 。需要注意,修改ARR时,如果计数器正在计数,可能会立即影响周期,通常需要配合预装载功能,在更新事件发生时再统一生效
5.PWM信号产生毛刺(干扰)如何处理?
- 引脚初始化顺序:在配置PWM时,应先配置GPIO为复用模式,再初始化定时器和PWM通道,防止引脚状态不定导致短暂乱序脉冲。
- 预装载功能:使能CCR和ARR的预装载功能(Preload),确保占空比和周期的变化在定时器更新事件时同步生效,避免在计数过程中修改导致不完整的脉冲
- 硬件滤波:在软件层面,可以在PWM输出引脚添加RC滤波电路。在硬件设计上,注意电源去耦和PCB布局,减少信号串扰。