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的舵机控制信号:
- 先确定ARR。舵机周期20ms,50Hz对应20ms。72MHz / 50Hz = 1,440,000。
- 选PSC=1440-1,ARR=999。实际频率 = 72,000,000 / 1440 / 1000 = 50Hz。
- 舵机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模式、极性、参数计算的关系串起来了。你配置时按这个流程走,基本不会出错。
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上,通过亮度变化判断占空比是否正常。虽然不精确,但能快速定位问题。