找回密码
 立即注册

QQ登录

只需一步,快速开始

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

利用51单片机和超声波实现双路测距及12864中文显示

[复制链接]
跳转到指定楼层
楼主
这个是我设计做的51单片机实现超声波双路测距。(附带详细电路图)
    本程序可以实现双路超声波测距,并且显示在12864上,并且实现了短距离报警功能。
电路原理图如下:


单片机代码如下:
  1. #include   <reg52.h>
  2. #include   <intrins.h>
  3. #define uint unsigned int
  4.     #define uchar unsigned char
  5.     //引脚定义
  6.     sbit     Trig1    =  P2^4;   //
  7.     sbit     Ecno1    =  P2^5;   //
  8. sbit     Trig2    =  P3^2; //
  9.     sbit     Ecno2    =  P3^3; //
  10. sbit     SPK=P2^3;
  11. sbit     LED1=P1^0;
  12. sbit     LED2=P1^1;
  13. #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
  14. #define LCD_data  P1^0             //数据口
  15. sbit LCD_RS  =  P3^5;            //寄存器选择输入
  16. sbit LCD_RW  =  P3^6;            //液晶读/写控制
  17. sbit LCD_EN  =  P3^4;            //液晶使能控制
  18. sbit LCD_PSB =  P3^7;            //串/并方式控制
  19. sbit wela    =  P2^7;
  20. sbit dula    =  P2^6;
  21.     // 函数声明
  22. void Write_char(uchar dat);
  23. bit lcd_busy();
  24. void Lcd_init(void);
  25. void LCD_Write_string(uchar *str);
  26. void LCD_set_xy( unsigned char x, unsigned char y );
  27. void  StartModule() ;
  28. void Clr_Scr();
  29. unsigned char code num[]={"0123456789 :."};
  30. unsigned char code table1[]={"前方距离:"};
  31. unsigned char code table2[] ={"后方距离:"};
  32. unsigned char code M[] =  {"CM"};
  33. unsigned int  time1=0;
  34. unsigned int  time2=0;
  35.          long S1=0;
  36.    long S2=0;
  37.          bit  flag =0;
  38.    
  39. unsigned char disbuff[4]={ 0,0,0,0,};
  40. /******************************************************************************/
  41. /*******************************************************************/
  42. /*                                                                 */
  43. /*  延时函数                                                       */
  44. /*                                                                 */
  45. /*******************************************************************/
  46. void delay(uint x)
  47. {
  48.     uint i,j;
  49.     for(i= x;i>0;i--)
  50.         for(j=110;j>0;j--);
  51. }
  52. void lcd_wcmd(uchar cmd)
  53. {                          
  54.    while(lcd_busy());
  55.     LCD_RS = 0;
  56.     LCD_RW = 0;
  57.     LCD_EN = 0;
  58.     _nop_();
  59.     _nop_();
  60.     P0 = cmd;
  61.     delayNOP();
  62.     LCD_EN = 1;
  63.     delayNOP();
  64.     LCD_EN = 0;  
  65. }
  66. void Lcd_init(void) //初始化LCD
  67. {
  68.     LCD_PSB = 1;         //并口方式
  69.    
  70.     lcd_wcmd(0x34);      //扩充指令操作
  71.     delay(5);
  72.     lcd_wcmd(0x30);      //基本指令操作
  73.     delay(5);
  74.     lcd_wcmd(0x0C);      //显示开,关光标
  75.     delay(5);
  76.     lcd_wcmd(0x01);      //清除LCD的显示内容
  77.     delay(5);  
  78. }
  79. bit lcd_busy()
  80. {                          
  81.     bit result;
  82.     LCD_RS = 0;
  83.     LCD_RW = 1;
  84.     LCD_EN = 1;
  85.     delayNOP();
  86.     result = (bit)(P0&0x80);
  87.     LCD_EN = 0;
  88.     return(result);
  89. }
  90. /******************************************************************************/
  91. /*void Write_char(uchar dat) //写指令或数据
  92. {
  93.    while(lcd_busy());
  94.     LCD_RS = 1;
  95.     LCD_RW = 0;
  96.     LCD_EN = 0;
  97.     P0 = dat;
  98.     delayNOP();
  99.     LCD_EN = 1;
  100.     delayNOP();
  101.     LCD_EN = 0;
  102. }
  103.   */

  104. /******************************************************************************/
  105. void Delaynms(unsigned int di) //延时
  106. {
  107. unsigned int da,db;
  108.   for(da=0;da<di;da++)
  109.      for(db=0;db<10;db++);
  110. }
  111. /******************************************************************************/
  112. void Clr_Scr(void)//清屏函数
  113. {
  114. lcd_wcmd(0x01);
  115. }
  116. /******************************************************************************/
  117. void LCD_set_xy( unsigned char X, unsigned char Y )//设置LCD显示的起始位置,X为行,Y为列
  118. {
  119.                         
  120.    uchar  pos;
  121.    if (X==0)
  122.      {X=0x80;}
  123.    else if (X==1)
  124.      {X=0x90;}
  125.    else if (X==2)
  126.      {X=0x88;}
  127.    else if (X==3)
  128.      {X=0x98;}
  129.    pos = X+Y ;  
  130.    lcd_wcmd(pos);     //显示地址
  131. }
  132. void lcd_wdat(uchar dat)
  133. {                          
  134.    while(lcd_busy());
  135.     LCD_RS = 1;
  136.     LCD_RW = 0;
  137.     LCD_EN = 0;
  138.     P0 = dat;
  139.     delayNOP();
  140.     LCD_EN = 1;
  141.     delayNOP();
  142.     LCD_EN = 0;
  143. }
  144. /******************************************************************************/
  145.   
  146. void LCD_Write_string(uchar *str)//
  147. {


  148. for(;*str!='\0';str++)
  149. {
  150.    lcd_wdat(*str);
  151.    delay(2);
  152. }

  153. }

  154. /******************************************************************************/
  155. void LCD_Write_number(unsigned char s)// 数字显示函数
  156. {

  157.   lcd_wdat(num[s]);
  158.      Delaynms(1);
  159. }
  160. /******************************************************************************/
  161. void Lcd_Mark2(void)
  162. {
  163. Clr_Scr();//清屏
  164. LCD_set_xy(0,0);
  165. LCD_Write_string("前方");//
  166. LCD_set_xy(0,7);
  167. LCD_Write_string("CM");
  168. LCD_set_xy(1,0);
  169. LCD_Write_string("后方");//
  170. LCD_set_xy(1,7);
  171. LCD_Write_string("CM");
  172. }
  173. /********************************************************/
  174. /********************************************************/
  175.     void Conut1(void)
  176. {
  177.     time1=TH0*256+TL0;
  178.     TH0=0x00;
  179.     TL0=0x00;
  180.     S1=time1*1.87/100;       //   11.0592M晶振
  181.    
  182.     if(flag==1)        //超出测量
  183.    {  
  184.     flag=0;
  185.     LCD_set_xy( 0, 5 );
  186. LCD_Write_string("超");
  187.    
  188.     }
  189.   else
  190.    {
  191.     disbuff[1]=S1%1000/100;
  192.     disbuff[2]=S1%1000%100/10;
  193.     disbuff[3]=S1%1000%100%10;
  194.     LCD_set_xy( 0, 5 );
  195.     LCD_Write_number(disbuff[1]);
  196.     LCD_Write_number(disbuff[2]);
  197.     LCD_set_xy( 0, 6 );
  198.     LCD_Write_number(disbuff[3]);
  199. if(S1<70&&S1>=50)
  200.   {
  201.                  SPK= 1;
  202.                 delay(1000);
  203.                 SPK= 0;
  204.                 delay(10);
  205.                
  206.   }
  207.   if(S1<50&&S1>=30)
  208.   {
  209.                  SPK= 1;
  210.                 delay(500);
  211.                 SPK= 0;
  212.                 delay(10);
  213.                
  214.   }
  215.   if(S1<30&&S1>=10)
  216.   {
  217.                  SPK= 1;
  218.                 delay(200);
  219.                 SPK= 0;
  220.                 delay(10);
  221.                
  222.   }
  223.   if(S1<10)
  224.   {
  225.                 SPK= 0;
  226.                
  227.   }
  228. else
  229.   {
  230.   SPK=1;
  231.   }
  232.    if(S1<70&&S1>=50)
  233.   {
  234.                  LED1= 1;
  235.                 delay(1000);
  236.                 LED1= 0;
  237.                 delay(10);
  238.                
  239.   }
  240.   if(S1<50&&S1>=30)
  241.   {
  242.                  LED1= 1;
  243.                 delay(500);
  244.                 LED1= 0;
  245.                 delay(10);
  246.                
  247.   }
  248.   if(S1<30&&S1>=10)
  249.   {
  250.                  LED1= 1;
  251.                 delay(200);
  252.                 LED1= 0;
  253.                 delay(10);
  254.                
  255.   }
  256.   if(S1<10)
  257.   {
  258.                 LED1= 0;
  259.                
  260.   }
  261. else
  262.   {
  263.   LED1=1;
  264.   }
  265.    }
  266. }

  267. /****************************************************/
  268. void Conut2(void)
  269. {
  270.     time2=TH0*256+TL0;
  271.     TH0=0x00;
  272.     TL0=0x00;
  273.     S2=time2*1.87/100;       //   11.0592M晶振
  274.     if(flag==1)        //超出测量
  275.    {  
  276.     flag=0;
  277.     LCD_set_xy( 1, 5 );
  278. LCD_Write_string("超");
  279.    
  280.     }
  281.   else
  282.    {
  283.     disbuff[1]=S2%1000/100;
  284.     disbuff[2]=S2%1000%100/10;
  285.     disbuff[3]=S2%1000%100%10;
  286.     LCD_set_xy( 1, 5 );
  287.     LCD_Write_number(disbuff[1]);
  288.     LCD_Write_number(disbuff[2]);
  289.     LCD_set_xy( 1, 6 );
  290.     LCD_Write_number(disbuff[3]);
  291.    }
  292. }
  293. /****************************************************/
  294. void changkuan()
  295. {

  296. }
  297. /********************************************************/
  298. void delay20us(void)   //误差 -0.016637731481us
  299. {
  300.     unsigned char a,b;
  301.     for(b=1;b>0;b--)
  302.         for(a=52;a>0;a--);
  303.      //if Keil,require use intrins.h
  304. }
  305. void Delay5ms()  //@11.0592MHz
  306. {
  307. unsigned char i, j;
  308. i = 54;
  309. j = 199;
  310. do
  311. {
  312.   while (--j);
  313. } while (--i);
  314. }

  315. void Delay50ms()  //@11.0592MHz
  316. {
  317. unsigned char i, j, k;
  318. i = 3;
  319. j = 26;
  320. k = 223;
  321. do
  322. {
  323.   do
  324.   {
  325.    while (--k);
  326.   } while (--j);
  327. } while (--i);
  328. }



  329. void Delay300ms()  //@11.0592MHz
  330. {
  331. unsigned char i, j, k;
  332. i = 13;
  333. j = 156;
  334. k = 83;
  335. do
  336. {
  337.   do
  338.   {
  339.    while (--k);
  340.   } while (--j);
  341. } while (--i);
  342. }
  343. /********************************************************/
  344.      void zd0() interrupt 1    //T0中断用来计数器溢出,超过测距范围
  345.   {
  346.     flag=1;        //中断溢出标志
  347.   }
  348. /********************************************************/
  349.    void  StartModule1()            //超声波触发函数
  350.   {   Trig1=0;
  351.   delay20us();
  352.    Trig1=1;
  353.    delay20us();      //发射一个大于10us的脉冲,触发超声波发射
  354.    Trig1=0;
  355.   }
  356.   /******************************************************/
  357.   void  StartModule2()            //超声波触发函数
  358.   {   Trig2=0;
  359.   delay20us();
  360.    Trig2=1;
  361.    delay20us();      //发射一个大于10us的脉冲,触发超声波发射
  362.    Trig2=0;
  363.   }
  364.   /******************************************************/
  365. /********************************************************/
  366. void main(void)
  367. {  
  368.     TMOD=0x01;     //设T0为方式1
  369. TH0=0x00;
  370. TL0=0x00;
  371. TR0=1;
  372. ET0=1;             //允许T0中断
  373. EA=1;      //开启总中断
  374. Lcd_init();       //设置液晶显示器
  375. Clr_Scr();        //清屏
  376. Delaynms(1000);
  377. Lcd_init();       //
  378.     Lcd_Mark2();
  379. Delaynms(1000);
  380. while(1)
  381. {  
  382.   StartModule1();        //发出信号
  383.    Ecno1 =1;     //把Ecno脚置高后等待高电平回波信号  
  384.   while(!Ecno1);  //当Ecno为零时等待  
  385.   TR0=1;       //开启计数
  386.   while(Ecno1);     //当RX为1计数并等待
  387.   TR0=0;    //关闭计数
  388.   Conut1();
  389.   delay(200);

  390. StartModule2();        //发出信号
  391.    Ecno2 =1;     //把Ecno脚置高后等待高电平回波信号  
  392.   while(!Ecno2);  //当Ecno为零时等待  
  393.   TR0=1;       //开启计数
  394.   while(Ecno2);     //当RX为1计数并等待
  395.   TR0=0;    //关闭计数
  396.   Conut2();
  397.   delay(250);

  398.    
  399. }
  400. }
复制代码
            
全部资料51hei下载地址:
双路超声波测距 12864显示.zip (106.25 KB, 下载次数: 44)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:58110 发表于 2019-10-8 08:36 | 只看该作者
谢谢分享!不知精度如何
回复

使用道具 举报

板凳
ID:618543 发表于 2019-10-8 10:06 来自触屏版 | 只看该作者
谢谢分享
回复

使用道具 举报

地板
ID:526075 发表于 2019-10-14 14:27 | 只看该作者
lyMarvin 发表于 2019-10-8 08:36
谢谢分享!不知精度如何

我实际测试精度在2cm之内
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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