1. 项目概述
180°舵机(SG90)是创客和嵌入式开发者最常用的执行器之一,而STM32F103C8T6作为经典的ARM Cortex-M3内核微控制器,两者的组合在机器人控制、智能家居等领域有着广泛应用。这个教程将带你从硬件连接到PWM信号生成,完整实现舵机的精准角度控制。
我第一次使用STM32驱动SG90时,发现网上很多教程要么缺少关键细节,要么参数配置有误,导致舵机抖动或响应异常。经过多次实测和示波器验证,我总结出一套稳定可靠的配置方法,即使是刚接触STM32的新手也能在30分钟内完成从零到精准控制的全过程。
2. 硬件准备与连接
2.1 所需材料清单
- STM32F103C8T6最小系统板(Blue Pill开发板)
- SG90舵机(工作电压4.8V-6V)
- 5V/2A直流电源(或3节AA电池盒)
- 杜邦线若干
- 万用表(可选,用于电压检测)
- 示波器(可选,用于PWM波形观测)
注意:SG90的工作电流在堵转时可达500-700mA,切勿直接使用STM32的3.3V引脚供电,必须外接独立电源!
2.2 电路连接示意图
code复制[STM32F103C8T6] [SG90舵机]
PA8 ------> 信号线(橙色)
GND ------> 地线(棕色)
[外部5V电源+] --> 电源线(红色)
[外部电源GND] --┬-> 舵机GND
└-> STM32 GND
2.3 关键连接细节
- 共地处理:必须将STM32与舵机电源的地线连接在一起,否则PWM信号无法正确参考
- 信号线保护:建议在PA8与舵机信号线之间串联220Ω电阻,防止意外电流冲击
- 电源去耦:在舵机电源正负极间并联100μF电解电容+0.1μF陶瓷电容组合
3. STM32定时器配置
3.1 PWM生成原理
SG90舵机通过20ms周期的PWM信号控制角度,其中:
- 0.5ms脉宽对应0°位置
- 1.5ms脉宽对应90°位置
- 2.5ms脉宽对应180°位置
在STM32中,我们使用定时器(TIM)的PWM模式来生成这个信号。以TIM1_CH1(PA8)为例:
3.2 定时器参数计算
假设系统时钟72MHz,预分频值设为71,则:
- 定时器时钟 = 72MHz / (71+1) = 1MHz
- 周期值 = 20ms / (1/1MHz) = 20000
- 0.5ms脉宽 = 500
- 1.5ms脉宽 = 1500
- 2.5ms脉宽 = 2500
3.3 CubeMX配置步骤
- 开启TIM1,选择Clock Source为Internal Clock
- 设置Channel1为PWM Generation CH1
- 参数配置:
- Prescaler: 71
- Counter Period: 19999 (因为从0开始计数)
- Pulse: 初始值1500(中间位置)
- CH Polarity: High
4. 代码实现详解
4.1 初始化代码
c复制// 启动PWM
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// 设置初始角度为90度
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 1500);
4.2 角度控制函数
c复制void Set_Servo_Angle(uint8_t angle)
{
// 角度限幅
if(angle > 180) angle = 180;
// 计算对应脉冲值 (500-2500对应0-180°)
uint16_t pulse = 500 + angle * (2000 / 180);
// 更新CCR寄存器
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse);
}
4.3 主程序示例
c复制int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
while (1)
{
// 从0°到180°往复运动
for(int i=0; i<=180; i+=10){
Set_Servo_Angle(i);
HAL_Delay(200);
}
for(int i=180; i>=0; i-=10){
Set_Servo_Angle(i);
HAL_Delay(200);
}
}
}
5. 调试技巧与问题排查
5.1 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 舵机无反应 | 电源未接通/电压不足 | 检查电源电压≥4.8V,电流≥1A |
| 舵机抖动 | PWM周期不稳定 | 用示波器检查20ms周期是否准确 |
| 角度不准 | 脉冲宽度计算错误 | 重新校准500-2500对应0-180° |
| 发热严重 | 机械负载过大 | 减小负载或更换更大扭矩舵机 |
5.2 高级调试技巧
- 示波器观测:直接测量PA8引脚波形,确认:
- 周期是否为20ms±1%
- 高电平时间是否随角度线性变化
- 软件校准:通过以下代码进行端点校准:
c复制// 0°位置校准 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 500); // 180°位置校准 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 2500); - 死区消除:在角度变化时添加5ms延时,避免快速切换导致的异常:
c复制Set_Servo_Angle(new_angle); HAL_Delay(5); // 等待舵机稳定
6. 性能优化与扩展应用
6.1 多舵机控制方案
当需要控制多个舵机时:
- 使用TIM1的4个通道(PA8/PA9/PA10/PA11)
- 或启用其他定时器(如TIM2/TIM3/TIM4)
- 每个定时器可支持4路独立PWM输出
6.2 中断控制实现
通过定时器中断实现更精确的时间控制:
c复制// 在定时器中断中更新CCR值
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1){
static uint16_t pulse = 500;
pulse = (pulse >= 2500) ? 500 : pulse + 100;
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse);
}
}
6.3 实际项目应用案例
- 机械臂控制:3个SG90构成3自由度机械臂
- 摄像头云台:2个舵机实现俯仰和水平旋转
- 智能门锁:控制锁舌的伸出/收回动作
我在一个农业机器人项目中使用了6个SG90舵机,通过TIM1+TIM2的组合控制,关键经验是:
- 为每个舵机配置独立的电源滤波电容
- 所有舵机不要同时启动,错开50ms以上
- 在机械结构上增加限位开关,防止过冲损坏