单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:20406|回复:4

51单片机多功能智能小车(循迹、红外避障、遥控综合源程序)带详细注释

 [复制链接]
ID:321792发表于 2018-5-4 08:28|显示全部楼层
单片机源程序如下:
  1. /*****************ZY08-C智能循迹、遥控、避障、寻光机器人*****************
  2. //=====================================================================//
  3.              ZY08-C循迹、红外避障、遥控综合程序演示                 //
  4. //  本程序主要将循迹程序、红外避障程序、遥控器程序综合在一起,通过主板按键切换
  5. ,蓝色小主板是右边按键S4切换,如果客户买的是绿色大主板 ,那么就是主板左边的按键S1
  6. 切换,数码管显示1,就是循迹模式,按一下按键数码管显示2,就是避障模式,按一下按键
  7. 数码管显示3,就是红外遥控程序,周而复始切换模式。
  8. //---------------------------------------------------------------------//

  9. *  平台:ZY08-C智能循迹、遥控、避障、寻光机器人 + Keil U4 + STC89C52
  10. *  程序名称:5、ZY08-C循迹、红外避障、遥控综合程序
  11. *  公司:湖南智宇科教设备有限公司
  12. *  编写:智宇公司研发一部
  13. *  交流:智能车QQ:1018973181
  14. *  晶振:11.0592MHZ
  15. *  售后技术说明:免费开源,不支持客户自己修改程序分析与改正,可以提供我公司程序说明
  16. *  视频教程:本小车配套学习C语言详细视频教程,资料统一网盘下载
  17. ******************************************************************/  

  18. #include< REGX52.H> //包含51单片机相关的头文件
  19. #include< intrins.h>
  20. sbit LeftLed=P2^0;                 //定义前方左侧指示灯端口
  21. sbit RightLed=P0^7;                 //定义前方右侧指示灯端口
  22. sbit FontLled=P1^7;

  23. sbit LeftIR=P3^5;                 //定义前方左侧红外探头端口
  24. sbit RightIR=P3^6;                 //定义前方右侧红外探头端口
  25. sbit FontIR=P3^7;                 //定义前方正前方红外探头端口

  26. sbit M1A=P0^0;                   //定义左侧电机驱动A端
  27. sbit M1B=P0^1;                   //定义左侧电机驱动B端

  28. sbit M2A=P0^2;                   //定义右侧电机驱动A端
  29. sbit M2B=P0^3;                   //定义右侧电机驱动B端

  30. sbit B1=P0^4;                     //定义语音识识别传感器端口
  31. sbit SB1=P0^6;                   //定义蜂鸣器端口
  32. sbit IRIN=P3^3;                           //定义红外接收端口

  33. unsigned char code  LedShowData[]={0x03,0x9F,0x25,0x0D,0x99,  //定义数码管显示数据
  34.                          0x49,0x41,0x1F,0x01,0x19};//0,1,2,3,4,5,6,7,8,9
  35. unsigned char code  RecvData[]={0x19,0x46,0x15,0x43,0x44,0x40,0x0D,0x0E,0x00,0x0F};
  36. unsigned char IRCOM[7];
  37. static unsigned int LedFlash;                 //定义闪动频率计数变量
  38. bit EnableLight=0;                         //定义指示灯使能位
  39. #define ShowPort P2                         //定义数码管显示端口
  40. unsigned char temp = 1;
  41. void tingzhi()
  42. {
  43.    M1A=0;                         //将M1电机A端初始化为0
  44.    M1B=0;                         //将M1电机B端初始化为0
  45.    M2A=0;                         //将M2电机A端初始化为0
  46.    M2B=0;

  47. }

  48. void qianjin()
  49. {
  50.    M1A=1;                        
  51.    M1B=0;                        
  52.    M2A=1;                        
  53.    M2B=0;
  54. }

  55. void houtui()
  56. {
  57.    M1A=0;                        
  58.    M1B=1;                        
  59.    M2A=0;                        
  60.    M2B=1;
  61. }

  62. void zuozhuan()
  63. {
  64.    M1A=0;                        
  65.    M1B=1;                        
  66.    M2A=1;                        
  67.    M2B=0;
  68. }

  69. void youzhuan()
  70. {
  71.    M1A=1;                        
  72.    M1B=0;                        
  73.    M2A=0;                        
  74.    M2B=1;
  75. }

  76. void Delay1ms(unsigned int i)
  77. {
  78. unsigned char j,k;
  79. do{
  80.   j = 10;
  81.   do{
  82.    k = 50;
  83.    do{
  84.    _nop_();
  85.    }while(--k);    
  86.   }while(--j);
  87. }while(--i);

  88. }

  89. void delay_nus(unsigned int i)  //延时:i>=12 ,i的最小延时单12 us
  90. {
  91.   i=i/10;
  92.   while(--i);
  93. }  
  94. void delay_nms(unsigned int n)  //延时n ms
  95. {
  96.   n=n+1;
  97.   while(--n)  
  98.   delay_nus(900);       //延时 1ms,同时进行补偿
  99.   
  100. }  

  101. void delayms(unsigned char x)                 //0.14mS延时程序
  102. {
  103.   unsigned char i;                         //定义临时变量
  104.   while(x--)                             //延时时间循环
  105.   {
  106.    for (i = 0; i<13; i++) {}                 //14mS延时
  107.   }
  108. }

  109. void Delay()                             //定义延时子程序
  110. {
  111.   unsigned int DelayTime=30000;                 //定义延时时间变量
  112.   while(DelayTime--);                       //开始进行延时循环
  113.   return;                               //子程序返回
  114. }
  115. void ControlCar(unsigned char ConType)   //定义电机控制子程序
  116. {

  117.   tingzhi();
  118. switch(ConType)                   //判断用户设定电机形式
  119. {
  120.   case 1:  //前进                 //判断用户是否选择形式1
  121.   {
  122.    //tingzhi();                                     //进入前进之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  123.        //Delay1ms(50);
  124.        LeftLed = 0 ;
  125.        qianjin();
  126.    break;
  127.   }
  128.   case 2: //后退                   //判断用户是否选择形式2
  129.   {
  130.    // tingzhi();                                           //进入后退之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  131.    // Delay1ms(50);
  132.    LeftLed = 1 ;      
  133.        houtui();                       //M2电机反转
  134.    break;
  135.   }
  136.   case 3: //左转                   //判断用户是否选择形式3
  137.   {
  138.      //tingzhi();                                             //进入左转之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  139.        // Delay1ms(50);
  140.        zuozhuan();                     //M2电机正转
  141.        break;
  142.   }
  143.   case 4: //右转                   //判断用户是否选择形式4
  144.   {
  145.    // tingzhi();                                             //进入右转之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  146. //       Delay1ms(50);
  147.        youzhuan();                       //M1电机正转
  148.                              //M2电机反转
  149.        break;
  150.   }
  151.   case 8: //停止                   //判断用户是否选择形式8
  152.   {
  153.    tingzhi();
  154.        break;                       //退出当前选择
  155.   }
  156. }
  157. }

  158. void ControlCar_yaokong(unsigned char ConType)   //定义电机控制子程序       (红外遥控单独设置一个 switch  case  语句  )
  159. {

  160.   tingzhi();
  161. switch(ConType)                   //判断用户设定电机形式
  162. {
  163.   case 1:  //前进                 //判断用户是否选择形式1
  164.   {
  165.    tingzhi();                                     //进入前进之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  166.        Delay1ms(150);
  167.        LeftLed = 0 ;
  168.        qianjin();
  169.    break;
  170.   }
  171.   case 2: //后退                   //判断用户是否选择形式2
  172.   {
  173.    tingzhi();                                           //进入后退之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  174.    Delay1ms(150);
  175.    LeftLed = 1 ;      
  176.        houtui();                       //M2电机反转
  177.    break;
  178.   }
  179.   case 3: //左转                   //判断用户是否选择形式3
  180.   {
  181.      tingzhi();                                             //进入左转之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  182.        Delay1ms(150);
  183.        zuozhuan();                     //M2电机正转
  184.        break;
  185.   }
  186.   case 4: //右转                   //判断用户是否选择形式4
  187.   {
  188.      tingzhi();                                             //进入右转之前 先停止一段时间  防止电机反向电压冲击主板 导致系统复位
  189.        Delay1ms(150);
  190.      youzhuan();                       //M1电机正转  //M2电机反转
  191.        break;
  192.   }
  193.   case 8: //停止                   //判断用户是否选择形式8
  194.   {
  195.    tingzhi();
  196.        break;                       //退出当前选择
  197.   }
  198. }
  199. }
  200. void Robot_Avoidance()             //机器人避障子程序
  201. {

  202.    LeftLed=LeftIR;                 //前方左侧指示灯指示出前方左侧红外探头状态
  203.    RightLed=RightIR;               //前方右侧指示灯指示出前方右侧红外探头状态
  204.    FontLled= FontIR;
  205.    SB1=FontIR;

  206.    if(FontIR == 0)                   //如果前面避障传感器检测到障碍物
  207.    {
  208.      ControlCar(8);                 //停止
  209.      delay_nms (300);                             //停止300MS   防止电机反相电压冲击  导致系统复位
  210.        ControlCar(2);                             //后退  
  211.        delay_nms (1000);                             //后退1500MS  
  212.        ControlCar(3);                             //
  213.        delay_nms (1800);      
  214.   }
  215.    else
  216.    {
  217.      ControlCar(1);               //右侧没有信号时,开始向左转一定的角度
  218.      delay_nms (10);
  219.    }
  220.    ControlCar(1);
  221. }
  222. //机器人循迹子程序
  223. void Robot_Traction()               //机器人循迹子程序
  224. {
  225.    LeftLed=LeftIR;                 //前方左侧指示灯指示出前方左侧红外探头状态
  226.    RightLed=RightIR;               //前方右侧指示灯指示出前方右侧红外探头状态
  227.    FontLled= FontIR;
  228.    SB1=LeftIR;
  229.    if(LeftIR == 0&& RightIR == 0)   //三个红外检测到黑线,就前进
  230.    {
  231.      ControlCar(1);               //左侧没有信号时,开始向右转一定的角度
  232.      delay_nms (10);
  233.    }
  234.   
  235.    else if(LeftIR == 0&& RightIR == 1)
  236.    {
  237.      ControlCar(3);               //右侧没有信号时,开始向左转一定的角度
  238.      delay_nms (10);
  239.    }

  240.    else if(LeftIR == 1&& RightIR == 0)
  241.    {
  242.      ControlCar(4);               //右侧没有信号时,开始向左转一定的角度
  243.      delay_nms (10);
  244.    }
  245.    ControlCar(8);
  246. }

  247. void main()                     //主程序入口
  248. {
  249.   
  250.   bit RunFlag=0;                   //定义小车运行标志位
  251.   LedFlash=3000;                           //对闪灯数据进行初始化
  252.   //EX1=1;                                 //同意开启外部中断1
  253.   IT1=1;                                 //设定外部中断1为低边缘触发类型
  254.   EA=1;                                 //总中断开启
  255.   ControlCar(8);                   //初始化小车运行状态
  256.   while(1)                       //程序主循环
  257.   {
  258.          if(P3_2 == 0)
  259.        {
  260.          delay_nms(10);
  261.          if(P3_2 == 0)
  262.          {
  263.                temp++;
  264.              while(!P3_2);
  265.          }
  266.        }
  267.        if(temp > 3)
  268.        {
  269.        temp = 1;
  270.        }
  271.        switch(temp)
  272.        {
  273.              case 1:       ShowPort = LedShowData[1];Robot_Traction();EX1 = 0;break;
  274.            case 2: ShowPort = LedShowData[2];Robot_Avoidance();EX1 = 0;break;
  275.            case 3: ShowPort = LedShowData[3];EX1 = 1;break;
  276.        }
  277.   }
  278. }
  279. //----------红外遥控-------------------------------------------------------------
  280. void IR_IN() interrupt 2 using 0               //定义INT2外部中断函数
  281. {
  282.   unsigned char j,k,N=0;                     //定义临时接收变量
  283.   
  284.   EX1 = 0;                               //关闭外部中断,防止再有信号到达  
  285.   delayms(15);                           //延时时间,进行红外消抖
  286.   if (IRIN==1)                           //判断红外信号是否消失
  287.   {  
  288.      EX1 =1;                             //外部中断开
  289.        return;                             //返回
  290.   }
  291.                   
  292.   while (!IRIN)                           //等IR变为高电平,跳过9ms的前导低电平信号。
  293.   {
  294.      delayms(1);                         //延时等待
  295.   }

  296.   for (j=0;j<4;j++)                         //采集红外遥控器数据
  297.   {
  298.    for (k=0;k<8;k++)                       //分次采集8位数据
  299.    {
  300.      while (IRIN)                         //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
  301.      {
  302.        delayms(1);                       //延时等待
  303.      }
  304.     
  305.      while (!IRIN)                       //等 IR 变为高电平
  306.      {
  307.        delayms(1);                       //延时等待
  308.      }
  309.   
  310.      while (IRIN)                         //计算IR高电平时长
  311.      {
  312.        delayms(1);                       //延时等待
  313.        N++;                             //计数器加加
  314.        if (N>=30)                         //判断计数器累加值
  315.          {
  316.          EX1=1;                         //打开外部中断功能
  317.            return;                         //返回
  318.        }            
  319.      }
  320.                           
  321.      IRCOM[j]=IRCOM[j] >> 1;                 //进行数据位移操作并自动补零
  322.     
  323.      if (N>=8)                           //判断数据长度
  324.      {
  325.        IRCOM[j] = IRCOM[j] | 0x80;             //数据最高位补1
  326.      }
  327.      N=0;                               //清零位数计录器
  328.    }
  329.   }
  330.   
  331.   if (IRCOM[2]!=~IRCOM[3])                   //判断地址码是否相同
  332.   {
  333.      EX1=1;                             //打开外部中断
  334.      return;                             //返回
  335.   }

  336.   for(j=0;j<10;j++)                         //循环进行键码解析
  337.    {
  338.      if(IRCOM[2]==RecvData[j])                 //进行键位对应
  339.      {
  340.      // ControlCar(j);
  341.            ControlCar_yaokong(j);                     //数码管显示相应数码
  342.      }
  343.    }
  344.    EX1 = 1;                             //外部中断开
  345. }
  346. //-------------------------------------------------------------------------------------------------------
复制代码



评分

黑币 +50
收起理由
+ 50
共享资料的黑币奖励!

查看全部评分

ID:341867发表于 2018-6-1 01:01来自手机|显示全部楼层
楼主代码好多呀
ID:431514发表于 2019-4-29 07:44|显示全部楼层
楼主厉害了
ID:305511发表于 2021-2-13 17:45|显示全部楼层
楼主好棒!
ID:927901发表于 2021-6-9 23:00|显示全部楼层
楼主请问这么控制小车的速度呀

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

Powered by 单片机教程网