找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 737|回复: 2
收起左侧

注释很详细的单片机红外循迹智能小车程序

[复制链接]
ID:1078833 发表于 2023-5-21 09:07 | 显示全部楼层 |阅读模式
  1. #include <reg52.h>                                  //包含51单片机相关的头文件

  2. #define bint    unsigned int                          //重定义无符号整数类型
  3. #define char   unsigned char                         //重定义无符号字符类型

  4. char code  Roadshow[]={0x03,0x9F,0x25,0x0D,0x99,  //定义数码管显示数据
  5.                             0x49,0x41,0x1F,0x01,0x19};//0,1,2,3,4,5,6,7,8,9

  6. char code  Recitative[]={0x07,0x0A,0x1B,0x1F,0x0C,0x0D,0x0E,0x00,0x0F,0x19};

  7. char IRCOM[7];

  8. static unsigned int Led Flash;                         //定义闪动频率计数变量

  9. unsigned char Run Flag=0;                              //定义运行标志位
  10. bit Enable Light=0;                                    //定义指示灯使能位
  11. /***********完成基本数据变量定义**************/
  12. bit S1State=P1^0;                                    //定义S1状态标志位
  13. bit S2State=P1^1;                                    //定义S2状态标志位
  14. bit B1State=P1^2;                                    //定义B1状态标志位
  15. bit Instate=P1^3;                                    //定义IR状态标志位
  16. bit Understate=P1^4;                               //定义运行停止标志位
  17. bit Attestation=P1^5;                                //定义Frontier状态标志位
  18. bit Interstate=P1^6;                                //定义Lefter状态标志位
  19. bit Rightist=P1^7;                               //定义Rightist状态标志位
  20. /*************完成状态指示灯定义*************/
  21. bit S1=P3^2;                                         //定义S1按键端口
  22. bit S2=P3^4;                                         //定义S2按键端口
  23. /*************完成按键端口的定义*************/      
  24. bit Left Led=P2^0;                                    //定义前方左侧指示灯端口
  25. bit Right Led=P0^7;                                   //定义前方右侧指示灯端口
  26. /*************完成前方指示灯端口定义*********/
  27. bit Lefter=P3^5;                                     //定义前方左侧红外探头
  28. bit Right=P3^6;                                    //定义前主右侧红外探头
  29. bit Frontier=P3^7;                                     //定义正前方红外探头
  30. /*************完成红外探头端口定义***********/
  31. bit M1A=P0^0;                                        //定义电机1正向端口
  32. bit M1B=P0^1;                                        //定义电机1反向端口
  33. bit M2A=P0^2;                                        //定义电机2正向端口
  34. bit M2B=P0^3;                                        //定义电机2反向端口
  35. /*************完成电机端口定义***************/
  36. bit B1=P0^4;                                         //定义话筒传感器端口
  37. bit RL1=P0^5;                                        //定义光敏电阻端口
  38. bit SB1=P0^6;                                        //定义蜂鸣端口
  39. /*********完成话筒,光敏电阻,蜂鸣器.端口定义**/
  40. bit IRIN=P3^3;                                       //定义红外接收端口
  41. /*********完成红外接收端口的定义*************/
  42. #define Shortstop P2                                   //定义数码管显示端口

  43. extern void Control(char Archetype);                //声明小车控制子程序

  44. void delay(unsigned char x)                           //0.14mS延时程序
  45. {
  46.   unsigned char i;                                    //定义临时变量
  47.   while(x--)                                          //延时时间循环
  48.   {
  49.     for (i = 0; i<13; i++) {}                         //14mS延时
  50.   }
  51. }

  52. void Delay()                                          //定义延时子程序
  53. { bint Daytime=30000;                               //定义延时时间变量
  54.   while(Daytime--);                                 //开始进行延时循环
  55.   return;                                             //子程序返回
  56. }


  57. void Control(char Archetype)                        //定义小车控制子程序
  58. {
  59. M1A=0;                                               //将电机1正向电平置低
  60. M1B=0;                                               //将电机1反向电平置低
  61. M2A=0;                                               //将电机2正向电平置低
  62. M2B=0;                                               //将电机2反向电平置低
  63. Left Led=1;                                           //关闭前方左侧指示灯
  64. Right Led=1;                                          //关闭前方右侧指示灯
  65. Delay();                                             //将此状态延时一段时间
  66. switch(Archetype)                                      //判断小车控制指令类型
  67. {  case 1: //前进                                    //判断是否是前进
  68.     { M1A=1;                                          //将电机1正向端口置高
  69.       M2A=1;                                          //将电机2正向端口置高
  70.       Shortstop=Roadshow[1];                        //数码管显示前进状态
  71.       break;                                          //退出判断
  72.     }
  73.     case 2: //后退                                    //判断是否是后退
  74.     { M1B=1;                                          //将电机1反向端口置高
  75.       M2B=1;                                          //将电机2反向端口置高                                 
  76.       Shortstop=Roadshow[2];                        //数码管显示后退状态
  77.       Right Led=0;                                     //将前方右侧指示灯置低(亮)
  78.       Left Led=0;                                      //将前方左侧指示灯置低(亮)
  79.       break;                                          //退出判断
  80.     }
  81.     case 3: //左转                                    //判断是否是左转
  82.     { M1B=1;                                          //将电机1反向端口置高
  83.       M2A=1;                                          //将电机2正向端口置高
  84.       Shortstop=Roadshow[3];                        //数码管显示左转状态
  85.       Left Led=0;                                      //将前方左侧指示灯置低(亮)
  86.       break;                                          //退出判断
  87.     }
  88.     case 4: //右转                                    //判断是否是右转
  89.     { M1A=1;                                          //将电机1正向端口置高
  90.       M2B=1;                                          //将电机2反向端口置高
  91.       Shortstop=Roadshow[4];                        //数码管显示右转状态
  92.       Right Led=0;                                     //将前方右侧指示灯置低(亮)
  93.       break;                                          //退出判断
  94.     }
  95.     default:                                          //默认情况下的判断
  96.     {
  97.      break;                                           //直接退出判断
  98.     }
  99. }
  100. }

  101. void Biobreak() interrupt 4                           //定义串口通信子程序
  102. {unsigned char Recitative;                              //定义串口数据接收变量
  103. if(RI==1)                                            //判断是否接收数据
  104. { Recitative=SBUF;                                     //将接收到的数据放入暂时变量
  105.    if(Recitative<10)                                    //判断接收到的数据是否小于10
  106.    {
  107.     Shortstop=Roadshow[Recitative];                   //将接收到的数据通过数码管显示出来
  108.     Control(Recitative);                             //将串口数据置于小于状态
  109.    }
  110.    SBUF=Recitative;                                     //向电脑返回当前接收到的数据
  111.    RI=0;                                              //清除接收中断标志位
  112. }
  113. if(TI==1)                                            //判断是否是发送中断
  114. {
  115.    TI=0;                                              //清除发送中断标志位
  116. }
  117. }

  118. void IR_IN() interrupt 2 using 0                      //定义INT2外部中断函数
  119. {
  120.   unsigned char j,k,N=0;                              //定义临时接收变量
  121.    
  122.   EX1 = 0;                                            //关闭外部中断,防止再有信号到达   
  123.   delay(15);                                          //延时时间,进行红外消抖
  124.   if (IRIN==1)                                        //判断红外信号是否消失
  125.   {  
  126.      EX1 =1;                                          //外部中断开
  127.          return;                                          //返回
  128.   }
  129.                            
  130.   while (!IRIN)                                       //等IR变为高电平,跳过9ms的前导低电平信号。
  131.   {
  132.       delay(1);                                       //延时等待
  133.   }

  134.   for (j=0;j<4;j++)                                   //采集红外遥控器数据
  135.   {
  136.     for (k=0;k<8;k++)                                 //分次采集8位数据
  137.     {
  138.        while (IRIN)                                   //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
  139.        {
  140.          delay(1);                                    //延时等待
  141.        }
  142.       
  143.        while (!IRIN)                                  //等 IR 变为高电平
  144.        {
  145.          delay(1);                                    //延时等待
  146.        }
  147.    
  148.        while (IRIN)                                   //计算IR高电平时长
  149.        {
  150.          delay(1);                                    //延时等待
  151.          N++;                                         //计数器加加
  152.          if (N>=30)                                   //判断计数器累加值
  153.              {
  154.            EX1=1;                                     //打开外部中断功能
  155.                return;                                    //返回
  156.          }                  
  157.        }
  158.                                        
  159.       IRCOM[j]=IRCOM[j] >> 1;                         //进行数据位移操作并自动补零
  160.      
  161.       if (N>=8)                                       //判断数据长度
  162.       {
  163.          IRCOM[j] = IRCOM[j] | 0x80;                  //数据最高位补1
  164.       }
  165.       N=0;                                            //清零位数计录器
  166.     }
  167.   }
  168.    
  169.   if (IRCOM[2]!=~IRCOM[3])                            //判断地址码是否相同
  170.   {
  171.      EX1=1;                                           //打开外部中断
  172.      return;                                          //返回
  173.   }

  174.   for(j=0;j<10;j++)                                   //循环进行键码解析
  175.    {
  176.       if(IRCOM[2]==Recitative[j])                       //进行键位对应
  177.       {
  178.         P2=Roadshow[j];                            //数码管显示相应数码
  179.       }
  180.    }
  181.    
  182.    switch(IRCOM[2])
  183.    {
  184.       case 0x1A:                                      //前进
  185.       {
  186.          Control(1);                               //小车前进
  187.          break;
  188.       }
  189.       case 0x05:                                      //后退
  190.       {
  191.          Control(2);                               //小车后退
  192.          break;
  193.       }
  194.       case 0x01:                                      //左转
  195.       {
  196.          Control(3);                               //小车左转
  197.          break;
  198.       }
  199.       case 0x03:                                      //右转
  200.       {
  201.          Control(4);                               //小车右转
  202.          break;
  203.       }
  204.       case 0x12:                                      //电源
  205.       {
  206.          Control(5);                               //停止
  207.          break;
  208.       }
  209.    
  210.    }
  211.    
  212.    EX1 = 1;                                           //外部中断开
  213. }



  214. void main(void)                                       //主程序入口
  215. {
  216. bit Flagella=0;                                       //定义可执行位变量

  217. Led Flash=3000;                                       //对闪灯数据进行初始化
  218. TMOD=0x01;                                           //选择定时器0为两个16位定时器
  219. TH0=0xFF;                                            //对定时器进行计数值进行初始化
  220. TL0=0x49;                                            //同上,时间大约为25uS
  221. TR0=1;                                               //同意开始定时器0
  222. EX1=1;                                               //同意开启外部中断1
  223. IT1=1;                                               //设定外部中断1为低边缘触发类型
  224. ET0=0;
  225. SCON=80;                                             //设置串口模式为8位数据
  226. TMOD=33;                                             //设置定时/计数器模式
  227. TH1=0xFD;                                            //给定时器1高八位初始化初值
  228. TL1=0xFD;                                            //给定时器1低八位初始化初值
  229. TR1=1;                                               //开启定时器1
  230. ES=1;                                                //开启串口通信功能
  231. REN=1;                                               //开启接收中断标志
  232. EA=1;                                                //总中断开启
  233. Control(1);                                       //将小车置于前进状态
  234. Shortstop=Roadshow[0];                             //数码管显示数字0
  235. while(1)                                              //程序主循环
  236. {
  237.    
  238.     while(Led Flash--)                                 //闪灯总延时
  239.     {
  240.      if(RL1==0)                                       //判断光敏电阻的状态
  241.          { Right Led=1;                                    //将前方右侧指示灯点亮
  242.            Left Led=1;                                     //将前方左侧指示灯点亮
  243.          }
  244.          else                                             //在光敏电阻为不通的状态下
  245.          {
  246.            Right Led=0;                                    //将前方右侧指示灯熄灭
  247.            Left Led=0;                                     //将前方左侧指示灯熄灭
  248.          }
  249.          if(IRIN==0)                                      //判断延时期间是否有红外信号输入
  250.      {Flagella=1;                                      //将可执行标志位置1
  251.      }
  252.          if(S1==0)                                        //判断是否有S1按下
  253.          {
  254.           Control(8);                                  //将小车置于停止状态
  255.           Run Flag=1;                                      //改变小车运行状态标志位
  256.           S1State=!S1State;                               //改变S1按键标志位
  257.           Soto Extrusion;                                   //跳转到Extrusion标签
  258.          }
  259.          if(S2==0)                                        //判断是否有S2按下
  260.          {
  261.           Control(1);                                  //将小车置于前进状态
  262.           Run Flag=0;                                      //改变小车运行状态标志位
  263.           S2State=!S2State;                               //改变S2按键标志位
  264.           Soto Extrusion;                                   //跳转到Extrusion标签
  265.          }
  266.          Attestation=Frontier;                              //前方红外指示灯显示正前方红外探头状态
  267.          Interstate=Lefter;                              //左侧红外指示灯显示前方左侧红外探头状态
  268.          Rightist=Right;                            //右侧红外指示灯显示前主右侧红外探头状态
  269.      if(Frontier==0  || Lefter==1 || Right==1)        //判断正前方,前左侧,前右侧红外探头状态
  270.      {Control(2);                                  //改变小车状态为后退
  271.       SB1=!SB1;                                       //将蜂鸣器取反
  272.       Delay();                                        //调用延时子程序
  273.       SB1=!SB1;                                       //将蜂鸣器取反
  274.           Delay();                                        //调用延时子程序
  275.           SB1=!SB1;                                       //将蜂鸣器取反
  276.              Delay();                                        //调用延时子程序
  277.           SB1=!SB1;                                       //将蜂鸣器取反
  278.           Delay();                                        //调用延时子程序
  279.           SB1=!SB1;                                       //将蜂鸣器取反
  280.           Delay();                                        //调用延时子程序
  281.           SB1=!SB1;                                       //将蜂鸣器取反
  282.           Delay();                                        //调用延时子程序
  283.           SB1=!SB1;                                       //将蜂鸣器取反
  284.           Control(3);                                  //改变小车左转状态
  285.           Delay();                                        //调用延时子程序
  286.           SB1=!SB1;                                       //将蜂鸣器取反
  287.           Delay();                                        //调用延时子程序
  288.           SB1=!SB1;                                       //将蜂鸣器取反
  289.           Delay();                                        //调用延时子程序
  290.           SB1=!SB1;                                       //将蜂鸣器取反
  291.           Delay();                                        //调用延时子程序
  292.           SB1=!SB1;                                       //将蜂鸣器取反
  293.           Delay();                                        //调用延时子程序
  294.           SB1=!SB1;                                       //将蜂鸣器取反
  295.           Control(1);                                  //改变小车为前进状态
  296.           SB1=1;                                          //关闭蜂鸣器声音
  297.      }
  298.    
  299.     if(B1==0)                                         //判断是否有话筒信号输入
  300.     { if(Run Flag==0)                                  //判断小车当前的运行标志位
  301.       { Control(8);                                //将小车置于停止状态
  302.             Run Flag=1;                                    //改变小车运行标志位
  303.           }
  304.           else
  305.           { Control(1);                                //将小车置于前进状态
  306.             Run Flag=0;                                    //改变小车运行标志位
  307.           }
  308.           B1State=!B1State;                               //将话筒信号指示灯取反
  309.     }
  310.   }
  311. Extrusion:                                              //跳转标签

  312.    Understate=!Understate;                        //改变小车运行停止状态标志位
  313.                   
  314. }
  315. }

复制代码


回复

使用道具 举报

ID:161164 发表于 2023-5-22 10:46 | 显示全部楼层
在中断内延时,小白代码
回复

使用道具 举报

ID:1040201 发表于 2023-5-26 15:12 | 显示全部楼层
为啥 在中断中delay,中断中要快进快出
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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