呵呵,第一次发帖。一直潜水来着,发现这里高手如云的。好吧,讲讲今天讨论呢的。
舵机控制信号 PWM 周期为20MS 高电平范围0.5ms-2.5ms 对应 0-180° 当多路舵机控制时候,目前这个方法最多只能8路控制 8*2.5(最大高电平时长)=20MS 刚好等于总周期。
下面贴上程序,本人小菜鸟,高手多多包涵。如果写的不好,请大家指点。多多学习,进步。
新论坛号码给封了,阿莫说一定要发帖,才能解锁。以后还想在论坛潜水呢, 大家帮帮忙啊。
/*-------------------------------------------------------------------------
* 文 件 名:舵机控制程序 实现任意角度变化 0.5MS-2.5MS 范围 周期20MS
* 芯 片:STC89C52RC
* 晶 振:12MHz
* 创 建 者:小强
* 创建日期:2011.10.25
* 修 改 者:
* 修改日期:
* 联系作者:
lyg407@126.com QQ:516380635
* 功能描述:两个按键控制 舵机从0-180°变化。。。
遇到问题: 如果使用平常方法给TH0 TL0 赋值 ,那样定时误差比较大。。
平常方法: TH0=(65536-500)/256;
TL0=(65536-500)%256;
而如果使用这种方法:
TH0=-num/256; //高电平时间
TL0=-num%256;
误差就比较小。 所以。。任何事情理论和实际都有可能会有区别。
所以都要实践得出结果。。
第一次INIT 初始化用平常方法可以,无所谓第一次中断。 。
但是后来定时 时间设置就不能就用平常方法了。而要用这个新颖的方法。
我也是看到别人是这么用的。。所以改了下,果然 效果很好。值得学习。
在KEIL仿真了一下。。然后观察寄存器 和平常方法是一致的。
-------------------------------------------------------------------------*/
#include<reg51.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define Cycle 20000 //定义周期
uint PWM_Value[8];
uchar order=0; //中断步长
sbit key1=P2^0;
sbit key2=P2^1;
//PWM的输出端口
sbit PWM_OUT0=P0^0;
sbit PWM_OUT1=P0^1;
sbit PWM_OUT2=P0^2;
sbit PWM_OUT3=P0^3;
void Init_Timer0() //定时器0 初始化
{
TMOD=0x01;
TH0=(65536-500)/256;
TL0=(65536-500)%256;
EA = 1;//打开总中断
ET0 = 1;//打开定时器0中断
TR0 = 1;//启动定时器0
PT0=1; //定时器0 设置为最高优先中断
PX0=0; // 外部中断0 设置最低中断
}
//延时
void delay(void)
{
uint i=100;
while(i--);
}
//按键检测
void keyscan()
{
if(key1==0) //高电平加
{
if(PWM_Value[0]<2000)
PWM_Value[0]+=2;
if(PWM_Value[1]<2000)
PWM_Value[1]+=2;
if(PWM_Value[2]<2000)
PWM_Value[2]+=2;
if(PWM_Value[3]<2000)
PWM_Value[3]+=2;
}
if(key2==0) //高电平减
{
if(PWM_Value[0]>1000)
PWM_Value[0]-=2;
if(PWM_Value[1]>1000)
PWM_Value[1]-=2;
if(PWM_Value[2]>1000)
PWM_Value[2]-=2;
if(PWM_Value[3]>1000)
PWM_Value[3]-=2;
}
delay();
}
//主函数
void main(void)
{
PWM_Value[0]=1500;
PWM_Value[1]=1500;
PWM_Value[2]=1500;
PWM_Value[3]=1500;
Init_Timer0();
while(1)
{
keyscan();
}
}
//定时器0 中断子函数
//这里输出几路波形 就应该为 20MS/N =X 那么X 就是N路平分时间
//在用N-高电平时间 就为该路低电平时间咯。 就这么简单。。。
void timer0(void) interrupt 1
{
switch(order)
{
case 1:PWM_OUT0=1;
TH0=-PWM_Value[0]/256; //第一路输出高电平时长
TL0=-PWM_Value[0]%256;
break;
case 2:PWM_OUT0=0;
TH0=-(5000-PWM_Value[0])/256; //第一路 输出低电平时长
TL0=-(5000-PWM_Value[0])%256;
break;
case 3:PWM_OUT1=1;
TH0=-PWM_Value[1]/256;
TL0=-PWM_Value[1]%256;
break;
case 4:PWM_OUT1=0;
TH0=-(5000-PWM_Value[1])/256;
TL0=-(5000-PWM_Value[1])%256;
break;
case 5:PWM_OUT2=1;
TH0=-PWM_Value[2]/256;
TL0=-PWM_Value[2]%256;
break;
case 6:PWM_OUT2=0;
TH0=-(5000-PWM_Value[2])/256;
TL0=-(5000-PWM_Value[2])%256;
break;
case 7:PWM_OUT3=1;
TH0=-PWM_Value[3]/256;
TL0=-PWM_Value[3]%256;
break;
case 8:PWM_OUT3=0;
TH0=-(5000-PWM_Value[3])/256;
TL0=-(5000-PWM_Value[3])%256;
order=0;
break;
default: order=0;
}
order++;
}
哈哈,这个问题我也奇怪, 我开始 是用第一种 方法 写的, 但是发现这样 出来的PWM 波形, 周期和高电平时长,都有大的误差,所以我就找了相关的参考,发现 都是用的第二种方法, 我做了试验, 第二种方法和第一种结果是一样的。可能是因为 单片机 处理两种语句 周期 时间 有区别吧。 个人理解,待高手指点吧。
一周热门 更多>