找回密码
 立即注册

QQ登录

只需一步,快速开始

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

自动入库避障智能小车的单片机源程序以及车库图和视频等资料分享

[复制链接]
跳转到指定楼层
楼主
很有用!
汇编程序仅仅可以进入一号库
C语言通过调节参数可以进入不同车库

引脚:  P2.0超声接收
    P2.1超声发射
    P1.2-P1.7步进电机
   
下面是自动入库避障智能小车视频截图:


车库图:


单片机源程序如下:
  1.             /*
  2. * 【实验平台】: QX-MCS51 单片机开发板 & QX-A51智能小车
  3. * 【外部晶振】: 11.0592mhz        
  4. * 【主控芯片】: STC89C52
  5. * 【编译环境】: Keil μVisio4
  6. * ********************************【接线说明】********************************
  7.              以下"A_"表示智能小车底板~~~"B_"表示开发板     
  8. *开发板供电线  :A_J5-VCC~~~B_VCC或5V0    A_J6-GND~~~B_GND (一共使用2根杜邦线)
  9. *电机控制线    :A_J10-P1.2至P1.7 对应接到B_P1.2至P1.7 (一共使用6根杜邦线)
  10. *超声波模块反馈线:A_J2-P20~~~B_P20    A_J2-P21~~~B_P21 (一共使用2根杜邦线)
  11.                         使用前请先以正确方式接上超声波模块与1602液晶
  12. ******************************************************************************
  13. * 【程序功能】:QX-A51智能小车超声波避障实验                                                                                   
  14. * 【使用说明】:接线无误后,烧写程序打开电源开、按下S2按键后蜂鸣器发出提示音1秒后启动小车
  15. * 【注意事项】:避免小车撞向障碍物或小车轮子堵转,小车电压不能低于6V
  16.                                 此程序只做参考,实际运行效果需根据不同实验场地进行不同调试
  17.                                 使用前请插接上1602液晶。如果液晶上无显示字符,请顺时针调节液晶对比度电位器。
  18.                                 如果显示字符过浓,请逆时针调节液晶对比度电位器
  19.                                 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  20.         ☆☆☆☆☆☆☆☆☆☆        如果没有使用1602液晶,请把P07接到GND上,否则无法运行☆☆☆☆☆☆☆☆☆☆
  21.                                 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  22. **********************************************************************************/
  23. #include <reg52.h> //51头文件
  24. #include <intrins.h>   //包含nop等系统函数
  25. #include <QXA51.h>//QX-A51智能小车配置文件

  26. sbit DU = P2^6;//数码管段选
  27. sbit RX = P2^0;//ECHO超声波模块回响端
  28. sbit TX = P2^1;//TRIG超声波模块触发端
  29. sbit LCM_RW = P3^6;     //定义LCD引脚
  30. sbit LCM_RS = P3^5;
  31. sbit LCM_E = P3^4;
  32. #define LCM_Data  P0   //定义液晶屏数据口
  33. #define Busy    0x80   //用于检测LCM状态字中的Busy标识

  34. unsigned char pwm_left_val = 150;//左电机占空比值 取值范围0-170,0最快
  35. unsigned char pwm_right_val = 150;//右电机占空比值取值范围0-170 ,0最快
  36. unsigned char pwm_t;//周期
  37. unsigned int  time = 0;//传输时间
  38. unsigned long S = 0;//距离
  39. bit      flag = 0;//超出测量范围标志位

  40. unsigned char code Range[] ="==Range Finder==";//LCD1602显示格式
  41. unsigned char code ASCII[13] = "0123456789.-M";
  42. unsigned char code table[]="Distance:000.0cm";
  43. unsigned char code table1[]="!!! Out of range";
  44. unsigned char disbuff[4] = { 0,0,0,0};//距离显示缓存
  45. unsigned int q=0;
  46. unsigned int w;
  47. unsigned int z=1;
  48. unsigned int u=0;
  49. unsigned int o=1;
  50. unsigned int v=0;
  51. void delay(unsigned int z)//毫秒级延时
  52. {
  53.         unsigned int x,y;
  54.         for(x = z; x > 0; x--)
  55.                 for(y = 114; y > 0 ; y--);
  56. }

  57. void Delay10us(unsigned char i)            //10us延时函数 启动超声波模块时使用
  58. {
  59.    unsigned char j;
  60.         do{
  61.                 j = 10;
  62.                 do{
  63.                         _nop_();
  64.                 }while(--j);
  65.         }while(--i);
  66. }

  67. void cmg88()//关数共阴极码管
  68. {
  69.     DU=1;            
  70.     P0=0X00;//共阴极数码管阳极给低电平,全部熄灭
  71.     DU=0;
  72. }

  73. /************************************LCD1602液晶屏驱动函数************************************************/
  74. //*******************读状态*************************//
  75. unsigned char ReadStatusLCM(void)
  76. {
  77.         LCM_Data = 0xFF;
  78.         LCM_RS = 0;
  79.         Delay10us(1);
  80.         LCM_RW = 1;
  81.         Delay10us(1);
  82.         do{
  83.         LCM_E = 0;
  84.         Delay10us(1);
  85.         LCM_E = 0;
  86.         Delay10us(1);
  87.         LCM_E = 1;
  88.         Delay10us(1);
  89.         }
  90.         while (LCM_Data & Busy); //检测忙信号
  91.         return(LCM_Data);
  92. }

  93. /****************写数据************************/
  94. void WriteDataLCM(unsigned char WDLCM)
  95. {
  96.         ReadStatusLCM(); //检测忙
  97.         LCM_Data = WDLCM;
  98.         LCM_RS = 1;
  99.         Delay10us(1);
  100.         LCM_RW = 0;
  101.         Delay10us(1);
  102.         LCM_E = 0; //若晶振速度太高可以在这后加小的延时
  103.         Delay10us(1);
  104.         LCM_E = 0; //延时
  105.         Delay10us(1);
  106.         LCM_E = 1;
  107.         Delay10us(1);
  108. }

  109. //****************写指令*************************//
  110. void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
  111. {
  112.         if (BuysC) ReadStatusLCM(); //根据需要检测忙
  113.         LCM_Data = WCLCM;
  114.         LCM_RS = 0;
  115.         Delay10us(1);
  116.         LCM_RW = 0;        
  117.         Delay10us(1);
  118.         LCM_E = 0;
  119.         Delay10us(1);
  120.         LCM_E = 0;
  121.         Delay10us(1);
  122.         LCM_E = 1;
  123.         Delay10us(1);
  124. }



  125. //*******************LCM初始化**********************//
  126. void LCMInit(void)
  127. {
  128.         LCM_Data = 0;
  129.         WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
  130.         delay(5);
  131.         WriteCommandLCM(0x38,0);
  132.         delay(5);
  133.         WriteCommandLCM(0x38,0);
  134.         delay(5);

  135.         WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
  136.         WriteCommandLCM(0x08,1); //关闭显示
  137.         WriteCommandLCM(0x01,1); //显示清屏
  138.         WriteCommandLCM(0x06,1); // 显示光标移动设置
  139.         WriteCommandLCM(0x0c,1); // 显示开及光标设置
  140. }

  141. //*********************按指定位置显示一个字符***********************//
  142. void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
  143. {
  144.         Y &= 0x1;
  145.         X &= 0xF; //限制X不能大于15,Y不能大于1
  146.         if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
  147.         X |= 0x80; //算出指令码
  148.         WriteCommandLCM(X, 1); //发命令字
  149.         WriteDataLCM(DData); //发数据
  150. }

  151. //**********************按指定位置显示一串字符*************************//
  152. void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
  153. {
  154.         unsigned char ListLength;

  155.   ListLength = 0;
  156.         Y &= 0x1;
  157.         X &= 0xF; //限制X不能大于15,Y不能大于1
  158.         while (DData[ListLength]>0x19) //若到达字串尾则退出
  159.                 {
  160.                         if (X <= 0xF) //X坐标应小于0xF
  161.                                 {
  162.                                         DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
  163.                                         ListLength++;
  164.                                         X++;
  165.                                 }
  166.                 }
  167. }


  168. /***************************************************************************/

  169. /*定时器0中断*/
  170. void timer0() interrupt 1        //T0中断用来计数器溢出,超过测距范围
  171. {
  172.         flag=1;                                                         //中断溢出标志                        
  173. }
  174. void  StartModule()                          //启动超声波模块
  175. {
  176.           TX=1;                                             //启动一次模块
  177.       Delay10us(2);
  178.           TX=0;
  179. }
  180.         
  181. /*小车前进*/
  182. void forward()
  183. {
  184.         left_motor_go; //左电机前进
  185.         right_motor_go; //右电机前进
  186. }

  187. /*PWM控制使能 小车后退*/
  188. void backward()
  189. {
  190.         left_motor_back; //左电机后退
  191.         right_motor_back; //右电机后退        
  192. }

  193. /*小车左转*/
  194. /*小车停止*/
  195. void stop()
  196. {
  197.         right_motor_stops;//右电机停止
  198.         left_motor_stops; //左电机停止        
  199. }

  200. /*PWM控制使能 小车高速左转*/
  201. void left_rapidly()
  202. {
  203.         left_motor_back;
  204.         right_motor_go;        
  205. }

  206. void right_rapidly()
  207. {
  208.         left_motor_go;
  209.         right_motor_back;        
  210. }

  211. /*定时器1中断输出PWM信号*/
  212. void timer1() interrupt 3
  213. {
  214.         pwm_t++;//周期计时加
  215.         if(pwm_t == 255)
  216.                 pwm_t = EN1 = EN2 = 0;
  217.         if(pwm_left_val == pwm_t)//左电机占空比        
  218.                 EN1 = 1;               
  219.         if(pwm_right_val == pwm_t)//右电机占空比
  220.                 EN2 = 1;                        
  221. }
  222. /*判断S2是否被按下*/
  223. void keyscan()
  224. {
  225.         for(;;)        //死循环
  226.         {
  227.                 if(key_s2 == 0)// 实时检测S2按键是否被按下
  228.                 {
  229.                         delay(5); //软件消抖
  230.                         if(key_s2 == 0)//再检测S2是否被按下
  231.                         {
  232.                                 while(!key_s2);//松手检测
  233.                                 beep = 0;        //使能有源蜂鸣器
  234.                                 delay(200);//200毫秒延时
  235.                                 beep = 1;        //关闭有源蜂鸣器
  236.                                 break;                //退出FOR死循环
  237.                         }
  238.                 }
  239.         }        
  240. }

  241. /*计算超声波所测距离并显示*/
  242. void Conut(void)
  243. {
  244.         time=TH0*256+TL0;
  245.         TH0=0;
  246.         TL0=0;
  247.         
  248.         S=(float)(time*1.085)*0.17;     //算出来是MM
  249.         if((S>=7000)||flag==1) //超出测量范围
  250.         {         
  251.                 flag=0;
  252.                 DisplayListChar(0, 1, table1);//1602显示数组table1
  253.         }
  254.         else
  255.         {
  256.                 disbuff[0]=S/1000; //距离数值千位
  257.                 disbuff[1]=S%1000/100;//距离数值百位
  258.                 disbuff[2]=S%100/10;//距离数值十位
  259.                 disbuff[3]=S%10; //距离数值个位
  260.             DisplayListChar(0, 1, table); //显示:Distance:000.0cm
  261.             DisplayOneChar(9, 1, ASCII[disbuff[0]]); //显示千位
  262.             DisplayOneChar(10, 1, ASCII[disbuff[1]]);        
  263.             DisplayOneChar(11, 1, ASCII[disbuff[2]]);
  264.         DisplayOneChar(12, 1, ASCII[10]);                //显示 .        
  265.             DisplayOneChar(13, 1, ASCII[disbuff[3]]);
  266.         }
  267. }

  268. /*超声波避障*******************************************************************/
  269. void        Avoid()
  270. {        
  271. if(u==0)
  272. {
  273.         if(S <180)//设置避障距离 ,单位毫米        刹车距离
  274.         {
  275.                 //beep = 0;//使能蜂鸣器
  276.                 stop();//停车
  277.                 backward();//后退
  278.                 delay(100);//后退时间越长、距离越远。后退是为了留出车辆转向的空间
  279.                
  280.                 do{
  281.                         
  282.                         right_rapidly();//高速右转
  283.                         delay(200);//时间越长 转向角度越大,与实际行驶环境有关
  284.                         stop();//停车
  285.                         delay(100);//时间越长 停止时间越久

  286.                         StartModule();        //启动模块测距,再次判断是否
  287.                         while(!RX);                //当RX(ECHO信号回响)为零时等待
  288.                         TR0=1;                            //开启计数
  289.                         while(RX);                        //当RX为1计数并等待
  290.                         TR0=0;                                //关闭计数
  291.                         Conut();                        //计算距离
  292.                         if(S<200)                                          /**************************小车左掉头180*********************************************/
  293.                         {
  294.                         left_rapidly();//高速左转
  295.                         delay(310);//时间越长 转向角度越大,与实际行驶环境有关        
  296.                         stop();//停车
  297.                         delay(100);//时间越长 停止时间越久长
  298.                         z=z+1;
  299.                         }        
  300.                         if(z>=3)
  301.                         {
  302.                         forward();//前进        
  303.                         u=1;
  304.                         }
  305.                         StartModule();        //启动模块测距,再次判断是否
  306.                         while(!RX);                //当RX(ECHO信号回响)为零时等待
  307.                         TR0=1;                            //开启计数
  308.                         while(RX);                        //当RX为1计数并等待
  309.                         TR0=0;                                //关闭计数
  310.                         Conut();
  311.                         }while(S < 140);//判断前面障碍物距离
  312.                 beep = 1;//关闭蜂鸣器
  313.        }
  314.         else
  315.         {
  316.                 forward();//前进
  317.         }        
  318. }


  319. else
  320.          {
  321.                  if(v==0)
  322.                 {
  323.                 if(S<530)
  324.                         {
  325.                         u=1;                 /********************************************************************/
  326.                     stop();//停车
  327.                     backward();//后退
  328.                     delay(100);//后退时间越长、距离越远。后退是为了留出车辆转向的空间
  329.                         left_rapidly();//高速左转
  330.                         delay(200);//时间越长 转向角度越大,与实际行驶环境有关
  331.                         stop();//停车
  332.                         delay(100);//时间越长 停止时间越久
  333.                         v=1;
  334.                         }
  335.                         else
  336.                                 forward();//前进
  337.                         
  338.                 }
  339.            else
  340.            {
  341.          if(S < 500)//设置避障距离 ,单位毫米        刹车距离
  342.           {
  343.                 //beep = 0;//使能蜂鸣器
  344.                 stop();//停车
  345.                 backward();//后退
  346.                 delay(100);//后退时间越长、距离越远。后退是为了留出车辆转向的空间
  347.                         do{
  348.                         right_rapidly();//高速右转
  349.                         delay(200);//时间越长 转向角度越大,与实际行驶环境有关
  350.                         stop();//停车
  351.                         delay(100);//时间越长 停止时间越久
  352.                         forward();//前进
  353.                         delay(400);
  354.                         left_rapidly();//高速左转
  355.                         delay(310);//时间越长 转向角度越大,与实际行驶环境有关        
  356.                         stop();//停车
  357.                         delay(100);//时间越长 停止时间越久长
  358.                          o=0;               
  359.                         }while(S < 140);//判断前面障碍物距离
  360.         }
  361.           else
  362.             {
  363.                 forward();//前进
  364.          }
  365.          }               
  366.     }
  367. }
  368. void main()
  369. {

  370.         
  371.         cmg88();//关数码管
  372.         LCMInit(); //LCM初始化
  373.         delay(5);//延时片刻

  374.         DisplayListChar(0, 0, Range);//1602第一行显示Range数组内容
  375.         DisplayListChar(0, 1, table);//1602第二行显示table数组内容
  376.         keyscan();//等待按下S2启动小车
  377.         delay(1000);//延时1秒
  378.         TMOD |= 0x20;//定时器1工作模式2,8位自动重装。用于产生PWM
  379.         TMOD |= 0x01;//定时器0工作模块1,16位定时模式。T0用测ECH0脉冲长度
  380.         TH1 = 220; //
  381.         TL1 = 220; //100HZ T1
  382.         TH0        = 0;
  383.     TL0        = 0;//T0,16位定时计数用于记录ECHO高电平时间         
  384.     ET1        = 1;//允许T1中断
  385.         ET0 = 1;//允许T0中断
  386.         TR1 = 1;//启动定时器1
  387. ……………………

  388. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码



所有资料51hei提供下载:
智能小车.rar (11.62 MB, 下载次数: 49)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:187963 发表于 2018-9-1 10:07 | 只看该作者
厉害啊大佬
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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