超声波液位检测 求指导

2019-07-15 15:22发布

本帖最后由 吥洅 于 2015-12-16 15:57 编辑

水位控制.txt (9.01 KB, 下载次数: 8)

网上买的电路图   自己焊 但是实现不了,现在淘宝店家理都不理,能确认硬件没问题,问题应该是出在程序,现在的状况就是只能设置上限值,其他都设置不了,而且超声波也没反应,求大神帮忙看下
  1. #include <reg52.h>                 //调用单片机头文件
  2. #define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
  3. #define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535
  4. #include <intrins.h>

  5. sbit c_send   = P3^3;                //超声波发射
  6. sbit c_recive = P3^2;                //超声波接收

  7. //这三个引脚参考资料
  8. sbit rs=P1^0;         //1602数据/命令选择引脚 H:数据              L:命令
  9. sbit rw=P1^1;         //1602读写引脚                 H:数据寄存器          L:指令寄存器
  10. sbit e =P1^2;         //1602使能引脚          下降沿触发
  11. uchar code table_num[]="0123456789abcdefg";

  12. uchar flag_en = 1;

  13. sbit beep = P1^6;   //蜂鸣器IO口定义

  14. bit flag_300ms ;

  15. long distance;                //距离
  16. uint set_gh,set_gl;                    //距离
  17. bit flag_csb_juli;        //超声波超出量程
  18. uint  flag_time0;     //用来保存定时器0的时候的

  19. //  按键的IO变量的定义
  20. uchar key_can;                 //按键值的变量
  21. uchar menu_1;        //菜单设计的变量
  22. uchar a_a;

  23. bit flag_lj_en;                 //按键连加使能
  24. bit flag_lj_3_en;         //按键连3次连加后使能  加的数就越大了
  25. uchar key_time,key_value;      //用做连加的中间变量
  26. bit key_500ms  ;

  27. uint shuiwei;
  28. uint sw_jz;   //基准水位

  29. /********************************************************************
  30. * 名称 : delay_uint()
  31. * 功能 : 小延时。
  32. * 输入 : 无
  33. * 输出 : 无
  34. ***********************************************************************/
  35. void delay_uint(uint q)
  36. {
  37.         while(q--);
  38. }

  39. /***********************1ms延时函数*****************************/
  40. void delay_1ms(uint q)
  41. {
  42.         uint i,j;
  43.         for(i=0;i<q;i++)
  44.                 for(j=0;j<120;j++);
  45. }


  46. /********************************************************************
  47. * 名称 : write_com(uchar com)
  48. * 功能 : 1602命令函数
  49. * 输入 : 输入的命令值
  50. * 输出 : 无
  51. ***********************************************************************/
  52. void write_com(uchar com)
  53. {
  54.         e=0;
  55.         rs=0;
  56.         rw=0;
  57.         P0=com;
  58.         delay_uint(25);
  59.         e=1;
  60.         delay_uint(100);
  61.         e=0;
  62. }

  63. /********************************************************************
  64. * 名称 : write_data(uchar dat)
  65. * 功能 : 1602写数据函数
  66. * 输入 : 需要写入1602的数据
  67. * 输出 : 无
  68. ***********************************************************************/
  69. void write_data(uchar dat)
  70. {
  71.         e=0;
  72.         rs=1;
  73.         rw=0;
  74.         P0=dat;
  75.         delay_uint(25);
  76.         e=1;
  77.         delay_uint(100);
  78.         e=0;        
  79. }

  80. /********************************************************************
  81. * 名称 : write_string(uchar hang,uchar add,uchar *p)
  82. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
  83.                   write_string(1,5,"ab cd ef;")
  84. * 输入 : 行,列,需要输入1602的数据
  85. * 输出 : 无
  86. ***********************************************************************/
  87. void write_string(uchar hang,uchar add,uchar *p)
  88. {
  89.         if(hang==1)   
  90.                 write_com(0x80+add);
  91.         else
  92.                 write_com(0x80+0x40+add);
  93.         while(1)
  94.         {
  95.                 if(*p == '')  break;
  96.                 write_data(*p);
  97.                 p++;
  98.         }        
  99. }

  100. /***********************lcd1602上显示两位十进制数************************/
  101. void write_sfm3(uchar hang,uchar add,uint date)
  102. {
  103.         if(hang==1)   
  104.                 write_com(0x80+add);
  105.         else
  106.                 write_com(0x80+0x40+add);
  107.         write_data(0x30+date/100%10);
  108.         write_data('.');
  109.         write_data(0x30+date/10%10);
  110.         write_data(0x30+date%10);        
  111.         write_data('m');
  112. }

  113. /********************************************************************
  114. * 名称 : init_1602()
  115. * 功能 : 初始化1602液晶
  116. * 输入 : 无
  117. * 输出 : 无
  118. ***********************************************************************/
  119. void init_1602()      //1602初始化
  120. {
  121.         write_com(0x38);
  122.         write_com(0x0c);
  123.         write_com(0x06);
  124.         delay_uint(1000);
  125.         write_string(1,0," Gaodu:  . m      ");        
  126.         write_string(2,0,"H:00.0m L:00.0m   ");
  127.         write_sfm3(2,2,set_gh);         //显示设置的高水位
  128.         write_sfm3(2,10,set_gl);         //显示设置的低水位
  129. }

  130. /********************独立按键程序*****************/
  131. uchar key_can;         //按键值

  132. void key()         //独立按键程序
  133. {
  134.         static uchar key_new;
  135.         key_can = 20;                   //按键值还原
  136.         P3 |= 0xf0;
  137.         if((P3 & 0xf0) != 0xf0)                //按键按下
  138.         {
  139.                 delay_1ms(1);                     //按键消抖动
  140.                 if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
  141.                 {                                                //确认是按键按下
  142.                         key_new = 0;
  143.                         switch(P3 & 0xf0)
  144.                         {
  145.                                 case 0x70: key_can = 1; break;           //得到k2键值
  146.                                 case 0xb0: key_can = 2; break;           //得到k3键值
  147.                                 case 0xd0: key_can = 3; break;           //得到k4键值
  148.                         }
  149.                 }                        
  150.                 flag_lj_en = 1;         //连加使能
  151.         }
  152.         else
  153.         {
  154.                 if(key_new == 0)
  155.                 {
  156.                         key_new = 1;
  157.                         flag_lj_en = 0;                //关闭连加使能
  158.                         flag_lj_3_en = 0;        //关闭3秒后使能
  159.                         key_value = 0;                //清零
  160.                         key_time = 0;
  161.                 }
  162.         }        
  163. }

  164. /****************按键处理显示函数***************/
  165. void key_with()
  166. {
  167.         if(menu_1 == 0)
  168.         {
  169.                 if(key_can == 3)
  170.                 {
  171.                         flag_en = 0;   //手动取消报警
  172.                         beep = 1;   //关闭蜂鸣器
  173.                 }
  174.                                        
  175.         }
  176.         if(key_can == 1)         //设置键
  177.         {
  178.                 menu_1 ++;
  179.                 if(menu_1 > 1)
  180.                 {
  181.                         menu_1 = 0;
  182.                         init_1602() ;     //1602初始化
  183.                 }
  184.                 if(menu_1 == 3)  //显示水位
  185.                 {
  186.                         write_string(1,0,"  juli:  . m     ");        
  187.                         write_string(2,0,"Jizhun:    m     ");
  188.                 }
  189.         }
  190.         if(menu_1 == 1)                        //设置高水位
  191.         {
  192.                 if(key_can == 2)
  193.                 {
  194.                         if(flag_lj_3_en == 0)
  195.                                 set_gh ++ ;                //加1
  196.                         else
  197.                                 set_gh += 10 ;                //加10
  198.                         if(set_gh > 500)
  199.                                 set_gh = 500;
  200.                 }
  201.                 if(key_can == 3)
  202.                 {
  203.                         if(flag_lj_3_en == 0)
  204.                                 set_gh -- ;                //减1
  205.                         else
  206.                                 set_gh -= 10;        //按键按下未松开自动减三次之后每次自动减10
  207.                         if(set_gh <= set_gl)
  208.                                 set_gh = set_gl + 1;
  209.                 }
  210.                 write_sfm3(2,2,set_gh);         //显示设置的高水位
  211.                 write_sfm3(2,10,set_gl);         //显示设置的低水位
  212.                 write_com(0x80+0x40+2);  //将光标显示地址
  213.                 write_com(0x0f);         //显示光标并且闪烁
  214.         }        
  215.         if(menu_1 == 2)                        //设置低水位
  216.         {
  217.                 if(key_can == 2)
  218.                 {
  219.                         if(flag_lj_3_en == 0)
  220.                                 set_gl ++ ;                //加1
  221.                         else
  222.                                 set_gl += 10 ;                //加10
  223.                         if(set_gl > set_gh)
  224.                                 set_gl = set_gh - 1;
  225.                 }
  226.                 if(key_can == 3)
  227.                 {
  228.                         if(flag_lj_3_en == 0)
  229.                                 set_gl -- ;                //减1
  230.                         else
  231.                                 set_gl -= 10;        //按键按下未松开自动减三次之后每次自动减10
  232.                         if(set_gl <= 10)
  233.                                 set_gl = 10 ;
  234.                 }
  235.                 write_sfm3(2,2,set_gh);         //显示设置的高水位
  236.                 write_sfm3(2,10,set_gl);         //显示设置的低水位
  237.                 write_com(0x80+0x40+10);  //将光标显示地址
  238.                 write_com(0x0f);         //显示光标并且闪烁
  239.         }        
  240.         if(menu_1 == 3)
  241.         {
  242.                 if(key_can == 2)
  243.                         sw_jz = distance;
  244.                 if(key_can == 3)
  245.                         sw_jz = distance;
  246.                 write_sfm3(2,8,sw_jz);         //显示基准水位
  247.                 write_com(0x80+0x40+7);  //将光标显示地址
  248.         }
  249. }  

  250. /**************10us延时函数***************/
  251. void delay()
  252. {
  253.         _nop_();                            //执行一条_nop_()指令就是1us
  254.         _nop_();
  255.         _nop_();
  256.         _nop_();
  257.         _nop_();
  258.         _nop_();
  259.         _nop_();  
  260.         _nop_();
  261.         _nop_();  
  262.         _nop_();
  263. }


  264. /*********************超声波测距程序*****************************/
  265. void send_wave()
  266. {
  267.         c_send = 1;                           //10us的高电平触发
  268.         delay();
  269.         c_send = 0;         
  270.         while(!c_recive);                  //当c_recive为零时等待
  271.         TR0=1;
  272.         while(c_recive)                      //当c_recive为1计数并等待
  273.         {
  274.                 flag_time0 = TH0 * 256 + TL0;
  275.                 if((flag_time0 > 40000))      //当超声波超过测量范围时,显示3个888
  276.                 {
  277.                         TR0 = 0;
  278.                         flag_csb_juli = 2;
  279.                         distance = 888;
  280.                         break ;               
  281.                 }
  282.                 else
  283.                 {
  284.                         flag_csb_juli = 1;        
  285.                 }
  286.         }
  287.         if(flag_csb_juli == 1)
  288.         {        
  289.                 distance =flag_time0;                         //读出定时器0的时间
  290.                 distance *= 0.017;               // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
  291.                 if((distance > 600))                                 //距离 = 速度 * 时间
  292.                 {        
  293.                         distance = 888;                                 //如果大于3.8m就超出超声波的量程
  294.                 }
  295.         }  
  296. }



  297. /*********************定时器0、定时器1初始化******************/
  298. void time_init()         
  299. {
  300.         EA  = 1;                   //开总中断
  301.         TMOD = 0X11;          //定时器0、定时器1工作方式1
  302.         ET0 = 0;                  //关定时器0中断
  303.         TR0 = 1;                  //允许定时器0定时
  304.         ET1 = 0;                  //开定时器1中断
  305.         TR1 = 1;                  //允许定时器1定时        
  306. }


  307. /**************报警函数***************/
  308. void clock_h_l()
  309. {
  310.         static uchar value;
  311.         if((shuiwei <= set_gl) || (shuiwei >= set_gh))
  312.         {
  313.                 value ++;  //消除实际距离在设定距离左右变化时的干扰
  314.                 if(value >= 2)
  315.                 {
  316.                         if(flag_en == 1)
  317.                                 beep = ~beep;           //蜂鸣器报警        
  318.                 }
  319.         }
  320.         else
  321.         {
  322.                 value = 0;
  323.                 beep = 1;                //取消报警
  324.                 flag_en = 1;
  325.         }        
  326. }

  327. /***************主函数*****************/
  328. void main()
  329. {
  330.         init_1602();      //1602初始化
  331.         time_init();
  332.         while(1)
  333.         {
  334.                 if(flag_300ms == 1)
  335.                 {
  336.                         flag_300ms = 0;
  337.                         clock_h_l();    //报警函数
  338.                         if((beep == 1))
  339.                                 send_wave();        //测距离函数
  340.                         if(menu_1 == 0)
  341.                         {
  342.                                 if(distance > 10 + sw_jz)  //说明水位出错
  343.                                 {
  344.                                         write_string(1,7,"--.-m");                        
  345.                                 }else
  346.                                 {
  347.                                         if(sw_jz >= distance)
  348.                                         {
  349.                                                 shuiwei = sw_jz - distance;          //计算出液位
  350.                                         }else
  351.                                                 shuiwei = 0;        
  352.                                         write_sfm3(1,7,shuiwei);                                       
  353.                                 }
  354.                         }               
  355.                         write_sfm3(1,8,distance);         //显示距离
  356.                 }
  357.                 key();                                         //按键函数
  358.                 if(key_can < 10)
  359.                 {
  360.                         key_with();                         //按键处理函数
  361.                 }
  362.         }
  363. }         

  364. /*********************定时器0中断服务程序************************/
  365. void time1_int() interrupt 3
  366. {        
  367.         static uchar value;
  368.         TH0 = 0x3c;
  369.         TL0 = 0xb0;     // 50ms
  370.         value ++;         
  371.         if(value % 6 == 0)
  372.         {
  373.                 flag_300ms = 1;           //300ms
  374.                 value = 0;
  375.         }
  376.         if(flag_lj_en == 1)           //按下按键使能
  377.         {
  378.                 key_time ++;
  379.                 if(key_time >= 10) //500ms
  380.                 {
  381.                         key_time = 0;
  382.                         key_500ms = 1; //500ms
  383.                         key_value ++;
  384.                         if(key_value > 3)
  385.                         {
  386.                                 key_value = 10;
  387.                                 flag_lj_3_en = 1; //3次后1.5秒连加大些
  388.                         }                                                
  389.                 }
  390.         }
  391. }


复制代码

SKT)$MN%K0C{~J6P(EO1717.png
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。