找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2993|回复: 0
打印 上一主题 下一主题
收起左侧

红外避障舵机控制源程序

[复制链接]
跳转到指定楼层
楼主
ID:248426 发表于 2017-11-11 17:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. /*****************ZYDJ-CSB09A舵机控制*****************
  2. // 本程序主要将循迹程序、红外避障程序、遥控器程序综合在一起,通过主板按键切换
  3. ,蓝色小主板是右边按键S4切换,数码管显示1,就是循迹模式,按一下按键数码管显示2,
  4. 就是避障模式,按一下按键数码管显示3,就是红外遥控程序,周而复始切换模式。

  5. ******************************************************************/

  6. //注意程序只做参考之用,要达到最理想的寻迹效果,还需要同学们细心调试。

  7. #include<AT89X52.H>    //包含51单片机头文件,内部有各种寄存器定义
  8. #include<ZY-4WD_PWM.H>    //包含HL-1蓝牙智能小车驱动IO口定义等函数
  9. #include <intrins.h>
  10. #define uint    unsigned int                          //重定义无符号整数类型
  11. #define uchar   unsigned char                         //重定义无符号字符类型
  12. uchar code  LedShowData[]={0x03,0x9F,0x25,0x0D,0x99,  //定义数码管显示数据
  13.                             0x49,0x41,0x1F,0x01,0x19};//0,1,2,3,4,5,6,7,8,9
  14. uchar code  RecvData[]={0x19,0x46,0x15,0x44,0x43,0x40,0x0D,0x0E,0x00,0x0F};
  15. uchar IRCOM[7];
  16. unsigned char RunFlag=0;                              //定义运行标志位
  17. bit EnableLight=0;                                    //定义指示灯使能位
  18. sbit IRIN=P3^3;                                       //定义红外接收端口
  19. /*********完成红外接收端口的定义*************/
  20. #define ShowPort P2                                   //定义数码管显示端口
  21. sbit pwm=P1^6;//PWM信号输出口  舵机信号输出口
  22. unsigned char n,count,angle;//距离标志位,0.5ms次数,角度标识
  23. uchar i;
  24. extern void ControlCar(uchar CarType);                //声明小车控制子程序
  25. unsigned char temp = 1;
  26. void delay_nus(unsigned int i)  //延时:i>=12 ,i的最小延时单12 us
  27. {
  28.   i=i/10;
  29.   while(--i);
  30. }   
  31. void delay_nms(unsigned int n)  //延时n ms
  32. {
  33.   n=n+1;
  34.   while(--n)  
  35.   delay_nus(900);         //延时 1ms,同时进行补偿
  36.   
  37. }
  38. void delayms(unsigned char x)                         //0.14mS延时程序
  39. {
  40.   unsigned char i;                                    //定义临时变量
  41.   while(x--)                                          //延时时间循环
  42.   {
  43.     for (i = 0; i<13; i++) {}                         //14mS延时
  44.   }
  45. }
  46. void Delay5()                                          //定义延时子程序
  47. { uint DelayTime=30000;                               //定义延时时间变量
  48.   while(DelayTime--);                                 //开始进行延时循环
  49.   return;                                             //子程序返回
  50. }
  51. /*------------------------------------------------
  52.                     定时器01初始化
  53. //定时器1工作方式1 (舵机 ),定时器0 电机PWM调速控制信号
  54. ------------------------------------------------*/
  55. void ControlCar(unsigned char ConType)    //定义电机控制子程序
  56. {

  57. switch(ConType)                          //判断用户设定电机形式
  58. {
  59.   case 1:  //前进                         //判断用户是否选择形式1
  60.   {
  61.     run();   //调用前进函数
  62. angle=12 ;
  63. ShowPort=LedShowData[1];
  64.     break;
  65.   }
  66.   case 2: //后退                              //判断用户是否选择形式2
  67.   {
  68.     Rearrun ();  //后退  1600MS
  69. angle=12;
  70. ShowPort=LedShowData[2];                             //M2电机反转
  71.     break;
  72.   }
  73.   case 3: //左转                              //判断用户是否选择形式3
  74.   {
  75.     leftrun();    //调用小车左转  函数
  76.     angle=14;  
  77. ShowPort=LedShowData[3];                             //M2电机正转
  78. break;
  79.   }
  80.   case 4: //右转                              //判断用户是否选择形式4
  81.   {
  82.                                   //M1电机正转
  83.     rightrun();     //调用小车右转 函数
  84.     angle=10;                                      //M2电机反转
  85. ShowPort=LedShowData[4];
  86. break;
  87.   }
  88.   case 5: //停止                          //判断用户是否选择形式8
  89.   {
  90.     Stoptrun();
  91. angle=12;
  92. ShowPort=LedShowData[0];
  93. break;                                //退出当前选择
  94.   }
  95. }
  96. }
  97. void ControlCar_yaokong(unsigned char ConType)    //定义电机控制子程序 (红外遥控单独设置一个 switch  case  语句  )
  98. {

  99. switch(ConType)                          //判断用户设定电机形式
  100. {
  101.   case 1:  //前进                         //判断用户是否选择形式1
  102.   {
  103.     run();   //调用前进函数
  104. angle=12 ;
  105. ShowPort=LedShowData[1];
  106.     break;
  107.   }
  108.   case 2: //后退                              //判断用户是否选择形式2
  109.   {
  110.     Rearrun ();  //后退  1600MS
  111. angle=12;
  112. ShowPort=LedShowData[2];                             //M2电机反转
  113.     break;
  114.   }
  115.   case 3: //左转                              //判断用户是否选择形式3
  116.   {
  117.     leftrun();    //调用小车左转  函数
  118.     angle=14;  
  119. ShowPort=LedShowData[3];                             //M2电机正转
  120. break;
  121.   }
  122.   case 4: //右转                              //判断用户是否选择形式4
  123.   {
  124.                                   //M1电机正转
  125.     rightrun();     //调用小车右转 函数
  126.     angle=10;                                      //M2电机反转
  127. ShowPort=LedShowData[4];
  128. break;
  129.   }
  130.   case 5: //停止                          //判断用户是否选择形式8
  131.   {
  132.     Stoptrun();
  133. angle=12;
  134. ShowPort=LedShowData[0];
  135. break;                                //退出当前选择
  136.   }
  137. }
  138. }
  139. void Robot_Avoidance()                   //机器人避障子程序
  140. {
  141.    //有信号为0  没有信号为1
  142.               if(LeftIRBZ ==1&&RightIRBZ ==1)  // 前面 没有障碍物  前速前进
  143.      {
  144.      run();   //调用前进函数
  145.      angle=12 ;
  146.      }
  147.       if(RightIRBZ ==0&&LeftIRBZ ==0)  //左右两边同时检测到障碍物
  148.       {   
  149.          
  150.      
  151.        Rearrun ();  //后退  1600MS
  152.        angle=12;
  153.             delay_nms(500);

  154.       leftrun();    //调用小车左转  函数
  155.                      angle=14;
  156.       delay_nms(1000);
  157.       }
  158.             
  159.       if(LeftIRBZ ==0&&RightIRBZ ==1)     //左边检测到障碍物
  160.       {
  161.       
  162.       rightrun();     //调用小车右转 函数
  163.       angle=10;
  164.         }
  165.       
  166.      if(RightIRBZ ==0&&LeftIRBZ ==1)  //右边检测到障碍物
  167.       {   
  168.          
  169.        leftrun();    //调用小车左转  函数
  170.                       angle=14;
  171.       }
  172. }
  173. //机器人循迹子程序
  174. void Robot_Traction()                     //机器人循迹子程序
  175. {
  176.      if(Left_1_led==0&&Right_1_led==0)
  177.      {
  178.      run();   //调用前进函数
  179.      angle=12 ;
  180.      }
  181.   else
  182. {     
  183.      if(Left_1_led==0&&Right_1_led==1)     //左边检测到黑线
  184.     {
  185.       
  186.     rightrun();     //调用小车右转 函数
  187.     angle=10;
  188.      }
  189.       
  190.    if(Right_1_led==0&&Left_1_led==1)  //右边检测到黑线
  191.    {   
  192.          
  193.                leftrun();    //调用小车左转  函数
  194.                angle=14;
  195.    }
  196. }
  197. }
  198. void Time1_Int() interrupt 3//舵机
  199. {
  200. TH1=0xff;
  201. TL1=0xa3;
  202. if(count<angle)//判断0.5ms次数是否小于角度标识
  203.     pwm=1;//确实小于,pwm输出高电平
  204.     else
  205.     pwm=0;//大于则输出低电平
  206. count=(count+1);//0.5ms次数加1
  207. count=count%40;//次数始终保持为40即保持周期为20ms
  208. }

  209. //主函数
  210. void main(void)
  211. {
  212. angle=12;//舵机居中
  213.     count=0;
  214.     P0=0XF0;   //关电机
  215.     //本实验学习的知识蜂鸣器,注意要在HJ-4WD头文件里定义IO口
  216. BUZZ=0; //50次检测K4确认是按下之后,蜂鸣器发出“滴”声响,然后启动小车。
  217. delay(50);
  218.     BUZZ=1;//响50ms后关闭蜂鸣器
  219. TMOD=0X11;
  220.     TH0= 0XFc;    //1ms定时
  221.     TL0= 0X18;
  222.     TR0= 1;
  223.     ET0= 1;
  224. EA = 1;      //开总中断
  225. TH1=0xff;
  226. TL1=0xa3;
  227. ET1=1;
  228. TR1= 1;
  229.    
  230. IT1=1;                                               //设定外部中断1为低边缘触发类型
  231.     Stoptrun();
  232. while(1) //无限循环
  233. {
  234.    if(P3_2 == 0)
  235.    {
  236.     delay_nms(10);
  237.     if(P3_2 == 0)
  238.     {
  239.        temp++;
  240.     while(!P3_2);
  241.     }
  242.    }
  243.    if(temp > 3)
  244.    {
  245.    temp = 1;
  246.    }
  247.    switch(temp)
  248.    {
  249.      case 1: ShowPort = LedShowData[1];Robot_Traction();EX1 = 0;break;
  250.   case 2: ShowPort = LedShowData[2];Robot_Avoidance();EX1 = 0;break;
  251.   case 3: ShowPort = LedShowData[3];EX1 = 1;break;
  252.    }
  253.   
  254.   }
  255. }
  256. //----------红外遥控-------------------------------------------------------------
  257. void IR_IN() interrupt 2 using 0                      //定义INT2外部中断函数
  258. {
  259.   unsigned char j,k,N=0;                              //定义临时接收变量
  260.    
  261.   EX1 = 0;                                            //关闭外部中断,防止再有信号到达   
  262.   delayms(15);                                        //延时时间,进行红外消抖
  263.   if (IRIN==1)                                        //判断红外信号是否消失
  264.   {  
  265.      EX1 =1;                                          //外部中断开
  266.   return;                                          //返回
  267.   }
  268.                            
  269.   while (!IRIN)                                       //等IR变为高电平,跳过9ms的前导低电平信号。
  270.   {
  271.       delayms(1);                                     //延时等待
  272.   }
  273.   for (j=0;j<4;j++)                                   //采集红外遥控器数据
  274.   {
  275.     for (k=0;k<8;k++)                                 //分次采集8位数据
  276.     {
  277.        while (IRIN)                                   //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
  278.        {
  279.          delayms(1);                                  //延时等待
  280.        }
  281.       
  282.        while (!IRIN)                                  //等 IR 变为高电平
  283.        {
  284.          delayms(1);                                  //延时等待
  285.        }
  286.    
  287.        while (IRIN)                                   //计算IR高电平时长
  288.        {
  289.          delayms(1);                                  //延时等待
  290.          N++;                                         //计数器加加
  291.          if (N>=30)                                   //判断计数器累加值
  292.       {
  293.            EX1=1;                                     //打开外部中断功能
  294.         return;                                    //返回
  295.          }                  
  296.        }
  297.                                        
  298.       IRCOM[j]=IRCOM[j] >> 1;                         //进行数据位移操作并自动补零
  299.      
  300.       if (N>=8)                                       //判断数据长度
  301.       {
  302.          IRCOM[j] = IRCOM[j] | 0x80;                  //数据最高位补1
  303.       }
  304.       N=0;                                            //清零位数计录器
  305.     }
  306.   }
  307.    
  308.   if (IRCOM[2]!=~IRCOM[3])                            //判断地址码是否相同
  309.   {
  310.      EX1=1;                                           //打开外部中断
  311.      return;                                          //返回
  312.   }
  313.   for(j=0;j<10;j++)                                   //循环进行键码解析
  314.    {
  315.       if(IRCOM[2]==RecvData[j])                       //进行键位对应
  316.       {
  317.        // ControlCar(j);
  318.   ControlCar_yaokong(j);                               //数码管显示相应数码
  319.       }
  320.    }
  321.    EX1 = 1;                                           //外部中断开
  322. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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