2、硬件平台介绍:常用MCU(STM32、ESP32)的PWM定时器资源、PWM输出引脚与复用功能
做PWM调试,第一步得搞清楚你手头的MCU到底有多少“家底”。说白了,就是定时器资源和引脚分布。我见过不少新手,代码写得飞起,结果发现引脚不对、定时器不够用,最后全得重来。今天咱们就把STM32和ESP32这两大主流平台的PWM家底翻个底朝天。
2.1 STM32的PWM定时器资源
STM32的定时器体系,我习惯把它分成三个梯队:
- 高级定时器(TIM1/TIM8):能输出6路互补PWM,带死区插入、刹车功能。做电机控制、逆变器,首选它们。
- 通用定时器(TIM2~TIM5,TIM9~TIM14):最常用的PWM发生器。4路独立通道,支持向上/向下/中央对齐计数。
- 基本定时器(TIM6/TIM7):不能输出PWM,只能做定时或触发DAC。别在这上面浪费时间找PWM。
举个例子,STM32F103C8T6这颗“小蓝板”上的资源:
| 定时器 | 类型 | 通道数 | PWM输出引脚 | 备注 |
|---|---|---|---|---|
| TIM1 | 高级 | 4(互补6路) | PA8~PA11 | 16位,支持死区 |
| TIM2 | 通用 | 4 | PA0~PA3 | 16位,最常用 |
| TIM3 | 通用 | 4 | PA6, PA7, PB0, PB1 | 16位 |
| TIM4 | 通用 | 4 | PB6~PB9 | 16位 |
2.2 STM32的引脚复用功能
STM32的引脚不是“一根筋”。同一个引脚,可能同时属于GPIO、USART、SPI、定时器通道。你得通过配置GPIO的复用功能(AF)来“告诉”芯片:这个引脚现在归定时器管。
以STM32F1系列为例,配置PWM输出时,GPIO要设成复用推挽输出(AF_PP),速度建议设到50MHz以上。我踩过坑:速度设成2MHz,PWM频率高了之后波形直接变形。
// STM32F1 TIM2_CH1 PWM输出配置示例
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0; // PA0 = TIM2_CH1
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 50MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
2.3 ESP32的PWM资源
ESP32的PWM体系和STM32差别很大。它没有传统意义上的“定时器通道”,而是用LED PWM控制器(LEDC)来实现。说白了,这是一个专门为PWM设计的硬件模块,和LED驱动无关,名字容易误导人。
ESP32的LEDC资源:
- 8个通道:分成两组,每组4个通道(0~3,4~7)
- 2个定时器:每组共享一个定时器,但每个通道可以独立设置占空比
- 16位分辨率:占空比精度0~65535
- 频率范围:从1Hz到40MHz,但分辨率越高,最高频率越低
你想想看,8个通道听起来不少,但如果你要控制8个舵机,每个舵机需要不同的频率,那就麻烦了——因为同一组的4个通道共享一个定时器,频率必须相同。
| LEDC组 | 定时器 | 通道 | 可输出引脚 | 特点 |
|---|---|---|---|---|
| 组0 | 定时器0 | 0~3 | 任意GPIO | 频率共享,占空比独立 |
| 组1 | 定时器1 | 4~7 | 任意GPIO | 频率共享,占空比独立 |
2.4 ESP32的PWM配置实战
ESP32用Arduino框架配置PWM很简单,但底层逻辑得清楚:
// ESP32 LEDC PWM配置示例
// 设置LEDC通道0,频率5000Hz,分辨率8位
ledcSetup(0, 5000, 8);
// 将通道0绑定到GPIO 18
ledcAttachPin(18, 0);
// 输出50%占空比(8位分辨率下,255的一半≈127)
ledcWrite(0, 127);
这里有个细节:ledcSetup的第三个参数是分辨率位数。8位分辨率下,占空比范围0~255;10位就是0~1023。分辨率越高,频率上限越低。我做过测试:16位分辨率下,最高频率只能到几kHz,做电机控制还行,做LED调光完全够用。
2.5 两张图看懂PWM资源体系
下面这张图,我画的是STM32和ESP32的PWM资源对比框架。你看一眼就能明白两者的设计思路差异:
2.6 选型建议:什么时候用谁?
我个人的经验总结:
- 做电机控制、逆变器、开关电源:选STM32的高级定时器。死区控制、刹车功能、互补输出,这些是硬需求。
- 做多路LED调光、舵机群控:ESP32更合适。引脚任意分配,省去PCB布线烦恼。
- 做音频PWM(Class-D功放):STM32的定时器精度更高,频率更稳定。ESP32的LEDC在高频下抖动偏大。
- 做IoT设备,需要WiFi+少量PWM:ESP32一把梭。省一颗MCU,省一堆麻烦。
嗯,硬件平台这部分就聊到这儿。记住一句话:PWM调试,七分在硬件规划,三分在代码实现。把定时器资源和引脚映射搞清楚,后面调试才能顺风顺水。