SOA快速指南 1 2 3,第 3 部分: 服务实现及架构设计
STM32F103定时器与PWM实战:从呼吸灯到电机控制进阶指南
在嵌入式开发领域,STM32F103系列微控制器因其出色的性价比和丰富的外设资源,成为众多工程师的首选。许多初学者通过经典的"呼吸灯"实验入门PWM技术,但往往止步于此,未能深入挖掘定时器的强大潜力。本文将带您突破基础应用,探索如何利用STM32F103的通用定时器实现舵机和步进电机的精确控制——这两种电机在机器人、3D打印机和自动化设备中无处不在。
1. STM32F103定时器系统深度解析
STM32F103系列微控制器配备了三种类型的定时器:高级定时器(TIM1/TIM8)、通用定时器(TIM2-TIM5)和基本定时器(TIM6/TIM7)。对于大多数电机控制应用,通用定时器已经能够完美胜任,它们提供了四路独立的PWM输出通道,且配置灵活。
定时器的核心工作原理围绕几个关键寄存器展开:
- 自动重装载寄存器(ARR) :决定计数周期上限
- 预分频寄存器(PSC) :对时钟源进行分频
- 捕获/比较寄存器(CCR) :PWM脉宽控制的关键
PWM频率的计算公式为:
PWM频率 = 定时器时钟频率 / [(ARR+1) * (PSC+1)]
而占空比则由CCR值决定:
占空比 = CCR / (ARR+1)
下表对比了不同定时器类型的主要特性:
| 特性 | 高级定时器 | 通用定时器 | 基本定时器 |
|---|---|---|---|
| PWM通道数 | 7 | 4 | 0 |
| 互补输出 | 支持 | 不支持 | 不支持 |
| 编码器接口 | 支持 | 支持 | 不支持 |
| 中断类型 | 丰富 | 常规 | 基本 |
| 典型应用 | 电机FOC控制 | 通用PWM生成 | 简单计时 |
提示:在资源允许的情况下,建议保留高级定时器(TIM1)用于更复杂的控制任务,通用定时器足以应对大多数舵机和步进电机应用。
2. 舵机控制:从理论到实践
舵机是一种位置伺服机构,其控制核心是50Hz的PWM信号(周期20ms),通过脉冲宽度在0.5ms-2.5ms范围内的变化来指定角度位置。这种控制方式看似简单,但实现精准控制需要深入理解其工作机制。
2.1 定时器参数计算与配置
以72MHz系统时钟为例,配置TIM3产生50Hz PWM:
- 选择预分频值(PSC)为71,将时钟分频至1MHz
-
设置自动重装载值(ARR)为19999,实现20ms周期:
1MHz / (71+1) = 1MHz 1MHz / (19999+1) = 50Hz -
脉宽对应CCR值范围:
- 0°位置:1000 (1ms)
- 90°位置:1500 (1.5ms)
- 180°位置:2000 (2ms)
实际初始化代码如下:
void Servo_PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// GPIO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // TIM3 CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 时基单元配置
TIM_TimeBaseStructure.TIM_Period = 19999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
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;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 1500; // 初始位置90°
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
}
2.2 提高舵机控制精度的技巧
实际应用中,舵机可能出现抖动或定位不准的问题,以下是几种有效的解决方案:
-
软件滤波 :对控制信号进行平滑处理
#define FILTER_DEPTH 5 uint16_t filterBuffer[FILTER_DEPTH]; uint16_t SmoothingFilter(uint16_t newValue) { static uint8_t index = 0; static uint32_t sum = 0; sum -= filterBuffer[index]; filterBuffer[index] = newValue; sum += newValue; index = (index + 1) % FILTER_DEPTH; return sum / FILTER_DEPTH; } -
电源去耦 :在舵机电源引脚附近添加100μF电解电容和0.1μF陶瓷电容
-
机械减震 :使用橡胶垫片隔离舵机与安装结构
-
死区补偿 :针对特定舵机特性添加微调偏移
注意:避免频繁发送微小角度变化指令,这会导致舵机电机持续工作而发热。建议设置变化阈值,只有当角度变化超过2-3°时才更新PWM信号。
3. 步进电机控制:精准脉冲生成艺术
与舵机不同,步进电机通过接收脉冲信号进行控制,每个脉冲对应一个固定的角度位移(步距角)。控制步进电机需要关注两个关键参数:脉冲频率(决定转速)和脉冲数量(决定位移)。
3.1 步进电机驱动器接口配置
常见步进电机驱动器需要三个控制信号:
- PUL :脉冲信号,每个上升沿触发一步
- DIR :方向信号,高/低电平控制正反转
- ENA :使能信号(可选)
使用TIM4生成脉冲信号,配合普通GPIO控制方向:
void Stepper_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置方向控制引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; // DIR和ENA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置PUL引脚( TIM4 CH1 )
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = 1000; // 初始频率
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 1MHz计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
// PWM模式配置 - 50%占空比方波
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 500; // 50%占空比
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_Cmd(TIM4, ENABLE);
}
3.2 加减速控制算法实现
直接以高频率启动步进电机可能导致失步,合理的加减速曲线至关重要。常用的梯形加减速算法实现如下:
typedef struct {
uint32_t currentFreq;
uint32_t targetFreq;
uint32_t stepInterval;
uint32_t acceleration;
uint16_t stepsRemaining;
} StepperProfile;
void Stepper_RunTrapezoid(StepperProfile *profile, uint32_t steps)
{
uint32_t stepsAccel = (profile->targetFreq - profile->currentFreq) / profile->acceleration;
stepsAccel = stepsAccel > steps/2 ? steps/2 : stepsAccel;
// 加速阶段
for(uint32_t i = 0; i < stepsAccel; i++) {
profile->currentFreq += profile->acceleration;
profile->stepInterval = 1000000UL / profile->currentFreq; // 转换为μs
TIM4->ARR = profile->currentFreq - 1;
Delay_us(profile->stepInterval);
}
// 匀速阶段
uint32_t stepsConst = steps - 2 * stepsAccel;
for(uint32_t i = 0; i < stepsConst; i++) {
Delay_us(profile->stepInterval);
}
// 减速阶段
for(uint32_t i = 0; i < stepsAccel; i++) {
profile->currentFreq -= profile->acceleration;
profile->stepInterval = 1000000UL / profile->currentFreq;
TIM4->ARR = profile->currentFreq - 1;
Delay_us(profile->stepInterval);
}
}
提示:实际应用中,建议使用定时器中断来更新频率参数,避免在Delay函数中阻塞系统。可以使用S曲线算法实现更平滑的加减速过程。
4. 硬件布局与抗干扰设计
电机控制系统对电路布局极为敏感,不当的设计可能导致控制信号异常甚至MCU复位。以下是经过实际验证的有效措施:
-
电源分离 :
- 使用独立LDO为MCU供电
- 电机电源与逻辑电源通过磁珠隔离
- 在电源入口处布置大容量电解电容(100-470μF)
-
信号保护 :
- PWM信号线串联22-100Ω电阻
- 敏感信号线使用双绞线或屏蔽线
- 在信号线上添加小容量电容(10-100pF)到地
-
PCB布局要点 :
- 电机驱动电路与MCU保持至少5mm间距
- 大电流路径尽量短而宽
- 晶振和关键信号线远离电机驱动部分
典型布局参考:
+-------------------+ +-------------------+ +-------------------+
| STM32F103 |-----| 信号隔离电路 |-----| 电机驱动器 |
| | | (光耦/电平转换) | | |
+-------------------+ +-------------------+ +-------------------+
| |
| |
+-------------------+ +-------------------+
| 5V稳压电源 | | 电机电源 |
| (为MCU和逻辑供电) | | (12-24V) |
+-------------------+ +-------------------+
在调试过程中,如果遇到异常情况,可以按照以下步骤排查:
- 检查所有电源电压是否稳定
- 用示波器观察PWM信号波形
- 暂时降低电机工作电流测试
- 检查地线连接是否可靠
- 尝试逐步移除外围电路,定位干扰源
实际项目中,我曾遇到过一个棘手的问题:步进电机在高速运行时导致STM32间歇性复位。最终发现是电机电源回路的瞬态干扰通过地线耦合到了MCU的复位电路。解决方案是在复位引脚添加0.1μF电容并在电源入口增加TVS二极管,同时优化了地平面布局。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)