找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机超声波水位控制器设计资料(源码+PCB+原理图与实物制作)

  [复制链接]
跳转到指定楼层
楼主
ID:400169 发表于 2018-9-19 19:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

按键功能分别为:设置键 增加键 减小键 复位键

三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L
                        绿色----最高H和最低L中间


本文采用AT89C52单片机系统实现了水塔水位的自动控制,设计出一种低成本、高实用价值的水塔水位控制器。该系统具有水位检测、水位高度LCD显示、低水位高水位报警以及自动加水等功能。
本设计过程中主要采用了传感技术、单片机技术、光报警技术以及弱电控制强电的技术。本设计传感器使用了超声波模块,并且详细阐述了超声波测距测的原理,给出了系统构成框图。此系统具有易控制、工作可靠、测量精度高的优点,可实时监控液位。并采用52单片机系统控制整个电路的信号处理以及采用光电耦合和继电器来实现弱电控制强电来实现加水系统的自动控制。它能自动完成水位检测、光报警、上水停水的全部工作循环,保证液面高度始终处于较理想的范围内,它结构简单,制造成本低,灵敏度高,节约能源显著,是用于各种高层液体储存的理想设备。

示意图:


制作出来的实物图如下:


Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件):


超声波水位控制器元件清单
1)    9*15万用板                                  1
2)    AT89C51单片机                            1
3)    超声波探头                                     0
4)    40脚IC座                                    1
5)    4脚排针                                         0
6)    杜邦线4根                                        0
7)    继电器*2                                        0
8)    LCD1602液晶                               1
9)    103电位器                                     0
10)    16脚IC座                                0
11)    16脚排针                                   1
12)    蜂鸣器                                         0
13)    8550三极管*3                           0
14)    1k电阻*8                                    0
15)    10k电阻                                        0
16)    10uf电容                                      0
17)    30pf电容*2                                 0
18)    12M晶振                                      1
19)    3mmLED(红、绿各2个,黄1个)       0
20)    轻触按键*4                                 1
21)    自锁开关                                       1
22)    DC电源插口                                1
23)    USB电源线(电池盒)
24)    直流水泵*2(根据客户自选)

单片机程序源码如下:

  1. /***************************************************************
  2.         名称:基于51单片机的超声波水位监测报警系统
  3.         单片机型号:AT89C51
  4.         单片机设置:时钟12T,晶体12MHZ
  5.         作者:学长电子工作室
  6.         注:修改增加水泵控制和排水控制,即双继电器
  7. ***************************************************************/

  8. #include <reg51.h>
  9. #include <intrins.h>                // 包含循环移位:_cror_
  10. #include "main.h"     
  11. //----------------------------------------------------------------------

  12. uchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};

  13. bool        g_flag = isNo;                //用于标记超时(65.536ms)           
  14. bool        g_flag05s = isNo;        //用于标记0.52秒  
  15. uchar         ucCount = 0;                        //用于计数0.52秒     
  16.    
  17. uint        uiH = 80;                        //设定的最高报警水位 H
  18. uint        uiL = 30;                        //设定的最低报警水位 L
  19. uint        uiD = 100;                         //检测探头到水库底部的距离 D

  20. bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志
  21. bool        g_flagBeepTimer = isNo;        //定时提醒标志
  22.                

  23. //-----------------------------------------------------------------------
  24. // 延时10us
  25. void delay10us(void)                //@12MHz
  26. {
  27.         unsigned char i;

  28.         _nop_();
  29.         i = 2;
  30.         while (--i);
  31. }

  32. // 延时100us
  33. void delay100us(void)                //@12MHz
  34. {
  35.         uchar i;

  36.         _nop_();
  37.         i = 47;
  38.         while (--i);
  39. }

  40. // 延时125us
  41. void delay125us(void)                //@12MHz
  42. {
  43.         unsigned char i;
  44.         i = 60;
  45.         while (--i);
  46. }

  47. // 延时5ms
  48. void delay5ms(void)                //@12.000MHz
  49. {
  50.         unsigned char i, j;

  51.         i = 10;
  52.         j = 183;
  53.         do
  54.         {
  55.                 while (--j);
  56.         } while (--i);
  57. }

  58. // 延时500ms
  59. void delay500ms(void)                //@12MHz
  60. {
  61.         unsigned char i, j, k;

  62.         _nop_();
  63.         i = 4;
  64.         j = 205;
  65.         k = 187;
  66.         do
  67.         {
  68.                 do
  69.                 {
  70.                         while (--k);
  71.                 } while (--j);
  72.         } while (--i);
  73. }

  74. //-----------------------------------------------------------------------
  75. //初始化IO端口                        
  76. void initIO(void)                                       
  77. {
  78.         P0 = 0xff;
  79.         P1 = 0xff;
  80.         P2 = 0xff;
  81.         P3 = 0xff;
  82. }

  83. // 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz
  84. void initTimer0(void)               
  85. {
  86.         TMOD &= 0xF0;                //设置定时器模式
  87.         TMOD |= 0x01;                //设置定时器模式
  88.         TL0 = 0;                                //定时器初值清零
  89.         TH0 = 0;                                //定时器初值清零
  90.         //TR0 = 1;                           //开定时器0
  91.     ET0 = 1;                          //开定时器0中断
  92.     EA = 1;                             //开总中断            
  93.         
  94. }

  95. // 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz
  96. void initTimer1(void)                //50毫秒@12.000MHz
  97. {        
  98.         TMOD &= 0x0F;                //设置定时器模式
  99.         TMOD |= 0x10;                //设置定时器模式
  100.         TL1 = 0xB0;                //设置定时初值
  101.         TH1 = 0x3C;                //设置定时初值        
  102.         TR1 = 1;                //定时器1开始计时
  103.         ET1 = 1;          //开定时器0中断
  104. }

  105. //-----------------------------------------------------------------------
  106. //定时器0中断
  107. void zd0(void) interrupt 1                  
  108. {
  109.         
  110.         g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
  111.         if(++ucCount >= 8)
  112.         {
  113.                 ucCount = 0;
  114.                 g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时
  115.         }
  116.         TL0 = 0;                //设置定时初值
  117.         TH0 = 0;                //设置定时初值
  118.         
  119. }


  120. //定时器1中断 定时50ms
  121. void tm1_isr() interrupt 3 using 1
  122. {
  123.         static uchar count = DATA_switchTime;        //50ms的200倍 = 10S
  124.         static uchar uiCount = 1200;                                //                        = 1分钟               
  125.         static uint uiCount_BeepTimer = DATA_BeepTimer;

  126.         TL1 = 0xB0;                //设置定时初值
  127.         TH1 = 0x3C;                //设置定时初值

  128.         if (g_flagSwitch == isNo)
  129.         {
  130.                 if (count-- == 0)               //50ms * 200 -> 10s
  131.                 {
  132.                         count = DATA_switchTime;
  133.                         g_flagSwitch = isYes;
  134.                         // TR1 = 0;
  135.                 }
  136.         }        
  137.         
  138.         if(g_flagBeepTimer == isNo)
  139.         {
  140.                 if (uiCount-- == 0)               //= 1分钟
  141.                 {
  142.                         uiCount = 1200;
  143.                         if(uiCount_BeepTimer-- == 0)
  144.                         {
  145.                                 uiCount_BeepTimer = DATA_BeepTimer;
  146.                                 g_flagBeepTimer = isYes;
  147.                                 // TR1 = 0;
  148.                         }                        
  149.                         
  150.                 }

  151.         }
  152. }

  153. //-----------------------------------------------





  154. //外部中断1
  155. void exint1() interrupt 2
  156. {
  157.     EX1 = 0;                         //关闭当前中断
  158.         TR0 = 0;                           //关闭时器0
  159.         
  160. }
  161. //-----------------------------------------------------------------------
  162.   
  163. //读LCD忙状态并等待忙状态结束
  164. void LCD_waitNotBusy(void)
  165. {
  166.         IO_LCD_Data = 0xFF;
  167.         io_LCD_RS = 0;
  168.         io_LCD_RW = 1;
  169.         io_LCD_E = 0;
  170.         _nop_();
  171.         _nop_();
  172.         io_LCD_E = 1;
  173.         while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙
  174. }

  175. //给LCD写指令
  176. void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
  177. {
  178.         if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙
  179.         IO_LCD_Data = command;
  180.         io_LCD_RS = 0;
  181.         io_LCD_RW = 0;        
  182.         io_LCD_E = 0;
  183.         _nop_();
  184.         _nop_();
  185.         io_LCD_E = 1;        
  186. }

  187. //给LCD写数据
  188. void LCDWriteData(uchar dat)
  189. {
  190.         LCD_waitNotBusy(); //等到不忙
  191.         IO_LCD_Data = dat;
  192.         io_LCD_RS = 1;
  193.         io_LCD_RW = 0;
  194.         io_LCD_E = 0;
  195.         _nop_();
  196.         _nop_();
  197.         io_LCD_E = 1;
  198. }




  199. // 初始化LCD1602液晶显示屏
  200. void initLCD1602(void)
  201. {
  202.         uchar        i;        
  203.         IO_LCD_Data = 0;                                                                // 数据端口清零
  204.         for(i = 0; i < 3; i++)                                                // 设置三次显示模式
  205.         {
  206.                 LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号
  207.                 delay5ms();
  208.         }
  209.         
  210.         LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号
  211.         LCDWriteCommand(0x08,isReadBusy); // 关闭显示
  212.         LCDWriteCommand(0x01,isReadBusy); // 显示清屏
  213.         LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
  214.         LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置
  215. }



  216. //按指定位置显示一个字符
  217. void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
  218. {

  219.         line &= DATA_LineMax;
  220.         position &= DATA_PositionMax;
  221.         if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
  222.         position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
  223.         LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
  224.         LCDWriteData(ucData);                                                                  //写入字符的数据        
  225. }

  226. //按指定位置显示一串字符
  227. void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
  228. {
  229.         uchar i;
  230.         for(i = 0; i < count; i++)                                                        //连续显示单个字符
  231.         {
  232.                 putOneCharToLCD1602(line, position + i, ucData[i]);        
  233.         }
  234. }


  235. //按指定位置连续显示三个字符(三位数字)
  236. void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)
  237. {
  238.         uiNumber %= 1000;
  239.         putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
  240.         putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
  241.         putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
  242.         
  243. }
  244.         


  245. // 按键检测子程序,有键按下返回键端口数据,无键返回0
  246. uchar GetKey(void)
  247. {        
  248.     uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        
  249.         
  250.         if( KeyTemp != DATA_KEY_Null )                                // 如果不为空
  251.         {
  252.                 uchar CountTemp = 0;
  253.                 do
  254.                 {
  255.                         delay125us();
  256.                         if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
  257.                         
  258.                 } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动
  259.                
  260.                 while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
  261.                
  262.                 return KeyTemp;        // 有键按下返回键端口数据
  263.         }
  264.         
  265.         return 0;        // 无有效键返回0
  266. }



  267. //加一
  268. uchar  INC_Number(uchar Number, uchar Min, uchar Max)
  269. {
  270.         if(Number >= Max) return Min; else return (++ Number);
  271.                
  272. }

  273. //减一
  274. uchar  DEC_Number(uchar Number, uchar Min, uchar Max)
  275. {
  276.         if(Number <= Min) return Max; else return (-- Number);
  277.                
  278. }

  279. // 检测到有按键后 这里执行按键任务                        
  280. void execute_key_task(uchar ucKeyValue)        
  281. {
  282.         uchar state = 0;                                                //定义调整数据的状态变量
  283.         uchar keyValue = 0;                                        //定义键值的临时变量
  284.         
  285.         if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出
  286.         
  287.         //是设置键继续-----------------------------------------------------
  288.         
  289.         putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT               
  290.         putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        
  291.         
  292.         while(1)
  293.         {
  294.                 keyValue = GetKey();        
  295.                 if(keyValue == 0) continue;
  296.                
  297.                 switch(keyValue)
  298.                 {
  299.                         case DATA_KEY_Set:
  300.                         {
  301.                                 // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
  302.                                 switch(state)
  303.                                 {
  304.                                         case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面
  305.                                         {
  306.                                                 state = 1;                                                
  307.                                                 putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
  308.                                         }
  309.                                         break;
  310.                                         case 1:
  311.                                         {
  312.                                                 uchar tempMax = uiD - DATA_uiD_Min;
  313.                                                 if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
  314.                                                 if(uiH > tempMax)
  315.                                                 {
  316.                                                         uiH = tempMax;
  317.                                                         putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
  318.                                                 }
  319.                                                 else if(uiH < 2 + 2)
  320.                                                 {
  321.                                                         uiH = 2 + 2;        
  322.                                                         putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
  323.                                                 }                                                        
  324.                                                 state = 2;
  325.                                                 putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
  326.                                         }
  327.                                         break;
  328.                                         case 2:
  329.                                         {
  330.                                                 if(uiL > uiH - 2)
  331.                                                 {
  332.                                                         uiL = uiH - 2;
  333.                                                         putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
  334.                                                 }
  335.                                                 return;        
  336.                                                 
  337.                                         }
  338.                                         break;
  339.                                 }
  340.                                 
  341.                         }
  342.                         break;
  343.                         // 如果按的是增加键,改变相应数据并显示
  344.                         case DATA_KEY_INC:
  345.                         {
  346.                                 switch(state)
  347.                                 {
  348.                                         case 0:
  349.                                         {
  350.                                                 uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);
  351.                                                 putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        
  352.                                         }
  353.                                         break;
  354.                                         case 1:
  355.                                         {
  356.                                                 uchar tempMax = uiD - DATA_uiD_Min;
  357.                                                 if(tempMax < 2 + 2) tempMax = 2 + 2;
  358.                                                 uiH = INC_Number(uiH, 2, tempMax);                                                
  359.                                                 putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
  360.                                         }
  361.                                         break;
  362.                                         case 2:
  363.                                         {
  364.                                                 uiL = INC_Number(uiL, 0, uiH - 2);        
  365.                                                 putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
  366.                                         }
  367.                                         break;
  368.                                 }
  369.                                 
  370.                         }
  371.                         break;
  372.                         // 如果按的是减少键,改变相应数据并显示
  373.                         case DATA_KEY_DEC:
  374.                         {
  375.                                 switch(state)
  376.                                 {
  377.                                         case 0:
  378.                                         {
  379.                                                 uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                       
  380.                                                 putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
  381.                                         }
  382.                                         break;
  383.                                         case 1:
  384.                                         {
  385.                                                 uchar tempMax = uiD - DATA_uiD_Min;
  386.                                                 if(tempMax < 2 + 2) tempMax = 2 + 2;
  387.                                                 uiH = DEC_Number(uiH, 2, tempMax);                                                
  388.                                                 putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        

  389.                                         }
  390.                                         break;
  391.                                         case 2:
  392.                                         {
  393.                                                 uiL = DEC_Number(uiL, 0, uiH - 2);        
  394.                                                 putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        

  395.                                         }
  396.                                         break;
  397.                                 }
  398.                                 
  399.                         }
  400.                         break;
  401.                         
  402.                 }
  403.                
  404.         }
  405.         
  406. }



  407. // 蜂鸣器        
  408. void        buzzerCall(void)
  409. {
  410.         uchar        i;
  411.         
  412.                 for(i = 0; i < 90; i++)
  413.                 {
  414.                         io_Buzzer = 0;
  415.                         delay100us();
  416.                         io_Buzzer = 1;
  417.                         delay100us();
  418.                         delay100us();               
  419.                 }
  420.                 delay100us();        
  421.                 delay100us();        
  422. }

  423. //计算水位
  424. bool CalculatedWaterLevel(void)
  425. {
  426.         uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置
  427.         uint          uiTime;                                                //声波传播时间
  428.         ulong         ulDis;                                                //实时测量到距离        
  429.         
  430.         uiTime = TH0 << 8 | TL0;        
  431.         ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
  432.         
  433.         TH0 = 0;
  434.         TL0 = 0;        
  435.         
  436.         if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;
  437.         {         
  438.                 g_flag = isNo;               
  439.                 TR0 = 0;
  440.                 putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
  441.                
  442.                 //阀门动作:               
  443.                 // if(g_flagSwitch == isYes)
  444.                 // {               
  445.                         // io_Control_Inlet = isio_Control_Inlet_OFF;               
  446.                         // io_Control_Outlet = isio_Control_Outlet_ON;
  447.                         // g_flagSwitch = isNo;
  448.                 // }               
  449.                
  450.                 //指示灯:
  451.                 ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
  452.                 ioLed_Green = ! ioLed_Green;
  453.                 ioLed_Yellow = ! ioLed_Yellow;
  454.                
  455.                 // 蜂鸣器叫:        
  456.                 if(buzzerCallFlag == isCall)
  457.                 {
  458.                         buzzerCall();                                        // 蜂鸣器叫        
  459.                 }
  460.                
  461.                 return isNo;                                                                        // 返回错误信息
  462.         }
  463.         else
  464.         {
  465.                 ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离
  466.                
  467.                 if(ulDis > uiH)                                                // 如果水位超高
  468.                 {
  469.                         
  470.                         //阀门动作:
  471.                         io_Control_Inlet = isio_Control_Inlet_OFF;
  472.                         io_Control_Outlet = isio_Control_Outlet_ON;        
  473.                         g_flagSwitch = isNo;
  474.                         
  475.                         //指示灯:
  476.                         ioLed_Red = ! ioLed_Red;                        // 红灯闪
  477.                         ioLed_Green = isLedOFF;               
  478.                         ioLed_Yellow = isLedOFF;                                
  479.                         // 蜂鸣器叫:
  480.                         if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
  481.                         {
  482.                                 buzzerCall();                                        // 蜂鸣器叫
  483.                         }
  484.                         
  485.                 }
  486.                 else if(ulDis < uiL)                                        // 如果水位超低
  487.                 {
  488.                         //阀门动作:        
  489.                         if(g_flagSwitch == isYes)
  490.                         {               
  491.                                 io_Control_Outlet = isio_Control_Outlet_OFF;        
  492.                                 io_Control_Inlet = isio_Control_Inlet_ON;        
  493.                                 g_flagSwitch = isNo;
  494.                         }        
  495.                         
  496.                         //指示灯:
  497.                         ioLed_Red = isLedOFF;
  498.                         ioLed_Green = isLedOFF;
  499.                         ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪
  500.                         // 蜂鸣器叫:                                                
  501.                         if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警
  502.                         {
  503.                                 buzzerCall();                                        // 蜂鸣器叫
  504.                         }
  505.                         
  506.                         
  507.                 }
  508.                 else                                                                // 水位在正常范围
  509.                 {        
  510.                         ioLed_Red = isLedOFF;
  511.                         ioLed_Green = ! ioLed_Green;
  512.                         ioLed_Yellow = isLedOFF;        
  513.                         
  514.                 }
  515.                 putThreeCharToLCD1602(lineTow, i, ulDis);
  516.                 return isYes;        
  517.                
  518.         }
  519.         return isYes;
  520. }

  521. void main(void)
  522. {
  523.     initIO();            //初始化IO端口   
  524.     delay500ms();         //启动延时,给器件进入正常工作状态留够时间   
  525.     initLCD1602();     //LCD初始化   
  526.     putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");    //显示distance (总)距离(检测探头到水库底部的距离)D
  527.     putThreeCharToLCD1602(lineOne, 8 + 2, uiD);        //显示三位数值
  528.     putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");    //显示设定的最高报警水位H
  529.     putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        //显示三位数值
  530.     putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");    //显示设定的最低报警水位L
  531.     putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        //显示三位数值
  532.     putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");    //显示当前CURRENT水位C
  533.    
  534.     initTimer0();        //初始化定时器0
  535.     initTimer1();
  536.    
  537.     //阀门动作:初始先排水
  538.     io_Control_Inlet = isio_Control_Inlet_OFF;   
  539.     io_Control_Outlet = isio_Control_Outlet_ON;
  540.     g_flagSwitch = isNo;   
  541.    
  542.     while(1)
  543.     {
  544.         io_US_TX = 1;                    //启动超声波模块信号
  545.         delay10us();
  546.         io_US_TX = 0;
  547.         
  548.         while(io_US_RX == 0);            //等待计时开始
  549.         TR0 = 1;                            //开启定时器0,计时开始   
  550.         IT1 = 1;                         //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
  551.         EX1 = 1;                        //使能外中断INT1        
  552.         
  553.         while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出   
  554.         {
  555.             uchar ucKeyValue = GetKey();                    //在等待中检测按键
  556.             if(ucKeyValue) execute_key_task(ucKeyValue);    //如果有键按下则执行按键任务   
  557.         }
  558.         
  559.         if(CalculatedWaterLevel() == isNo) continue;        //计算水位,如果超出范围返回isNo并重新循环        
  560.         
  561.         TR0 = 0;        //暂时关闭定时器0
  562.         //清零定时器和计数变量以及标志
  563.         TL0 = 0;        
  564.         TH0 = 0;        
  565.         g_flag = isNo;
  566.         ucCount = 0;
  567.         g_flag05s = isNo;
  568.         
  569.         TR0 = 1;        //打开定时器0                    
  570.         while(g_flag05s == isNo)        //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果
  571.         {            
  572.             uchar ucKeyValue = GetKey();
  573.             if(ucKeyValue)
  574.             {
  575.                 if(ucKeyValue == DATA_KEY_DEC)
  576.                 {
  577.                     g_flagBeepTimer = isNo;//用减小按键取消报警标志
  578.                 }

  579.                 execute_key_task(ucKeyValue);    //如果有键按下则执行按键任务   
  580.             }               

  581.         }   
  582.         TR0 = 0;        //暂时关闭定时器0
  583.         //清零定时器和复位标志
  584.         TL0 = 0;   
  585.         TH0 = 0;   
  586.         g_flag = isNo;        
  587.         
  588.         //-----------------------------------
  589.         //水箱清洗提示:
  590.         
  591. ……………………

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


全部资料51hei下载地址:
基于单片机超声波液位控制器设计.7z (4.14 MB, 下载次数: 633)


评分

参与人数 2黑币 +55 收起 理由
无名小白0 + 5 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:137767 发表于 2018-9-19 20:10 | 只看该作者
好资料,谢谢分享。
回复

使用道具 举报

板凳
ID:400659 发表于 2018-9-20 18:30 | 只看该作者
实用,做工也很好,值得学习
回复

使用道具 举报

地板
ID:401209 发表于 2018-9-24 15:21 来自手机 | 只看该作者
币不够怎么办
回复

使用道具 举报

5#
ID:89286 发表于 2018-9-25 22:25 | 只看该作者
thanks for sharing
回复

使用道具 举报

6#
ID:355489 发表于 2018-9-26 21:51 | 只看该作者
谢谢分享
回复

使用道具 举报

7#
ID:104477 发表于 2018-9-28 02:05 来自手机 | 只看该作者
编译通不过
回复

使用道具 举报

8#
ID:423360 发表于 2018-11-8 23:58 | 只看该作者
赞一个 好东西
回复

使用道具 举报

9#
ID:423360 发表于 2018-11-12 01:23 来自手机 | 只看该作者
wylx 发表于 2018-9-19 20:10
好资料,谢谢分享。

你做出来了吗?。我做完硬件但是显示不出来。不知道是不是软件的问题。
回复

使用道具 举报

10#
ID:423360 发表于 2018-11-12 01:24 来自手机 | 只看该作者
xuiangin@com 发表于 2018-9-20 18:30
实用,做工也很好,值得学习

你做出来了吗?。我做完硬件但是显示不出来。不知道是不是软件的问题。
回复

使用道具 举报

11#
ID:423360 发表于 2018-11-12 01:25 来自手机 | 只看该作者
faridzled 发表于 2018-9-25 22:25
thanks for sharing

你做出来了吗?。我做完硬件但是显示不出来。不知道是不是软件的问题。
回复

使用道具 举报

12#
ID:423360 发表于 2018-11-12 01:25 来自手机 | 只看该作者
hjx820 发表于 2018-9-26 21:51
谢谢分享

你做出来了吗?。我做完硬件但是显示不出来。不知道是不是软件的问题。
回复

使用道具 举报

13#
ID:423360 发表于 2018-11-12 01:26 来自手机 | 只看该作者
hs88 发表于 2018-9-28 02:05
编译通不过

你做出来了吗?。我做完硬件但是显示不出来。不知道是不是软件的问题。
回复

使用道具 举报

14#
ID:303383 发表于 2018-11-13 21:26 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

15#
ID:433349 发表于 2018-11-29 19:19 | 只看该作者
东西不错,符合预期的设想
回复

使用道具 举报

16#
ID:476622 发表于 2019-2-22 00:18 | 只看该作者
与光电式液位传感器有什么区别吗?
回复

使用道具 举报

17#
ID:476622 发表于 2019-2-22 00:38 | 只看该作者
用光电式液位传感器会怎么样呢
回复

使用道具 举报

18#
ID:357502 发表于 2019-5-20 11:29 | 只看该作者
感谢分享
回复

使用道具 举报

19#
ID:357502 发表于 2019-5-21 12:50 | 只看该作者
有protus仿真吗
回复

使用道具 举报

20#
ID:687485 发表于 2020-1-20 08:51 | 只看该作者
这个测试的距离是多少?
回复

使用道具 举报

21#
ID:732180 发表于 2020-4-27 20:06 | 只看该作者
有大神仿真做出来了吗,我做出仿真LCD没有数据显示
回复

使用道具 举报

22#
ID:741892 发表于 2020-5-8 14:47 | 只看该作者
很棒 很实用 很好
回复

使用道具 举报

23#
ID:749615 发表于 2020-5-12 09:25 | 只看该作者
这个有人实现吗?
回复

使用道具 举报

24#
ID:712493 发表于 2020-5-13 14:38 | 只看该作者
那个超声笔模块哪里买的?好像有电路在里面
回复

使用道具 举报

25#
ID:712493 发表于 2020-5-13 14:39 | 只看该作者
超声波测距跟温度有关?这个没有?
回复

使用道具 举报

26#
ID:76671 发表于 2020-7-7 16:24 | 只看该作者

开机就显示000就卡死了,按任何按键不会动,重启也还是这样,能帮忙看下什么问题吗?
回复

使用道具 举报

27#
ID:76671 发表于 2020-7-8 00:03 | 只看该作者
28674500 发表于 2020-7-7 16:24
开机就显示000就卡死了,按任何按键不会动,重启也还是这样,能帮忙看下什么问题吗?

问题解决了,上电要给Trig一个高电平延时0.5S再低电平才能启动超声波模块
现在问题是,通过按键设置的参数无法保存,重启又复原了。
回复

使用道具 举报

28#
ID:76671 发表于 2020-7-8 11:03 | 只看该作者
还有程序有问题。超过50CM就显示不准了
回复

使用道具 举报

29#
ID:906820 发表于 2021-4-16 15:03 来自手机 | 只看该作者
这个布线怎么布到同一层,
回复

使用道具 举报

30#
ID:1051985 发表于 2022-11-19 12:38 | 只看该作者
fj51hei 发表于 2020-5-13 14:39
超声波测距跟温度有关?这个没有?

没有,但是可以增加一个温度检测模块
回复

使用道具 举报

31#
ID:34298 发表于 2022-12-29 13:56 | 只看该作者
这篇文章优秀实用
回复

使用道具 举报

32#
ID:824664 发表于 2023-3-13 09:21 | 只看该作者
思路清晰,有实用价值,好好学习。
回复

使用道具 举报

33#
ID:1073409 发表于 2023-4-22 17:33 | 只看该作者
28674500 发表于 2020-7-7 16:24
开机就显示000就卡死了,按任何按键不会动,重启也还是这样,能帮忙看下什么问题吗?

你好 你在吗 我想请问一下 19年你做的水位自动检测相关的问题 我们按照这个做的液晶显示屏不亮 请问是什么原因呢 希望你看见可以回复我!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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