自动避障红外电动小车C51程序

自动避障红外电动小车C51程序
  1. 自动避障红外电动小车C51程序
  2.  
  3.  
  4.  
  5. #include"reg51.h"
  6.  
  7. #include<intrins.h>
  8.  
  9. #define uchar unsigned char
  10.  
  11. #define uint  unsigned int
  12.  
  13. #define left_infrare  0
  14.  
  15. #define right_infrare 1
  16.  
  17. #define dj_state1        0X5F      //前进
  18.  
  19. #define dj_state2        0X4F      //右转  
  20.  
  21. #define dj_state3        0X1F      //左转  
  22.  
  23. #define dj_state4        0X0F      //后退  
  24.  
  25. #define dj_state5        0XfF      //停车
  26.  
  27. #define light_off        0x0f      //关转向灯
  28.  
  29. #define left_light       0X5F      //左转向灯    两个是5f
  30.  
  31. #define right_light      0XaF      //右转向灯0xaf,两个是0xbf
  32.  
  33. #define back_light       0XcF      //刹车灯即后灯
  34.  
  35. #define front_light      0x3f      //前灯
  36.  
  37. #define light_on         0xff      //开所有灯
  38.  
  39. #define true  1
  40.  
  41. #define false 0
  42.  
  43. #define LCD_Data  P0
  44.  
  45. #define Busy  0x80            //用于检测LCD状态字中的Busy标识
  46.  
  47. sbit    c=P1^2;              //转向灯使能端
  48.  
  49. uchar code talk1[]={"backward"};
  50.  
  51. uchar code talk2[]={"forward"};
  52.  
  53. uchar code talk3[]={"Turnleft"};
  54.  
  55. uchar code talk4[]={"Turn right"};
  56.  
  57. uchar flage =0x00;
  58.  
  59. sbit  ledcs=P1^2;         //74H573的片选信号
  60.  
  61. //sbit  left_led=P0^2;     //左红外发射管
  62.  
  63. //sbit  right_led=P0^3;    //右红外发射管
  64.  
  65.  
  66.  
  67. sbit  LCD_RS = P1^5;     //LCD定义引脚
  68.  
  69. sbit  LCD_RW = P1^6;     //
  70.  
  71. sbit  LCD_E  = P1^7 ;
  72.  
  73. void Delay5Ms(void)
  74.  
  75. {
  76.  
  77. uint TempCyc = 5552;
  78.  
  79. while(TempCyc--);
  80.  
  81. }
  82.  
  83. //400ms延时
  84.  
  85. void Delay400Ms(void)
  86.  
  87. {uchar TempCycA = 5;
  88.  
  89. uint TempCycB;
  90.  
  91. while(TempCycA--)
  92.  
  93.    { TempCycB=7269;
  94.  
  95.      while(TempCycB--);
  96.  
  97.     }
  98.  
  99. }
  100.  
  101. //LCD读状态
  102.  
  103. unsigned char ReadStatusLCD(void)
  104.  
  105. {
  106.  
  107. LCD_Data = 0xFF;
  108.  
  109. LCD_RS = 0;
  110.  
  111. LCD_RW = 1;
  112.  
  113. LCD_E = 0;
  114.  
  115. LCD_E = 0;
  116.  
  117. LCD_E = 1;
  118.  
  119. while (LCD_Data & Busy);   //检测忙信号
  120.  
  121. return(LCD_Data);
  122.  
  123. }
  124.  
  125. //LCD写数据
  126.  
  127. void WriteDataLCD(unsigned char WDLCD )
  128.  
  129. {
  130.  
  131. ReadStatusLCD();  //检测忙
  132.  
  133. LCD_Data = WDLCD;
  134.  
  135. LCD_RS=1;
  136.  
  137. LCD_RW =0;
  138.  
  139. LCD_E = 0; //若晶振速度太高可以在这后加小的延时
  140.  
  141. LCD_E = 0; //延时 ,为了安全
  142.  
  143. LCD_E = 0; //延时
  144.  
  145. LCD_E = 1;
  146.  
  147. }
  148.  
  149. //LCD写指令
  150.  
  151. void WriteCommandLCD(unsigned char WCLCD,BuysC)
  152.  
  153. {
  154.  
  155. if (BuysC) ReadStatusLCD();   //根据需要检测忙,BuysC为0时忽略忙检测
  156.  
  157. LCD_Data = WCLCD;
  158.  
  159. LCD_RS= 0;
  160.  
  161. LCD_RW= 0;
  162.  
  163. LCD_E = 0;  //延时 ,为了安全
  164.  
  165. LCD_E = 0;
  166.  
  167. LCD_E = 0; //延时
  168.  
  169. LCD_E = 1;
  170.  
  171. }
  172.  
  173. void LCDInit(void)         //LCD初始化
  174.  
  175. {
  176.  
  177. Delay400Ms();
  178.  
  179. LCD_Data = 0;
  180.  
  181. WriteCommandLCD(0x38,0);  //三次显示模式设置,不检测忙信号
  182.  
  183. Delay5Ms();
  184.  
  185. WriteCommandLCD(0x38,0);
  186.  
  187. Delay5Ms();
  188.  
  189. WriteCommandLCD(0x38,0);
  190.  
  191. Delay5Ms();
  192.  
  193.  
  194.  
  195. WriteCommandLCD(0x38,1); //显示模式设置,开始要求每次检测忙信号
  196.  
  197. WriteCommandLCD(0x08,1); //关闭显示
  198.  
  199. WriteCommandLCD(0x01,1); //显示清屏
  200.  
  201. WriteCommandLCD(0x06,1); // 显示光标移动设置
  202.  
  203. WriteCommandLCD(0x0C,1); // 显示开及光标设置
  204.  
  205. }
  206.  
  207. //按指定位置显示一个字符
  208.  
  209. void DisplayOneChar(uchar X, uchar Y, uchar DData)
  210.  
  211. {
  212.  
  213. Y &= 0x1;
  214.  
  215. X &= 0xF;                 //限制X不能大于15,Y不能大于1
  216.  
  217. if (Y)
  218.  
  219. X |= 0x40;               //当要显示第二行时地址码+0x40;
  220.  
  221. X |= 0x80;               // 算出LCD的指令码
  222.  
  223. WriteCommandLCD(X, 0);   //这里不检测忙信号,发送地址码
  224.  
  225. WriteDataLCD(DData);
  226.  
  227. }
  228.  
  229. //按指定位置显示一串字符(只能写一行);
  230.  
  231. void DisplayListChar(uchar X, uchar Y,uchar ListLength, uchar  *DData,uchar n)
  232.  
  233. { uchar i;
  234.  
  235. Y &= 0x01;
  236.  
  237. X &= 0x0F;                 //限制X不能大于15,Y不能大于1
  238.  
  239. for(i=0;i<ListLength;i++)
  240.  
  241. { if (X <= 0x0F) //X坐标应小于0xF
  242.  
  243.     {   DisplayOneChar(X, Y, DData[i]); //显示单个字符
  244.  
  245.          if(n==true)Delay400Ms();
  246.  
  247.           X++;
  248.  
  249.     }
  250.  
  251.   }
  252.  
  253. }
  254.  
  255. /****************************
  256.  
  257. 红外线接收子程序,利用了中断的下降沿触发方式
  258.  
  259. ****************************/
  260.  
  261. void infrared_ray()interrupt 0  using 3
  262.  
  263. {  uchar i=90;
  264.  
  265.    flage=0x01;             //接受标志位
  266.  
  267.    while(i--);            //减小灵敏度
  268.  
  269.    EX0=0;               //关掉中断,等到发射方波后才开启,处于别动
  270.  
  271. }
  272.  
  273. // 延时子程序
  274.  
  275. void delay(uint n)
  276.  
  277. {
  278.  
  279.   while(--n);
  280.  
  281. }
  282.  
  283. //中断初始化
  284.  
  285. void Init0(void)
  286.  
  287. {  EA=1;
  288.  
  289.    IT0=1;
  290.  
  291.     }
  292.  
  293. /***************************************
  294.  
  295. /*原理是把中断打开并 发射方波,
  296.  
  297. 当有中断时就转到中断产生中断位为下一步转向做准备,
  298.  
  299. 当没有是关闭中断
  300.  
  301. ****************************************/
  302.  
  303. void seng_wave(uchar timer,bit n)//timer通过载波发射信号的时间,n->左右发射管的选择
  304.  
  305. {  uchar i;
  306.  
  307.    P1 |= 0X04;      //ledcs=1为74ls573为11脚为高电平时数据直接输出,为低时把数据锁存住,即保持
  308.  
  309.    IE |= 0X01;
  310.  
  311.    P0 |=0x0c;   //04
  312.  
  313.    for(i=timer;i>0;i--)
  314.  
  315.      { if(n)P0^=0x08;                      // 右发射管通过载波发射信号//00
  316.  
  317.         else P0^=0x04;                    // 左发射管通过载波发射信号//0c
  318.  
  319.          delay(100);                     //这里控制着灵敏度(控制38khz的方波的多少)和距离
  320.  
  321.       }                                     //timer*delay(x)即为发射管得到的平均电流
  322.  
  323.     P1 &= 0Xfb;
  324.  
  325.     IE &= 0Xfe;
  326.  
  327. }
  328.  
  329. //led转向灯指示子程序
  330.  
  331. void light_control(uchar deng)
  332.  
  333. {   ledcs=1;
  334.  
  335.     P0 =deng;
  336.  
  337.     ledcs=0;  //11111011
  338.  
  339. }
  340.  
  341. //电机和灯光的控制部分
  342.  
  343. void  control(uchar n,uchar dj_state,uchar light)
  344.  
  345. {   uchar i;
  346.  
  347.    // P1|=0x04;
  348.  
  349.      light_control(light);    //led转向指示灯
  350.  
  351.      delay(100);
  352.  
  353.      P2 =dj_state;              //电机的方向控制
  354.  
  355.     WriteCommandLCD(0x01,1); //LCD显示清屏
  356.  
  357.  
  358.  
  359.           switch(dj_state)
  360.  
  361.           { case dj_state2 :{ DisplayListChar(3,1,10,talk4,false);}break;
  362.  
  363.             case dj_state3: { DisplayListChar(3,1,8,talk3,false);}break;
  364.  
  365.             case dj_state4: { DisplayListChar(3,1,7,talk1,false); }break;
  366.  
  367.              default :break;
  368.  
  369.              }
  370.  
  371.           for(i=n;i>0;i--)
  372.  
  373.           {delay(2000);}
  374.  
  375.            P2=dj_state5;               //停车
  376.  
  377.          light_control(light_off);       //led关闭
  378.  
  379.         WriteCommandLCD(0x01,1); //LCD显示清屏
  380.  
  381.          P2=dj_state1;                     //前进
  382.  
  383.         if(dj_state1)
  384.  
  385.            { P1|=0X04;          //ledcs=1;
  386.  
  387.              P0=0x0f;
  388.  
  389.              P1&=0XFB;
  390.  
  391.              delay(100);
  392.  
  393.              DisplayListChar(0,0,7,talk2,false);
  394.  
  395.              }
  396.  
  397.      }
  398.  
  399. /****************************************
  400.  
  401. 避障主要控制部分
  402.  
  403. *****************************************/
  404.  
  405. void move_car(void)
  406.  
  407. {
  408.  
  409.    uchar temp =0x00;
  410.  
  411.    //左边红外管发射
  412.  
  413.        seng_wave(1,left_infrare);     //向下为中断开启有关闭后,要执行的语句
  414.  
  415.         if(flage==0x01){temp|=0x01;flage=0x00;}
  416.  
  417.        //右边红外管发射
  418.  
  419.          delay(30);
  420.  
  421.         seng_wave(1,right_infrare);    //向下为中断开启有关闭后,要执行的语句
  422.  
  423.         if(flage==0x01){temp|=0x02;flage=0x00;}
  424.  
  425.  
  426.  
  427.       //左边有障碍物,右转
  428.  
  429.      if(temp==0x01){control(2,dj_state2,left_light); temp =0x00;}
  430.  
  431.       //右边有障碍物,左转
  432.  
  433.       else if(temp==0x02) {control(2,dj_state3,right_light ); temp =0x00;}
  434.  
  435.        //两个方向都有障碍物,后退,右转
  436.  
  437.         else if(temp==0x03) {control(10,dj_state4,back_light );
  438.  
  439.               control(5,dj_state2,right_light ); temp =0x00;}      
  440.  
  441.  
  442.  
  443.     }
  444.  
  445. void main(void)
  446.  
  447. {  Init0();       //中断初始化
  448.  
  449.    P1 |= 0X04;    //开锁存器的控制位
  450.  
  451.    P0 = 0xFf;     //数据口的清零
  452.  
  453.    P1&=0XFB;      //关锁存器的控制位
  454.  
  455.    LCDInit();     //LCD初始化
  456.  
  457.    WriteCommandLCD(0x01,1);   //显示清屏
  458.  
  459.    delay(100);
  460.  
  461.    P2=dj_state1;
  462.  
  463.    DisplayListChar(0,0,8,talk2,false);
  464.  
  465. while(1)
  466.  
  467.    {    move_car();  //主要控制部分
  468.  
  469.         delay(200000);//延时
  470.  
  471.     }
  472.  
  473. }
  474.  
  475.  
  476.  
  477.  
复制代码

 
 
 

文件到原文下载,原文出自:https://bbs.usoftchina.com/thread-208705-1-1.html

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值