舵机是闭环角度伺服系统,靠PWM 信号定目标、电位器 / 编码器测实际、控制电路闭环纠偏、减速齿轮增扭定位,实现精准角度控制。
注意事项:正常是0-180度,编程时注意最大转角,在0-170度之间,不得使用手去转到舵机,否则容易损坏内部结构。

舵机工作原理
- 舵机的转动的角度是通过调节 PWM(脉冲宽度调制)信号的占空比来实现的,标准 PWM(脉冲宽度调制)信号的周期固定为 20ms(50Hz),理论上脉宽分布应在 1ms 到 2ms 之间,但是,事实上脉宽可由 0.5ms 到 2.5ms 之间,脉宽和舵机的转角 0°~180° 相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。


脉冲宽度调制 (PWM)
- 脉冲宽度调制 (PWM),简称脉宽调制,是利用微处理器的数字输出来对模拟电路
- 进行控制的一种非常有效的技术。简单的讲就是对输出的脉冲宽度进行控制。
- PWM 有 3 个参数,分别是频率、占空比、周期,下面分别给大家介绍一下这 3 个参数
- PWM 的频率是指每秒钟信号从高电平到低电平再回到高电平的次数。
- PWM 的占空比就是在输出的 PWM 中,高电平持续的时间和该 PWM 信号的周期持续的时间之比。
- PWM 的周期就是指一个完整 PWM 信号持续的时间。
PWM电机调速原理
- 对于电机的转速调整,我们是采用脉宽调制(PWM)办法,控制电机的时候,电源并非连续地向电机供电,而是在一个特定的频率下以方波脉冲的形式提供电能。不同占空比的方波信号能对电机起到调速作用,这是因为电机实际上是一个大电感,它有阻碍输入电流和电压突变的能力,因此脉冲输入信号被平均分配到作用时间上,这样,改变在使能端 EN1 和 EN2 上输入方波的占空比就能改变加在电机两端的电压大小,从而改变了转速。
电路中用微处理器实现脉宽调制(PWM)
-
软件方式实现通过执行软件延时循环程序,交替改变端口某个二进制位的输出逻辑状态来产生脉宽调制信号;设置不同的延时时间,即可得到不同的占空比。
- 特点:实现简单,无需专用硬件,但会占用 CPU 运行时间,影响程序其他任务的执行效率。
-
硬件方式实现利用单片机自带的 PWM 硬件模块(如 PWM 模式下的计数器 1)自动产生 PWM 信号,不占用 CPU 处理时间。
- 特点:精度高、稳定性好、不占用 CPU 资源,是工程中更推荐的实现方式,具体配置需参考对应单片机的技术手册。
单片机 PWM 程序:双路错开 PWM 实现方案
一、需求拆解
- 生成2 路 PWM 信号,周期均为 256 个计数单位
- 两路占空比均为
80/256(高电平持续 80 个计数单位) - 两路波形不能同时为高电平 ,高电平起始时刻相差
48/256个周期 - 可在普通单片机(非 PIC 专用 PWM 外设)上实现
二、核心实现思路(双定时器方案)
1. 定时器分工
| 定时器 | 核心作用 | 控制参数 |
|---|---|---|
| T0 | 控制 PWM频率 / 周期 | 改变 T0 初值,调整 PWM 周期(256 个计数单位) |
| T1 | 控制 PWM占空比 | 改变 T1 初值,调整高电平持续时间(80 个计数单位) |
2. 单路 PWM 生成逻辑
- T0 定时器中断触发:将对应 IO 口置为高电平,同时启动 T1 定时器
- T1 定时器中断触发:将该 IO 口置为低电平,关闭 T1 定时器
- 循环执行,即可生成固定频率、固定占空比的 PWM 信号
三、关键参数计算
- 周期总计数:256
- 单路高电平:80 → 占空比 = 80/256 ≈ 31.25%
- 两路相位差:48 → 相位偏移 = 48/256 = 18.75% 周期
- 两路高电平区间:
- PWM1:0 ~ 80
- PWM2:48 ~ 128
- 重叠区间:48 ~ 80(共 32 个计数单位,需通过时序控制避免同时为高)

·占空比越大,对应电压的数值越大,最大到3.3v;
·占空比又与时间对应,比如0.5ms-2.0ms对应0-180度的旋转角度。
舵机左右摇摆实验
- 舵机周期:20ms
- 0° → 0.5ms 高电平
- 180° → 2.5ms 高电平
- 90° → 1.5ms 高电平
zhuanjiao = 5→ 0°zhuanjiao = 15→ 90°(中间)zhuanjiao = 25→ 180°
舵机控制函数
void DuojiMid() // 舵机回中
{
zhuanjiao = 15;
Delayms(300); // 停 300ms
}
void DuojiRight() // 舵机右转
{
zhuanjiao = 7;
Delayms(300);
}
void DuojiLeft() // 舵机左转
{
zhuanjiao = 23;
Delayms(300);
}
--------------------------------
while(1)
{
zhuanjiao = 15;
Delayms(300);
huanjiao = 7;
Delayms(300);
zhuanjiao = 23;
Delayms(300);
}
舵机一直循环 → 右 → 中 → 左 → 右 → 中 → 左......
归中调试:可以将zhuanjiao的值尝试用12,13,14,16,这几个附近的值代替