基于STM32F103实现两路PWM输出
一、硬件连接方案
1. 引脚分配(以TIM3为例)
| 通道 | 默认引脚 | 重映射引脚 | 适用场景 |
|---|---|---|---|
| CH1 | PA6 | PB4 | 电机控制/LED调光 |
| CH2 | PA7 | PB5 | 伺服电机/呼吸灯 |
2. 电路设计要点
-
电机驱动:需外接H桥电路(如TB6612)保护GPIO
-
LED限流:串联220Ω电阻防止烧毁
-
滤波电路:在电源端添加0.1μF陶瓷电容
二、软件实现代码
1. 定时器初始化(TIM3双通道PWM)
#include "stm32f10x.h"
void TIM3_PWM_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
// 引脚重映射配置
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); // PA6→PB4, PA7→PB5
// GPIO初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = arr; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM模式配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 通道1配置
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
// 通道2配置
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
// 使能定时器
TIM_Cmd(TIM3, ENABLE);
}
2. 占空比动态调整
// 设置通道1占空比(0-100%)
void Set_PWM1_DutyCycle(u8 percent) {
u16 compare_val = (arr + 1) * percent / 100;
TIM_SetCompare1(TIM3, compare_val);
}
// 设置通道2占空比(0-100%)
void Set_PWM2_DutyCycle(u8 percent) {
u16 compare_val = (arr + 1) * percent / 100;
TIM_SetCompare2(TIM3, compare_val);
}
3. 主函数示例
int main(void) {
// 初始化PWM(周期20ms,频率50Hz)
TIM3_PWM_Init(19999, 71); // 72MHz/(72)=1MHz → 1MHz/(19999+1)=50Hz
while(1) {
// 通道1从0%到100%渐变
for(u8 i=0; i<=100; i++) {
Set_PWM1_DutyCycle(i);
Delay_ms(10);
}
// 通道2从100%到0%渐变
for(u8 i=100; i>=0; i--) {
Set_PWM2_DutyCycle(i);
Delay_ms(10);
}
}
}
三、关键参数计算
1. PWM频率公式
频率 = 72MHz / (预分频系数 + 1) / (自动重装载值 + 1)
- 示例:psc=71, arr=19999 → 72/(72)/(20000)=50Hz
2. 占空比计算
占空比(%) = (CCR值 / (ARR+1)) × 100
四、调试技巧
1. 示波器观察要点
-
上升沿对齐:确保两路PWM上升沿同步
-
占空比精度:检查实际值与设定值偏差(应<1%)
-
死区时间:电机控制需添加死区(建议0.1-0.5μs)
2. 常见问题解决
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 无输出 | GPIO未正确映射 | 检查AFIO时钟和重映射配置 |
| 占空比失真 | 中断干扰 | 关闭相关中断或提高优先级 |
| 频率漂移 | 系统时钟异常 | 验证PLL配置和外部晶振 |
五、扩展功能实现
1. 输入捕获同步
// 配置TIM3_CH1为输入捕获(用于编码器)
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
2. 硬件PWM刹车
// 紧急停止时强制输出低电平
void PWM_Brake() {
GPIO_ResetBits(GPIOB, GPIO_Pin_4 | GPIO_Pin_5);
}
参考代码 STM32F103控制的两路PWM输出 www.youwenfan.com/contentcnr/103639.html
六、完整工程配置
-
CubeMX配置流程:
-
选择STM32F103C8T6
-
启用TIM3定时器
-
配置通道1和2为PWM模式
-
设置时钟树(HSE=8MHz, PLL=9倍频)
-
-
Keil工程结构:
Project/ ├── Core/ │ ├── Inc/ (头文件) │ └── Src/ (源文件) ├── Drivers/ │ ├── CMSIS/ │ └── STM32F1xx_HAL_Driver/ └── Middlewares/ └── USB_Device/
浙公网安备 33010602011771号