3、PWM输出模式详解:模式1与模式2区别、占空比与频率计算、极性配置

PWM这东西,说白了就是通过快速开关信号,让负载感受到一个平均电压。你想想看,LED调光、电机调速、舵机转角,背后都是PWM在干活。STM32的定时器里集成了硬件PWM发生器,一旦配置好,CPU基本不用管,脉冲自己跑,效率非常高。

我个人习惯,拿到一个新项目,先搞清楚PWM的两个核心参数:频率和占空比。频率决定了控制周期,占空比决定了有效输出。今天咱们就把模式1、模式2、极性配置这些容易搞混的东西,一次说清楚。

3.1 PWM模式1与模式2的本质区别

STM32的定时器支持两种PWM输出模式。很多初学者刚接触时觉得这俩模式很绕,其实理解起来很简单——就看计数器与比较值的关系。

对比项 PWM模式1 PWM模式2
有效电平 计数器值 < 比较值时输出有效电平 计数器值 > 比较值时输出有效电平
向上计数波形 起始为有效电平,到达比较值后翻转 起始为无效电平,到达比较值后翻转
向下计数波形 起始为无效电平,到达比较值后翻转 起始为有效电平,到达比较值后翻转
常用场景 舵机控制、LED调光 电机驱动、互补输出

举个例子,向上计数模式下,ARR=99,CCR=30:

  • 模式1:计数器从0到99,0~29输出高电平,30~99输出低电平。占空比30%。
  • 模式2:计数器从0到99,0~29输出低电平,30~99输出高电平。占空比70%。

你看,模式1和模式2其实就是把有效电平的位置对调了一下。我刚开始用STM32时,习惯用模式1,因为逻辑更直观——比较值直接对应高电平宽度。后来做电机控制,发现模式2配合互补输出更方便,尤其是做刹车和死区插入的时候。

核心记忆法:模式1是"小于有效",模式2是"大于有效"。记住这个,配置时就不会搞反。

3.2 占空比与频率的计算方法

频率和占空比的计算,其实就两个公式。我建议你把它写在笔记本第一页,每次配置定时器前看一眼。

频率公式:

PWM频率 = 定时器时钟 / (PSC + 1) / (ARR + 1)

占空比公式:

占空比 = CCR / (ARR + 1) × 100%

举个例子,STM32F103的TIM2挂载在APB1上,时钟72MHz。我想输出50Hz的舵机控制信号:

  1. 先确定ARR。舵机周期20ms,50Hz对应20ms。72MHz / 50Hz = 1,440,000。
  2. 选PSC=1440-1,ARR=999。实际频率 = 72,000,000 / 1440 / 1000 = 50Hz。
  3. 舵机0°对应CCR=50,90°对应CCR=150,180°对应CCR=250。占空比范围5%~25%。
// 50Hz舵机PWM配置示例
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructure.TIM_Prescaler = 1440 - 1;     // PSC=1439
TIM_TimeBaseStructure.TIM_Period = 1000 - 1;        // ARR=999
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   // 模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 150;                // CCR=150,90°
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

TIM_Cmd(TIM2, ENABLE);

经验之谈:我一般先定ARR,再算PSC。ARR决定了分辨率,比如ARR=999时占空比精度0.1%。如果分辨率不够,可以增大ARR,但要注意频率别跑偏。

3.3 极性配置与输出波形

极性配置,说白了就是决定有效电平是高还是低。STM32里通过TIM_OCPolarity来设置:

  • TIM_OCPolarity_High:有效电平为高,无效电平为低。
  • TIM_OCPolarity_Low:有效电平为低,无效电平为高。

极性配置和PWM模式组合起来,能产生四种不同的输出波形。我整理了一张表,你配置时对照着看:

模式 极性 向上计数波形 有效电平
模式1 高有效 起始高,CCR后低 高
模式1 低有效 起始低,CCR后高 低
模式2 高有效 起始低,CCR后高 高
模式2 低有效 起始高,CCR后低 低

你发现没有?模式1+高有效 和 模式2+低有效,波形其实是一样的。这就是为什么有些人说"模式1和模式2可以通过极性互换"。但我不建议你这么玩,因为不同外设对有效电平的定义不同。比如舵机信号要求高电平为有效,电机驱动有时需要低电平刹车。

我曾经踩过的坑:做四轴飞行器电调控制时,我把极性配反了。结果电机在最低油门时全速旋转,差点炸机。后来我养成了一个习惯——每次配置完PWM,先用示波器看波形,确认有效电平对不对。

3.4 知识结构总览

下面这张图把PWM模式、极性、参数计算的关系串起来了。你配置时按这个流程走,基本不会出错。

PWM输出模式知识结构图 PWM核心参数 模式选择 频率计算 极性配置 模式1:小于有效 模式2:大于有效 PSC预分频器 ARR自动重装 高有效 低有效 PWM输出波形 配置流程建议 ① 先确定目标频率 → ② 计算PSC和ARR → ③ 选择PWM模式 → ④ 配置极性 → ⑤ 设置CCR ⑥ 使能定时器 → ⑦ 用示波器验证波形 → ⑧ 微调参数

3.5 实战中的避坑指南

做PWM配置时,有几个地方特别容易翻车。我把自己踩过的坑整理了一下:

  • ARR和CCR的关系:CCR不能大于ARR,否则占空比会变成100%或0%。我见过有人把CCR设成ARR+1,结果波形直接没了。
  • 定时器时钟源:不同定时器挂载在不同总线上,时钟频率可能不一样。TIM1和TIM8在APB2上,其他在APB1上。配置前先查时钟树。
  • 互补输出和死区:做H桥驱动时,要用TIM_BDTRConfig配置死区时间。死区太小会烧MOS管,太大影响效率。我一般设1~2μs。
  • 重载机制:修改CCR时,最好等定时器更新事件发生后再写入。用DMA或中断更新CCR,可以避免波形抖动。

调试小技巧:没有示波器时,可以用逻辑分析仪看PWM波形。再不行,把PWM输出接到LED上,通过亮度变化判断占空比是否正常。虽然不精确,但能快速定位问题。