别再只会调角度了!用STM32CubeMX+MG90S舵机,5分钟搞定PWM精准控制
·
别再只会调角度了!用STM32CubeMX+MG90S舵机,5分钟搞定PWM精准控制
在嵌入式开发中,舵机控制是一个经典的应用场景。对于刚接触STM32的新手来说,手动配置PWM参数往往令人望而生畏——寄存器配置复杂、参数计算繁琐、调试过程耗时。而MG90S作为一款经济实惠的180度舵机,广泛应用于机器人、遥控模型等领域。本文将带你使用STM32CubeMX这一强大工具,快速实现从零到精准控制的完整流程。
1. 环境准备与硬件连接
1.1 所需材料清单
- STM32开发板(如STM32F103C8T6)
- MG90S舵机(工作电压4.8-6V)
- 杜邦线若干
- USB转TTL模块(用于串口调试)
- ST-Link调试器(可选)
注意:舵机供电需单独处理,避免开发板5V输出电流不足导致抖动。推荐使用外接电源或稳压模块。
1.2 硬件连接示意图
STM32 PA7(PWM输出) → 舵机信号线(橙色)
STM32 GND → 舵机GND(棕色)
外部5V电源 → 舵机VCC(红色)
提示:若使用开发板供电,需确认其5V输出能力≥1A。MG90S堵转电流可达700mA。
2. STM32CubeMX工程配置
2.1 定时器PWM模式设置
- 打开CubeMX,选择对应STM32型号
- 在
Pinout & Configuration标签页:- 激活TIM3(或其他可用定时器)
- 选择Channel2 → PWM Generation CH2
- 时钟树配置确保APB1 Timer Clocks为72MHz
2.2 关键参数计算
MG90S的控制信号要求:
- 周期:20ms(50Hz)
- 脉宽:0.5ms(0°)至2.5ms(180°)
在 Parameter Settings 中配置:
Prescaler (PSC) = 71 // 72MHz/(71+1) = 1MHz
Counter Period (ARR) = 19999 // 20ms/(1/1MHz) -1
此时生成的PWM频率为: $$ f_{PWM} = \frac{72MHz}{(71+1) \times (19999+1)} = 50Hz $$
2.3 生成工程代码
- 在
Project Manager中设置Toolchain为MDK-ARM或IDE - 勾选
Generate peripheral initialization as a pair of .c/.h files - 点击
GENERATE CODE生成Keil工程
3. 角度控制实现
3.1 PWM占空比与角度换算
MG90S的角度-脉宽对应关系:
| 角度 | 脉宽(ms) | CCR值计算公式 |
|---|---|---|
| 0° | 0.5 | (ARR+1)*0.5/20 |
| 90° | 1.5 | (ARR+1)*1.5/20 |
| 180° | 2.5 | (ARR+1)*2.5/20 |
实际代码实现:
void Set_Servo_Angle(TIM_HandleTypeDef *htim, uint32_t Channel, float angle)
{
if(angle > 180) angle = 180;
if(angle < 0) angle = 0;
uint32_t pulse = 500 + angle * (2000/180); // 500~2500us
__HAL_TIM_SET_COMPARE(htim, Channel, pulse * (htim->Instance->ARR+1) / 20000);
}
3.2 动态控制技巧
通过HAL库函数实现平滑转动:
for(int angle=0; angle<=180; angle+=10){
Set_Servo_Angle(&htim3, TIM_CHANNEL_2, angle);
HAL_Delay(100); // 每100ms移动10度
}
进阶:可使用PID算法实现位置闭环控制,消除负载变化带来的角度误差。
4. 常见问题排查
4.1 舵机无反应检查清单
- 确认电源电压≥4.8V且电流充足
- 检查信号线是否连接至PWM输出引脚
- 验证定时器配置:
- 使用逻辑分析仪测量输出波形
- 确认
HAL_TIM_PWM_Start()已调用
4.2 角度不准的校准方法
- 实测0°和180°对应的CCR值:
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 100); // 逐步调整 - 修改角度映射公式:
// 替换原计算公式 uint32_t pulse = SERVO_MIN + angle * (SERVO_MAX-SERVO_MIN)/180;
4.3 减少抖动的硬件方案
- 在舵机电源端并联1000μF电容
- 使用带磁环的电源线
- 确保机械结构无卡顿
5. 进阶应用:多舵机协同控制
5.1 多定时器配置
在CubeMX中激活多个定时器:
- TIM1_CH1 → 舵机1
- TIM2_CH2 → 舵机2
- TIM3_CH3 → 舵机3
5.2 机械臂控制实例
六自由度机械臂控制代码结构:
typedef struct {
TIM_HandleTypeDef *htim;
uint32_t channel;
float current_angle;
} Servo_Instance;
Servo_Instance arm[6];
void Move_All_Joints(float angles[6])
{
for(int i=0; i<6; i++){
Set_Servo_Angle(arm[i].htim, arm[i].channel, angles[i]);
arm[i].current_angle = angles[i];
}
}
实际项目中建议使用RTOS任务管理各关节运动。
6. 性能优化技巧
6.1 中断方式更新角度
避免频繁调用HAL库函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim4){ // 专用定时器触发
static uint32_t target_ccr = 1500;
TIM3->CCR2 = target_ccr; // 直接操作寄存器
}
}
6.2 使用DMA减轻CPU负载
CubeMX配置步骤:
- 在TIM3配置中启用DMA
- 添加Memory-to-Peripheral传输
- 设置数据宽度为Word
应用示例:
uint32_t ccr_values[3] = {1500, 1750, 2000};
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2, ccr_values, 3);
6.3 低功耗模式下的控制
在STOP模式下维持PWM输出:
- 配置定时器为
Clock Source: LSI - 设置唤醒中断:
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 唤醒后重新初始化时钟
SystemClock_Config();
更多推荐

所有评论(0)