小R科技-WIFI机器人网·机器人创意工作室

 找回密码
 立即注册
查看: 20387|回复: 25

51单片机控制舵机示例代码

[复制链接]
发表于 2013-5-8 21:17:04 | 显示全部楼层 |阅读模式
从别的论坛看到的,算法很经典。
/*-------------------------------------------------------------------------
* 文 件 名:舵机控制程序  实现任意角度变化 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++;
}

回复

使用道具 举报

发表于 2013-5-9 08:30:10 | 显示全部楼层
单片机 学习中,能看懂部分了
回复 支持 反对

使用道具 举报

发表于 2013-5-9 14:19:24 | 显示全部楼层
这个算法一也不错。。。
回复 支持 反对

使用道具 举报

发表于 2013-5-9 18:04:49 | 显示全部楼层
不错不错  {:3_48:}
回复 支持 反对

使用道具 举报

发表于 2013-5-9 19:20:27 | 显示全部楼层
不太明白,Cycle 只有定义,在哪里用了。新手看不太明白,求详细注释。。
回复 支持 反对

使用道具 举报

发表于 2013-6-8 16:40:04 | 显示全部楼层
在学习中!!楼主辛苦
回复 支持 反对

使用道具 举报

发表于 2013-7-15 23:05:03 | 显示全部楼层
单片机学习中,能看懂,但是自己不会编。。
回复 支持 反对

使用道具 举报

发表于 2014-1-10 19:43:16 | 显示全部楼层
这个算法确实很不错,赞一个
回复 支持 反对

使用道具 举报

发表于 2014-8-12 10:37:05 | 显示全部楼层
学习中,看一半
回复 支持 反对

使用道具 举报

发表于 2014-8-16 10:35:42 | 显示全部楼层
cycle/N=N路的的平分时间。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

新品特惠推荐上一条 /2 下一条

QQ|QQ技术咨询1|QQ技术咨询2|商务合作微信1:xiaorgeek001|商务合作微信2:XiaoRGEEK|诚聘英才|Archiver|手机版|小R科技-WIFI机器人网·机器人创意工作室 ( 粤ICP备15000788号-6 )

GMT+8, 2024-4-26 17:53 , Processed in 1.177131 second(s), 24 queries .

Powered by XiaoR GEEK X3.4

© 2014-2021 XiaoR GEEK

快速回复 返回顶部 返回列表