STM32 PWM 输出模式详解:从定时器到舵机控制
STM32 PWM 输出模式详解:从定时器到舵机控制
分类: 嵌入式开发
标签: STM32, PWM, 定时器, 舵机, 电机控制

一、PWM 基本原理
PWM(Pulse Width Modulation,脉冲宽度调制)是一种通过调节脉冲宽度(占空比)来实现模拟量控制的技术。其核心思想是:在固定频率下,改变高电平持续时间的比例,从而等效地输出一个连续可调的模拟电压。
STM32 的 PWM 输出依赖于高级定时器(TIM1/TIM8)或通用定时器(TIM2~TIM5)的输出比较(Output Compare)功能。
关键寄存器
- ARR(Auto-Reload Register):决定 PWM 周期
- CCRx(Capture/Compare Register x):决定占空比
- CNT(Counter):从 0 计数到 ARR,循环往复
当 CNT < CCR 时输出高电平,当 CNT ≥ CCR 时输出低电平。因此:
$$f_{PWM} = \frac{f_{TIM}}{ARR + 1}$$
$$Duty = \frac{CCR}{ARR + 1} \times 100\%$$
二、STM32F103 定时器资源
STM32F103RCT6 拥有以下定时器:
| 定时器 | 类型 | 通道数 | 功能特点 |
|---|---|---|---|
| TIM1 | 高级 | 4 | 互补输出、刹车输入、死区插入 |
| TIM2~TIM5 | 通用 | 4 | 基本 PWM,常用 |
| TIM6~TIM7 | 基本 | 0 | 无 PWM 输出 |
| TIM8 | 高级 | 4 | 同 TIM1 |
注意:PA9/PA10 被 USART1 占用,PA11/PA12 被 USB 占用,PA13/PA14 被 SWD 占用,这些引脚不能作为 PWM 输出。
推荐引脚分配
| 定时器通道 | 引脚 | 用途 |
|---|---|---|
| TIM2_CH1 | PA0 | 舵机 1 控制 |
| TIM2_CH2 | PA1 | 舵机 2 控制 |
| TIM3_CH1 | PA6 | LED 呼吸灯 |
| TIM3_CH2 | PA7 | 电机速度控制 |
三、配置步骤
1. 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // TIM2 在 APB1 上
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOA 在 APB2 上
2. GPIO 复用配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
3. 定时器配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 72MHz / (71+1) = 1MHz
TIM_TimeBaseStructure.TIM_Period = 19999; // 1MHz / 20000 = 50Hz(适合舵机)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
4. PWM 通道配置
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM1 模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1500; // 初始占空比(1.5ms = 中位)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
5. 启动定时器
TIM_Cmd(TIM2, ENABLE); // 使能 TIM2
四、实际应用:舵机控制
SG90 舵机的控制信号是周期 20ms(50Hz)的 PWM:
| 脉宽 | 角度 |
|---|---|
| 0.5ms (CCR=500) | 0° |
| 1.0ms (CCR=1000) | 45° |
| 1.5ms (CCR=1500) | 90°(中位) |
| 2.0ms (CCR=2000) | 135° |
| 2.5ms (CCR=2500) | 180° |
// 设置舵机角度
void servo_set_angle(uint16_t angle) {
// angle: 0~180
uint16_t pulse = 500 + (angle * 2000) / 180; // 500~2500
TIM_SetCompare1(TIM2, pulse);
}
五、注意事项
- 引脚冲突:避开 PA9/PA10(USART1)、PA11/PA12(USB)、PA13/PA14(SWD)
- 驱动能力:STM32 GPIO 输出电流有限,驱动电机需加 MOSFET 或专用驱动芯片
- 滤波器:PWM 输出建议加 RC 滤波器(10kΩ + 100nF)减少 EMI
- 备用引脚:PC12~PC15、PA15 可作为额外 PWM 输出(通过定时器重映射)
总结
PWM 是嵌入式开发中最常用的输出技术之一。理解 STM32 定时器的工作原理和寄存器配置,不仅能实现舵机和电机控制,还能扩展到 LED 调光、音频输出、开关电源控制等多种场景。掌握好这些基础,后续学习高级定时器的死区插入、互补输出等功能会轻松很多。
STM32 PWM 输出模式详解:从定时器到舵机控制
https://blog.la.lmxslms.top//archives/stm32-pwm-output-mode