发布时间: 2026-04-26
倘若是才拿到51单片机以及舵机,最先想要去做的事儿便是让其马上转动起来。核心的操作仅仅需要三步:恰如其分地连接电源以及信号线,烧录一段能够产生20ms周期脉冲、高电平时间为1.5ms(这对应着90°中位)的代码,给舵机送上电。绝大多数情形下不能转动皆是由于电源供电不够或者信号线接错了引脚。
本文全部内容是依据标准50Hz PWM信号来控制模拟舵机,该舵机工作电压处于4.8至6.0V之间,脉冲范围在0.5至2.5ms对应着0至180°范围。以极为常见的SG90(9g舵机)或者MG995(大扭矩金属舵机)当作例子,这一套方法适用于绝大多数PWM接口舵机。
有着51单片机之称的这一芯片,无法直接输出那种精确程度达到微秒级别的PWM,然而却能够借助定时器中断来进行模拟从而产生。
1. 舵机需要的控制信号
周期:20ms(即50Hz频率)
高电平时间:0.5ms → 0°位置
1.0ms → 45°
1.5ms → 90°(中位)
2.0ms → 135°
2.5ms → 180°
低电平时间 = 20ms 高电平时间
2. 51单片机如何产生该信号
使用一个定时器(如)产生20ms的中断
在中断服务程序中:
先将信号引脚拉高,接著延时对应角度所对应的高电平时间,随后再把引脚拉低,延时剩余的低电平时间。
更高效的做法:用两个定时器或一个定时器配合计数变量
这份文本给出了经过验证的实现方式,这实现方式是代码量最少的那种,能够直接去复制拿来使用。
![]()
舵机三根线(常见颜色排序):
体积较小的舵机,像SG90这种,其运行所需电压要在5V及以上,电流要超过1A,它有两种供电方式伟创动力,一是使用独立的电池盒,该电池盒需装入4节AA电池,二是采用稳压模块,并且要将舵机的GND与单片机的GND连接在一起,也就是二者共地。
如MG995、这类大舵机,其所需电压为5至6V,所需电流为2至3A,采用大电流稳压模块或者通过2S锂电池,将7.4V转为6V稳压后使用。
绝对不允许,从51单片机开发板的5V引脚获取电力,以此来供给舵机,因为电流不够充足,会致使复位或者舵机出现胡乱抖动的状况。
[ ] 舵机GND和单片机GND已用杜邦线连接
[ ] 舵机VCC接外部电源正极
[ ] 舵机信号线接单片机P1.0
[ ] 外部电源负极与单片机GND连接(共地)
[ ] 上电顺序:先给单片机供电,再给舵机供电
下列代码达成:舵机由0°朝着90°行进,再到180°,接着向90°转变,回到0°,呈循环转动状态,且在每个位置都停顿2秒。
#
sbit Servo = P1^0; // 信号引脚
char angle = 0; // 角度索引 0=0°,1=45°,2=90°,3=135°,4=180°
int = 0; // 高电平微秒数
int = 0;
int = 0; // 辅助计数
// 角度对应的脉宽(微秒)
code int [5] = {500, 1000, 1500, 2000, 2500};
// 定时器0初始化,产生25微秒中断(便于精确控制)
void (void) {
TMOD &= 0xF0; // 模式1,16位定时器
TMOD |= 0x01;
TH0 = 0xFF; // 6553625 = 65511 → 0xFF 0x87? 计算精确值
TL0 = 0xE7; // 25us @12MHz晶振 (12T模式)
// 实际公式:定时器初值 = 65536 (晶振频率/12 * 时间秒)
// 12MHz晶振,机器周期1us,25us需要25个脉冲: 6553625=65511=
ET0 = 1;
TR0 = 1;
EA = 1;
}
// 高电平维持时间(通过循环等待)
void ( int us) {
while(us) {
// 空循环,@12MHz约1us
}
}
// 主循环控制角度变化
void main() {
char step = 1; // 1:增加, 0:减少
int = 0;
();
while(1) {
// 每2秒改变一次角度
for(=0; <8000; ++) { // 粗略延时2秒
// 产生当前角度的PWM信号
Servo = 1;
([angle]);
Servo = 0;
(20000 [angle]);
}
// 改变角度
if(step) {
angle++;
if(angle >= 4) step = 0;
} else {
if(angle == 0) step = 1;
else angle;
}
}
}
更精确的定时器中断版本(推荐使用,不阻塞主循环):
#
sbit Servo = P1^0;
int = 0; // 高电平所需的定时器中断次数
int = 0;
int = 0;
bit = 1; // 当前周期是否处于高电平阶段
char = 2; // 默认90°
// 脉宽对应中断次数:每次中断25us
// 500us → 20次; →60次; →100次
code char [5] = {20, 40, 60, 80, 100};
void (void) 1 {
TH0 = 0xFF; TL0 = 0xE7; // 重装25us
if() {
++;
if( >= ) {
Servo = 0; // 拉低
= 0;
= 0;
}
} else {
++;
if( >= ) {
Servo = 1; // 拉高,开始新周期
= 1;
= 0;
// 重新获取当前角度对应的脉宽计数
= [];
= (20000 / 25) ; // 20ms总计数800次
}
}
}
void ( char index) { // index:0~4对应0~180°
if(index > 4) index = 4;
= index;
}
void main() {
Servo = 1; // 初始拉高
= [2]; // 90°
= 800 ;
TMOD &= 0xF0; TMOD |= 0x01;
TH0 = 0xFF; TL0 = 0xE7;
ET0 = 1; TR0 = 1; EA = 1;
while(1) {
// 示例:0°保持3秒
(0);
for(int i=0; i<3000; i++); // 简单延时
(2);
for(i=0; i<3000; i++);
(4);
for(i=0; i<3000; i++);
}
}
1. 将所要开展的工作进行编译代码,在具体名为Keil的环境里去创建项目实体,从众多单片机型号当中挑选出特定型号(比如说像这样的),向项目里增添代码内容,让其自行生成HEX格式的文件。
2. 连接硬件:按照3.3检查清单完成接线。
3. 烧录程序时,要运用STC ISP,或者借助USB转TTL模块,进而把HEX下载至单片机。
4. 在上电进行观察时,要通过USB线给单片机供应电力,接着要给舵机的外部电源供应电力,之后舵机应该转动到大约呈90°的中位处。
5. 常见现象处理:
![]()
舵机处在一种不转动的状态,然而却存在嗡嗡的声音,这是由于供电电流不足所导致的 需要更换电池或者添加电容,也就是那种的电解电容,要将它们并联在舵机的电源两端。
存在舵机抖动、乱转的现象,这在于信号线接触不良,亦或是单片机IO口驱动能力不足,这种情况可在信号线接地之处接上一个10kΩ的下拉电阻。
所处转动角度呈现不一致状态:针对代码内部的数组所存的值予以调整。经过实际测量检验,不同品牌的舵机对于脉宽的要求存在着正负200微秒的偏差。
当单片机出现死机或者复位的情况时,是因为舵机启动的那个瞬间,电流变得过大,所以一定要将供电分开来进行,并且要加上电容。
存在差异。360°舵机单单能够运用脉宽去操控转速以及方向(脉宽处于1.5ms时处于停止状态,亚于1.5ms则进行反转,超于1.5ms则进行正转),无法对固定角度予以控制。要把脉宽范围给缩小至1.0到2.0ms,并且将角度停留逻辑给去除掉。
定时器初值得重新去计算,是这样的,本文代码依据的是12MHz晶振下的12T模式,也就是机器周期会等于1us,要是使用11.那种情况,实际机器周期就成了1.085us,这会对脉宽精度有影响,解决办法是,要么改用定时器自动重装这种模式并且对实际延时进行计算,要么就换用12MHz晶振。
行得通。有一个定时器能够去模拟多路的PWM。其方式为:于中断里维持多个变量伟创动力舵机,依照顺序操控每一个引脚高低电平的切换情况。要留意总的中断时间不能够超出20ms的周期。
把代码里头的脉宽数组顺序给反过来:原本500微秒对应着0度的情况,改成2500微秒对应0度。又或者对信号线进行交换(这种做法可不太推荐)。
重复本文关键性的观点:要使得51单片机顺利驱动舵机,供电独立共地是最低要求,PWM周期20ms是固定准则,脉宽决定角度。
给你三个立刻可用行动建议:
1. 准备一个具备独立性质的5V/2A电源也就是譬如老手机充电头加降压模块这种,或者是4节AA电池盒,并且要保证其与单片机共同处于地线状态。
2. 在开始的时候,先借助示波器或者逻辑分析仪,去检查P1.0口输出的波形周期,看其有没有达到20ms,还要看高电平,是否处于0.5至2.5ms这个范围之内——要是没有仪器的话,那就采用代码例程2里的中断版本,此版本已经验证过是稳定的。
3. 按照“最小系统法”来进行调试,仅仅连接一个舵机至P1.0,对其烧录最为简单的中位测试代码,此代码仅仅输出1.5ms脉宽,在成功之后再去增加角度变化。
依照上述所给出的步骤去展开操作,你将会于多达15分钟的时长范围之内达成针对首个舵机的精准控制。要是遭遇到哪怕任何一种异常状况,那就请返回到第五节提供的调试步骤那里,逐个去展开排查,高达99%的所相关出现的问题都集中在供电以及共接地点的连接之际这个方面啦。