基于51单片机的高精度舵机控制程序PWM 定时器

摘    要

虽然舵机的控制原理比较简单统一,但是PWM控制舵机的程序实现方式多种多样,有的使用延时(delay(ms)),有的使用定时器(time),而网上搜到的大部分控制代码却质量一般,控制精度都需要提高,就要对单片机定时器有详细的了解,否则延时将出现偏差。

本文使用单片机T2定时器,这个定时器大多数人很少使用它,而却不知道它有一个非常优秀的功能就是定时自动重载功能。利用这个功能能够更为精确的对定时器进行设定,可控制精度在1个机器周期(12M晶振下就是1us),T0、T1都需要手动重载,其精度无法很好的控制。

关键词:51单片机 舵机 精准控制 PWM T2定时器

 

本程序硬件需求

/*------------------------------
硬件需求: 12T系列单片机(8051内核)
                     拥有T2定时器
                     12M时钟晶振
                     P2_0输出控制
                     舵机角度范围在0~180 高电平范围0.5ms~2.5ms 20ms周期 
--------------------------------*/


软件仿真演示(精准的50Hz的PWM信号)

基于51单片机的高精度舵机控制程序PWM 定时器_第1张图片

 

基于51单片机的高精度舵机控制程序PWM 定时器_第2张图片

程序设计思想:

根据舵机对PWM的需求,我们可以得知在20ms的周期中,我们需要在输出开始为高电平,在高电平结束时触发中断改为低电平,低电平结束后由触发中断将其设置为输出高电平,如此循环往复。

其中我们可以发现,我们的定时器是不断根据角度的设定而变化的,而定时器的工作需要在计时高电平与低电平间来回切换,这个定时器定时下次时间是通过装载在RCAP中的初始值决定了,于是我们完全可以通过设定RCAP2L,RCAP2H来改变下一次的定时时间,根据这个思想 定时器中断中便如此设计。            if(SW)的分支语句 将20ms分为高低电平的定时 而且可以确定两者之和是20ms 也就是说完成了20ms的周期PWM波的输出。

具体功能见代码 ,注释,有问题请在评论区留言

// Header:舵机控制程序
// File Name: 
// Author:程蒙蒙(QQ1058515967)
// Date:2018年9月12日
//Description:基于12T系列单片机且有T2定时器的单片机舵机控制程序
//,本程序控制精度高(1us),定时器自动控制舵机转动
/*------------------------------
硬件需求: 12T系列单片机(8051内核)
					 拥有T2定时器
					 12M时钟晶振
					 P2_0输出控制
					 舵机角度范围在0~180 高电平范围0.5ms~2.5ms 20ms周期 
--------------------------------*/

#include 

#define T2_PWMout P2_0  //舵机控制端
unsigned int PWMTimes=0;//高电平时间
unsigned char angle=0; //测试角度
void T2_Init();//初始化定时器2
void SetMotoangle(float angle);//设置舵机角度
void Delay100ms();		//@12.000MHz
void main()
{
	bit SWdir=0;
    T2_Init();//初始化定时器
    while(1)//演示程序,舵机左右摆动 
			{
				if(angle>180)SWdir=0;
				else if(angle==0)SWdir=1;
				
        SetMotoangle(SWdir?angle++:angle--);
				Delay100ms();
    }
}

void T2_Init()
{
    unsigned int time=65536-20000;
    RCAP2L = TL2 = time;            //initial timer2 low byte
    RCAP2H = TH2 = time >> 8;       //initial timer2 high byte
    TR2 = 1;                        //timer2 start running
    ET2 = 1;                        //enable timer2 interrupt
    EA = 1;                         //open global interrupt switch
}
void SetMotoangle(float angle)
{
    //防止越界而损伤电机
    if(angle > 175) angle = 175;
    if(angle <5) angle = 5;

    PWMTimes=500+angle*2000.0/180;//计算出高电平时间


}
/* Timer2 interrupt routine */
void tm2_isr() interrupt 5 using 1
{
    static  bit SW=0;
    unsigned int T2count;
    TF2 = 0;//标志位清零
    SW=~SW;//状态取反
    T2_PWMout=SW;//更新输出
    if(SW)//低电平时间
    {
        T2count=0xB1E0+PWMTimes;//0xB1E0即为20ms中断用时
        RCAP2L=T2count;
        RCAP2H=T2count>>8;
    }
    else//高电平时间
    {
        T2count=0-PWMTimes;
        RCAP2L=T2count;
        RCAP2H=T2count>>8;
    }

}
void Delay100ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 195;
	j = 138;
	do
	{
		while (--j);
	} while (--i);
}


 

 

你可能感兴趣的:(单片机,51单片机,舵机,精准控制,PWM,T2定时器)