51单片机控制舵机转角的C语言程序

刚开始学习51单片机,对定时器不是很明白, 有点云里雾里导致对以下这个程序不太理解,以下程序从网上搜到的,我拷贝到KEIL软件中运行,下载到单片机,连接舵机 可以运行,程序没有什么错误,想请教大虾:

就是这个程序中定时器0 定时器1 以及主程序中while函数他们都是怎样运行的

#include<reg52.h>
typedef unsigned int uint;
typedef unsigned char uchar;
sbit pwm=P0^3;//输出PWM信号
uint pwm_value=1500;//初值为1.5ms

uint value[]={1500,1000,1500,2000,1500};//
void delay_ms(uint x)
{
uint i;
while(x--)for(i=0;i<125;i++);
}
void InitTimer(void)
{
TMOD=0x11;//开定时器0,1
TH0=-20000/256;//定时20MS,20MS为一个周期
TL0=-20000%256;
TH1=-1500/256;//定时1.5MS,这时舵机处于0度
TL1=-1500%256;
EA=1;//开总断
TR0=1;//开定时器0
ET0=1;
TR1=1;//开定时器1
ET1=1;
}
void timer0(void) interrupt 1//定时器0中断函数
{
pwm=1;
TH0=-20000/256;
TL0=-20000%256;
TR1=1;
}

void timer1(void) interrupt 3//定时器1中断函数
{
pwm=0;
TH1=-pwm_value/256;
TL1=-pwm_value%256;
TR1=0;
}
void main(void)//主函数
{
uchar i;
InitTimer();
pwm_value=1500;
while(1)
{
for(i=0;i<5;i++)
{
pwm_value=value[i];//通过数组就可以改变舵机的转角度
delay_ms(1000);
}
}
}
以上程序实现:以51单片机89C52用定时器模拟PWM信号去控制舵机转角,舵机的控制是在控制线输入一个周期性的正向脉冲PWM信号,这个周期脉冲信号的高电平时通常在0.5ms~2.5ms之间,而舵机的控制频率在50HZ~200HZ之间。0.5ms为-90度,它是舵机右转极限位置、1.0ms为-45度、1.5ms为0度,这时舵机处于静止、2.0ms为+45度、2.5ms为+90度,它是舵机左转极限位置。我们只需改变正脉冲的时间,即可转变舵机转角。

定时器0表示的是脉冲总周期20ms,定时器1表示的是正脉冲宽度(如pwm_value = 1500时表示正脉冲宽度为1.5ms), 而while循序只是为了改变正脉冲宽度。运行过程是:定时器0和定时器,1同时开启,此时pwm = 1,定时器1的时间到了之后pwm = 0,并关闭定时器1,等待脉冲总周期达到20ms即定时器0中断,在定时器0的中断服务中又将pwm赋值为1并开启定时器1……以这样的方式循环就可以控制舵机转动了!
温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-04-07
舵机频率50hz就是说一周期是20ms,占空比在百分之2.5到12.5可以从-90转到90度
单片机内部有工作的晶振频率,定时器就是基于这个频率计时,根据程序可以知道,20ms计时20000,所以计时器每加一的时间为1us,这个程序的意思就是先工作定时器0,20ms后输出置为1并打开定时器1,定时器1计时到1.5ms后触发中断使得输出为0,即占空比为1.5/20=百分之7.5,中间位置
定时器的寄存器加到0会触发中断,所以寄存器都写负数,如想要20ms就写-20000,这样往上加到0需要的计数的次数就为20000,一次计数为1us,所以为20ms,而寄存器是由两个八位寄存器组成的,所以20000要分开写
建议有时间可以去看一下郭天祥老师的51单片机视频,能搜到而且不多,貌似第三集是讲的定时器追问

打开定时器0,定时20毫秒,进入定时器0中断函数,执行pwm=1,输出高电平,同时打开定时器1,定时1.5毫秒,进入定时器1中断函数,执行pwm=0,输出低电平,执行定时器1计时到1.5ms后触发中断使得输出为0,在定时器1计时1.5毫秒的过程中,是高电平,在定时器0计时20毫秒的过程中,是低电平,这样一个周期就是20+1.5=21.5毫秒了,那为什么还说是20毫秒的周期呢

追答

因为定时器0计时完进入中断后计时的寄存器被重新赋值:
TH0=-20000/256;
TL0=-20000%256;
然后打开定时器1,此时1和0是同时工作的,所以还是20ms以后,而不是定时器1工作完了0才工作

追问

在整个函数中开定时器0 TR0=1;始终是开着的 也就是说定时器零一直在定时,一直在做0-20毫秒的周期定时 ,定时器1在这个周期的前1.5毫秒中是开着的,然后1.5毫秒后TR1=0;关闭定时器1

追答

对!

本回答被提问者采纳