【酷】 自写-多路舵机控制程序,舵机控制不明白的进来看!

2020-01-12 17:18发布

呵呵,第一次发帖。一直潜水来着,发现这里高手如云的。好吧,讲讲今天讨论呢的。

舵机控制信号  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++;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
91条回答
追风少年
1楼-- · 2020-01-17 09:46
 精彩回答 2  元偷偷看……
司马朝阳007
2楼-- · 2020-01-17 11:30
正在学pwm
ahuang227
3楼-- · 2020-01-17 13:34
liweiqiang668 发表于 2012-4-26 21:42
看得不是很明白,我以前做多路PWM输出时用以下这种方法,不知效果如何。

void tim0_ISR() interrupt 1   / ...

一般的舵机中间值是1520us,你这样子,那个20us怎么出来呢?
568581185
4楼-- · 2020-01-17 15:16
如果要限制时间的话,是不是得另开一个定时器?
lyg407
5楼-- · 2020-01-17 17:03
568581185 发表于 2012-10-28 22:25
如果要限制时间的话,是不是得另开一个定时器?



什么是时间限制?   周期20MS  那么所有的信号,必须20MS 在给一次型号。 如果是1-2MS范围 那么 2MS *10=20MS     最多分10分,驱动10路舵机。 如果是0.5-2.5MS  那么2.5MS*8=20MS  最多分8路。驱动8路舵机。  这是一个定时器驱动这么多路,  如果2个定时器,那么可以驱动更多路了哦。
diyeyuye
6楼-- · 2020-01-17 19:17
 精彩回答 2  元偷偷看……

一周热门 更多>