找回密码
 立即注册

QQ登录

只需一步,快速开始

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

智能小车 超声波测距

[复制链接]
跳转到指定楼层
楼主
ID:94111 发表于 2015-10-30 16:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include<reg52.h>

  2. #include <intrins.h>

  3. #define uint unsigned int

  4. #define uchar unsigned char


  5. sbit in=P3^3;          //超声波接收口
  6. sbit out=P3^4;          //超声波发射口


  7. //LCD1602端口定义

  8. sbit RS=P0^6;          //寄存器选择位,将RS位定义为P2.0引脚           //1602引脚定义
  9. sbit RW=P0^5;          //读写选择位,将RW位定义为P2.1引脚
  10. sbit E=P0^4;           //使能信号位,将E位定义为P2.2引脚
  11. sbit BF=P1^7;          //忙碌标志位,,将BF位定义为P0.7引脚
  12. #define LCD1602data P1 //1602数据口接单片机P1口


  13. uint time;
  14. unsigned long s=0;
  15. bit flag; //超声波超出测量范围标志位
  16. uint s1,s2,s3;



  17. /*****************************************************
  18. 以下为1602模块语句
  19. ***************************************************/


  20. /*****************************************************
  21. 函数功能:延时1ms
  22. ***************************************************/
  23. void delay1ms()
  24. {
  25.            unsigned char i,j;       
  26.         for(i=0;i<10;i++)
  27.         for(j=0;j<33;j++);                 
  28. }
  29. /*****************************************************
  30. 函数功能:延时若干毫秒
  31. 入口参数:n
  32. ***************************************************/
  33. void delay(unsigned int n)
  34. {
  35.            unsigned int i;
  36.         for(i=0;i<n;i++)
  37.         delay1ms();
  38. }
  39. /*****************************************************
  40. 函数功能:判断液晶模块的忙碌状态
  41. 返回值:result。result=1,忙碌;result=0,不忙
  42. ***************************************************/
  43. bit BusyTest(void)
  44.   {
  45.             bit result;
  46.         RS=0;//根据规定,RS为低电平,RW为高电平时,可以读状态
  47.             RW=1;
  48.             E=1;        //E=1,才允许读写
  49.             _nop_();   //空操作
  50.             _nop_();
  51.             _nop_();
  52.            _nop_();   //空操作四个机器周期,给硬件反应时间       
  53.             result=BF;  //将忙碌标志电平赋给result
  54.         E=0;
  55.             return result;
  56.   }
  57. /*****************************************************
  58. 函数功能:将模式设置指令或显示地址写入液晶模块
  59. 入口参数:dictate
  60. ***************************************************/
  61. void Write_com (unsigned char dictate)
  62. {   
  63.     while(BusyTest()==1); //如果忙就等待
  64.          RS=0;            //根据规定,RS和R/W同时为低电平时,可以写入指令
  65.          RW=0;   
  66.          E=0;             //E置低电平(写指令时,
  67.                           // 就是让E从0到1发生正跳变,所以应先置"0"
  68.          _nop_();
  69.          _nop_();         //空操作两个机器周期,给硬件反应时间
  70.          LCD1602data=dictate;//将数据送入P0口,即写入指令或地址
  71.          _nop_();
  72.          _nop_();
  73.          _nop_();
  74.          _nop_();         //空操作四个机器周期,给硬件反应时间
  75.          E=1;             //E置高电平
  76.          _nop_();
  77.          _nop_();
  78.          _nop_();
  79.          _nop_();         //空操作四个机器周期,给硬件反应时间
  80.           E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令
  81. }
  82. /*****************************************************
  83. 函数功能:指定字符显示的实际地址
  84. 入口参数:x
  85. ***************************************************/
  86. void WriteAddress(unsigned char x)
  87. {
  88.      Write_com(x|0x80); //显示位置的确定方法规定为"80H+地址码x"       
  89. }
  90. /*****************************************************
  91. 函数功能:将数据(字符的标准ASCII码)写入液晶模块
  92. 入口参数:y(为字符常量)
  93. ***************************************************/
  94. void WriteData(unsigned char y)
  95. {
  96.     while(BusyTest()==1);  
  97.           RS=1;           //RS为高电平,RW为低电平时,可以写入数据
  98.           RW=0;
  99.           E=0;            //E置低电平(写指令时,,
  100.                        // 就是让E从0到1发生正跳变,所以应先置"0"
  101.           LCD1602data=y;  //将数据送入P0口,即将数据写入液晶模块
  102.           _nop_();
  103.           _nop_();
  104.           _nop_();
  105.               _nop_();       //空操作四个机器周期,给硬件反应时间
  106.           E=1;          //E置高电平
  107.           _nop_();
  108.           _nop_();
  109.           _nop_();
  110.           _nop_();        //空操作四个机器周期,给硬件反应时间
  111.           E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令
  112. }
  113. /*****************************************************
  114. 函数功能:对LCD的显示模式进行初始化设置
  115. ***************************************************/
  116. void LcdInt(void)
  117. {
  118.            delay(15);      //延时15ms,首次写指令时应给LCD一段较长的反应时间
  119.            Write_com(0x38);  //显示模式设置:16×2显示,5×7点阵,8位数据接口
  120.         delay(5);   //延时5ms 
  121.         Write_com(0x38);
  122.         delay(5);
  123.         Write_com(0x38); //3次写 设置模式
  124.         delay(5);
  125. //        Write_com(0x0F);  //显示模式设置:显示开,有光标,光标闪烁
  126. //        delay(5);

  127.         Write_com(0x0c);  //显示模式设置:显示开,不显示光标
  128.         delay(5);

  129.         Write_com(0x06);  //显示模式设置:光标右移,字符不移
  130.         delay(5);                                                                                          
  131.         Write_com(0x01);  //清屏幕指令,将以前的显示内容清除
  132.         delay(5);
  133. }

  134. //add为显示字符的位置(在第二行显示)//x为显示的字符
  135. //调用此函数请注意:此函数是为显示数字的,display(10,9);display(10,a);
  136. //分别表示第二行第十位显示数字9和a代表的数字
  137. //如果想把此函数改写成显示字母的,
  138. //只需把最后WriteData(0x30+x);中的
  139. // 0x30+ 去掉即可,调用时注意格式  display(10,'a');
  140. display(unsigned char add,unsigned char x)            
  141. {                                         
  142.                        

  143.                  WriteAddress(0x00);
  144.                                                                                                                                                                                
  145.                  delay(5);

  146.                  Write_com(0x80+0x40+add);

  147.                  WriteData(0x30+x);
  148. }



  149. LCD1602()//1602初显示
  150. {
  151.        

  152.               LcdInt();         //调用LCD初始化函数  
  153.           delay(10);
  154.               Write_com(0x01);                //清屏

  155.                   delay(5);

  156.                   WriteAddress(0x00);
  157. //设置显示位置为第一行第一个字,这条语句可以不用写,因为默认是从第一行第一个字显示                                                                                                                                                                               
  158.                   delay(5);
  159. //第一行显示 DISTANCE:   
  160.                   WriteData('D');
  161.               WriteData('I');
  162.                   WriteData('S');
  163.                   WriteData('T');
  164.                   WriteData('A');       
  165.                   WriteData('N');       
  166.                   WriteData('C');       
  167.                   WriteData('E');       
  168.                   WriteData(':');
  169. }



  170. /*****************************************************
  171. 以上为1602模块语句
  172. ***************************************************/


  173. void  FS()                          //发射超声波
  174.   {
  175.           out=1;                                      
  176.           _nop_();
  177.           _nop_();
  178.           _nop_();
  179.           _nop_();
  180.           _nop_();
  181.           _nop_();
  182.           _nop_();
  183.           _nop_();
  184.           _nop_();
  185.           _nop_();
  186.           _nop_();
  187.           _nop_();
  188.           _nop_();
  189.           _nop_();
  190.           _nop_();
  191.           _nop_();
  192.           _nop_();
  193.           _nop_();
  194.           _nop_();
  195.           _nop_();
  196.           _nop_();
  197.           out=0;
  198.   }

  199. void conut(void) //计算并显示超声波测到的距离
  200. {
  201.          time=TH0*256+TL0;
  202.          TH0=0;
  203.          TL0=0;
  204.        
  205.          s=(time*1.7)/100;     //算出来单位是CM

  206.          if((s>=700)||flag==1) //超出测量范围显示"ERROR"
  207.          {         
  208.           flag=0;
  209.          
  210.           Write_com(0x80+0x40+11);
  211.           WriteData('E');        delay(5);
  212.       WriteData('R');        delay(5);
  213.           WriteData('R');        delay(5);
  214.           WriteData('O');        delay(5);
  215.           WriteData('R');        delay(5);
  216.          }
  217.          else
  218.          {
  219.           s1=s%1000/100;
  220.           s2=s%1000%100/10;
  221.           s3=s%1000%10 %10;
  222.           display(11,s1);
  223.           WriteData('.');
  224.           display(13,s2);       
  225.           display(14,s3);
  226.           WriteData('m');
  227.          }


  228. }
  229. /********************************************************/
  230. void zd0() interrupt 1                  //T0中断用来计数器溢出,超过测距范围
  231. {
  232.     flag=1;                                                         //中断溢出标志
  233. }

  234. main()
  235. {
  236.          LCD1602();
  237.          while(1)
  238.          {
  239.                     TMOD=0x01;                   //设T0为方式1,GATE=0;
  240.                TH0=0;
  241.                TL0=0;         
  242.                ET0=1;             //允许T0中断
  243.                EA=1;
  244.                                               //开启总中断       
  245.                     while(1)
  246.                    {
  247.                               FS();
  248.                            while(!in);
  249.                            TR0=1;
  250.                            while(in);
  251.                            TR0=0;
  252.                            conut();
  253.                                     
  254.                    }
  255.                   
  256.          }

  257. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的积分奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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