这是来自百度的解释:舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。
百度上还有很大一部分解释,但我觉得那都是放屁,看再多解释不如一张实物图来的实在。
怎么驱动这个东西?PWM信号
什么是PWM信号? PWM ,英文名 Pulse Width Modulation ,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进 行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通 过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的 时间占据整个信号周期的百分比,例如方波的占空比就是 50%. 使用PWM来控制舵机,理解占空比是关键。如何实现PWM信号输出?
有一些芯片上是集成了PWM的,这可以在芯片手册和原理图上看出来。在这里,因为我使用的51芯片并没有PWM的管脚,所以我是用的软件来实现信号输出。当然,这种输出方式肯定是没有硬件PWM那么好,软件会存在一定的误差。
怎么控制舵机?向黄色信号线“灌入”PWM信号
怎么让舵机转动多少度这个问题,其实很简单。我的解决方法是,直接用现成的数据不就好了吗。
0.5ms-------------0度; 2.5% 对应函数中占空比为250
1.0ms------------45度; 5.0% 对应函数中占空比为500
1.5ms------------90 度; 7.5% 对应函数中占空比为 750 2.0ms-----------135 度; 10.0% 对应函数中占空比为 1000 2.5ms-----------180 度; 12.5% 对应函数中占空比为 1250 编程实现用51单片机使舵机运动起来,其实也挺简单的。用一个小实验来看看怎么让舵机动起来。这个小实验要让舵机每隔两秒转动一次。除了要用到PWM,还要用到定时器和中断。
先来配置定时器
void Time0Init()
{
//定时器模式选择
TMOD = 0X01;
//给定初始值 我们先定一个0.5ms
TL0 = 0X33;
TH0 = 0XFE;
//开启定时器
TF0 = 0;
TR0 = 1;
}
定时器开启了,但这还没完。我们还需要用到中断,因为定时器每到0.5ms的时候就会溢出,需要CPU响应中断才可以将溢出标志位清0。刚好定时器0就有中断寄存器,可以实现中断响应。
所以完整的定时器配置应该是这样的:
void Time0Init()
{
TMOD = 0X01;
TL0 = 0X33;
TH0 = 0XFE;
TR0 = 1;
TF0 = 0;
//开启定时器0中断
ET0 = 1;
//开启总中断
EA = 1;
}
有中断了,那自然就要有中断处理函数吧。定时器爆表的时间是0.5ms,上面说的占空比和让舵机转动角度的数据就派上用场了:
占空比:
就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比0.5ms-------------0度; 2.5% 对应函数中占空比为250
1.0ms------------45度; 5.0% 对应函数中占空比为500
1.5ms------------90 度; 7.5% 对应函数中占空比为 750 2.0ms-----------135 度; 10.0% 对应函数中占空比为 1000 2.5ms-----------180 度; 12.5% 对应函数中占空比为 1250 中断处理函数void Time0Handler() interrupt 1
{
cnt++; //统计爆表次数
//重新给初值:因为CPU响应中断之后,中断处理函数才会被执行,这个时候TL0和TH0都需要重新赋值
TL0 = 0X33;
TH0 = 0XFE;
if(cnt < jd) //jd 角度
{
sg90_con = 1; //给舵机高电平
}else{
sg90_con = 0; //给舵机低电平
}
if(cnt == 40) //一个周期20ms 0.5*40
{
cnt = 0;
}
}
主函数
void main()
{
jd = 1;
Time0Init(); //定时器初始化
sg90_con = 1; //舵机初始状态是高电平
while(1)
{
jd = 3; //转动90度
cnt = 0;
Delay2000ms();
jd = 1;
cnt = 0;
Delay2000ms();
}
}
全部代码:
#include "reg52.h"
sbit sg90_con = P1^1;
int jd;
int cnt = 0;
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Time0Init()
{
TMOD = 0X01;
TH0 = 0XFE;
TL0 = 0X33;
TR0 = 1;
TF0 = 0;
ET0 = 1;
EA = 1;
}
void main()
{
1
jd = 1;
Time0Init();
sg90_con = 1;
while(1)
{
jd = 3;
cnt = 0;
Delay2000ms();
jd = 1;
cnt = 0;
Delay2000ms();
}
}
void Time0Handler() interrupt 1
{
cnt++;
TH0 = 0XFE;
TL0 = 0X33;
if(cnt < jd)
{
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40)
{
cnt = 0;
sg90_con = 1;
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)