用51单片机怎么玩SG90舵机?

用51单片机怎么玩SG90舵机?,第1张

什么是舵机?

这是来自百度的解释:舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。

百度上还有很大一部分解释,但我觉得那都是放屁,看再多解释不如一张实物图来的实在。

怎么驱动这个东西?

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;
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1295384.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存