在嵌入式开发中,舵机控制是机器人、云台等项目的核心基础。市面上大多数教程只给出"填参数"式的代码片段,却很少解释为什么0.5ms对应-90°、2.5ms对应90°。本文将带您从数学原理出发,完整推导两种角度表示法的转换公式,并深入分析STM32定时器参数(arr/psc/ccr)的物理意义,最终实现可移植的PWM控制代码。
标准舵机的控制信号是周期20ms的PWM波,通过高电平脉冲宽度(0.5ms-2.5ms)控制角度。两种常见表示法:
对称表示法(-90°~90°):
code复制0.5ms → -90°
1.5ms → 0°
2.5ms → 90°
非对称表示法(0°~180°):
code复制0.5ms → 0°
1.5ms → 90°
2.5ms → 180°
建立角度θ与高电平时间t的线性关系:θ = k·t + b
对称表示法推导:
math复制0.5k + b = -90
2.5k + b = 90
=> k = 90, b = -135
=> θ = 90t -135
非对称表示法推导:
math复制0.5k + b = 0
2.5k + b = 180
=> k = 90, b = -45
=> θ = 90t -45
以STM32F407ZGT6为例,配置TIM8产生20ms周期PWM:
c复制TIM8_Init(200-1, 16800-1); // arr=199, psc=16799
参数计算过程:
code复制f_cnt = 168MHz / (psc+1) = 1kHz
code复制T = (arr+1)/f_cnt = 200ms/1kHz = 20ms
捕获比较寄存器CCR与高电平时间t的关系:
math复制t = (CCR/arr) × 20ms
代码实现对比:
| 表示法 | 公式转换 | 代码实现示例 |
|---|---|---|
| 对称表示法 | CCR = (θ + 135)/9 | TIM8->CCR1 = (angle+135)/9 |
| 非对称表示法 | CCR = (θ × 20)/180 + 5 | TIM_SetCompare1(TIM8, (angle*20/180)+5) |
典型云台需要控制YAW(偏航)和PITCH(俯仰)两个自由度:
c复制void Servo_Update(int yaw, int pitch) {
// 对称表示法
TIM8->CCR1 = (yaw + 135)/9; // 通道1控制YAW
TIM8->CCR2 = (pitch + 135)/9; // 通道2控制PITCH
}
实际机械安装可能存在偏差,可通过公式调整:
c复制// 示例:PITCH轴需要补偿-5°
TIM8->CCR2 = (pitch + 135 - 5)/9;
调试技巧:先用示波器验证PWM波形,再安装舵机
不同于基础定时器,高级定时器需要额外操作:
c复制TIM_CtrlPWMOutputs(TIM8, ENABLE); // 必须使能PWM输出
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8); // 引脚复用
c复制TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始CCR值
TIM_OC1Init(TIM8, &TIM_OCInitStructure);
实际项目中,我曾遇到机械结构限制必须使用非对称表示法的情况,通过封装转换函数保持代码可读性:
c复制float SymmetricToAsymmetric(float angle) {
return angle + 90; // -90°~90° → 0°~180°
}
调试时建议先用Servo_SetAngle(90,90)测试中点位置,再逐步调整。遇到异常首先检查: