一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4119|回复: 7

基于单片机超声波液位控制器设计

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑
3 s; t# b2 \& H% K" e% h4 {: N2 L  |, S4 \
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

7 V3 Z( [6 c+ D3 O. r( d
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

- S: o3 k$ x7 e: A+ t. x
按键功能分别为:设置键 增加键 减小键 复位键
4 _; S4 V# h+ e; c
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)
0 Y3 H4 `/ }# m6 _% h; S; L
发表于 2020-11-24 12:28 | 显示全部楼层
先下载学习学习。头次坐沙发
回复

使用道具 举报

发表于 2020-11-24 20:58 | 显示全部楼层
没程序?

点评

/*************************************************************** 名称:基于51单片机的超声波水位监测报警系统 单片机型号:AT89C51 单片机设置:时钟12T,晶体12MHZ 注:修改增加水泵控制和排水控制,即双  详情 回复 发表于 2020-12-4 09:56
回复

使用道具 举报

 楼主| 发表于 2020-12-4 09:56 | 显示全部楼层
本帖最后由 leishidianzi 于 2020-12-14 08:44 编辑 . o- N# A  S6 U* x5 k5 }7 I1 o
tdc31224 发表于 2020-11-24 20:587 \7 j7 M5 Z( y$ E# H# W" T3 w
没程序?
/ m1 \8 \( [: A) e6 n9 P
& [" b: |3 c  y7 T( l0 _
/***************************************************************
' }& P" v* t5 U# t# Z# q  ~        名称:基于51单片机的超声波水位监测报警系统
% `8 T1 T- y* @# e4 L7 C        单片机型号:AT89C51% O1 o& z4 Y/ f$ W( D) N9 Q
        单片机设置:时钟12T,晶体12MHZ
( A/ Y; B) w: p7 t( ?+ A1 B. S+ Q        注:修改增加水泵控制和排水控制,即双继电器
) X! @/ e( G0 ^0 v***************************************************************/* v! {# \3 {. M

: {+ V. E, {; P. H! U) o#include <reg51.h>! u6 g. |1 i, `  M& a
#include <intrins.h>                // 包含循环移位:_cror_
9 l. M4 U8 Q$ V) J1 [#include "main.h"     + x' @# I. ]' l$ ^( f- s0 K5 h0 c
//----------------------------------------------------------------------
7 I, u! {  O+ a- E0 p5 I
1 J( j# N, S' y& I. puchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};
: i4 G  m% G- {  P2 U6 x
+ k4 x) W) g7 I" L: nbool        g_flag = isNo;                //用于标记超时(65.536ms)           # Y& ]+ `0 D+ r8 Z$ p$ K& c0 @
bool        g_flag05s = isNo;        //用于标记0.52秒  
6 m) d$ Z; ?, }! Tuchar         ucCount = 0;                        //用于计数0.52秒     6 j0 x; O. T- V3 Z! W2 k
. x# ]6 |. U  B; B) S
uint        uiH =  86;                        //设定的最高报警水位 H5 h( r+ A4 i# U9 o2 ^" A
uint        uiL =  73;                        //设定的最低报警水位 L' D. R% x' H# p/ p5 P6 j# f  n
uint        uiD =156;                         //检测探头到水库底部的距离 D
; I8 k. H. j3 {4 d6 O0 i' L4 [/ s0 T3 F8 O2 w+ H# U
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志- ]$ V9 H- l, }6 Q2 d
bool        g_flagBeepTimer = isNo;        //定时提醒标志7 o$ l: W6 @- ]4 {
               
. o8 f/ i( }; `8 j3 m' R
- R) ^# ^5 U( W& `- H  x& E//-----------------------------------------------------------------------
- g# r/ m& j2 b// 延时10us6 B2 @; y9 t+ @( k% h
void delay10us(void)                //@12MHz5 `- t+ ~* `. k1 T4 Z" f
{
% @- G1 {" f8 p6 i* ]4 J6 J2 U        unsigned char i;/ @8 v4 v4 p! A. H
2 j) F) F! M* k0 p: _! [
        _nop_();
( H% t- E1 }# N' a$ S4 w        i = 2;. v; |* b+ d" Y3 _7 K
        while (--i);+ ]1 u& Z6 f6 U
}" L- W9 Y8 y% @  s6 j, E

+ S. u. ^+ n. p6 v4 D// 延时100us- N- M& z, l5 u
void delay100us(void)                //@12MHz
3 z' s, h& q) g{
: i; R& S+ L# p8 I        uchar i;
# V1 ?4 P* r* i+ h6 S- `( F8 }
5 ?* s9 l4 }# z  B: N        _nop_();$ m* k; j8 t# v- Q) g
        i = 47;# m* p) |# i1 W/ O5 k/ u2 w
        while (--i);& k  H8 D1 T4 g7 |" v+ I4 x+ U" H
}+ z+ Z! _+ [  a4 {/ V

7 z5 ^9 P! j  l! j4 q  `" _0 j, Z// 延时125us" q& w6 `1 ]2 ~* s6 H
void delay125us(void)                //@12MHz- V6 B/ N/ Z: `, @5 t6 g4 a
{
$ J. n8 q- Q% n7 p0 x# F$ c# D        unsigned char i;
! L+ t( z$ v' C        i = 60;# l- o. v; W9 ^. T! I" L
        while (--i);
' A+ F8 B, O4 ^7 |3 V}1 x# ^, c5 N7 |! f

4 E9 h6 n, U3 M4 G// 延时5ms
8 i  k4 A9 [; Y/ v, n, k5 P7 O+ nvoid delay5ms(void)                //@12.000MHz4 S& A+ J2 G/ H" o4 B& A
{
5 p1 }( x1 }. V+ H, s# o7 w        unsigned char i, j;& H! p4 T) {& |
, f; p( u  [9 d! Y9 _" u: o
        i = 10;
/ P" P( V; d+ l  k7 w' O0 v        j = 183;
# p: x- w* j3 n0 g  F        do, f* |6 i8 H# v1 `  [
        {
& ]6 ^# [6 x4 z" V' ~2 @                while (--j);
+ D! n, c7 B7 C: ~- s2 h/ k        } while (--i);/ n  \" X) \3 x3 Z% U4 J2 ]1 l
}7 y6 [1 X* k; B/ L- a" D4 J! S5 |. L! S
5 j. }. ~6 F; ~0 U* i  ?" k
// 延时500ms6 S. \  ]: b7 h  F- l
void delay500ms(void)                //@12MHz
3 W$ c) ]( w0 r/ O  b' J{
& Z- c: r* Y3 [0 e        unsigned char i, j, k;) N1 `2 o, j1 ]( l5 B7 n& U' L
9 v: v# }( F$ P# ~& n- i6 I6 _; S
        _nop_();  t* @: c7 h3 L4 J1 d% x# n0 K
        i = 4;! q* K) i1 B- E$ H
        j = 205;
4 u# Y, M$ l! K8 n( M6 w5 ~5 Y7 V        k = 187;
6 L0 l0 A  L. |, B0 q) a" Q  ?        do
, k/ p' e! P9 D+ W/ @        {9 E6 E8 Z, C, ?' p9 o3 |% M
                do
+ N7 @0 b) F! U7 K3 G                {5 t4 x+ V0 [- x7 F0 d; c% M3 N
                        while (--k);8 G. J) D, j. _8 u3 Q
                } while (--j);7 q8 T4 Y" M% M6 f) ]( n
        } while (--i);, X+ @: H# [+ m! _
}3 ~3 K- |% K* p$ @

- l* l( l. ?1 @6 h0 f//-----------------------------------------------------------------------
/ k9 _& s* b1 H; o0 E% _//初始化IO端口                        - F- a4 ?. l+ }  v! U. D
void initIO(void)                                       
* h, q( R' x+ A" y* I& G% Z# g{4 c6 I, P9 j3 m# [, e9 K
        P0 = 0xff;
# W  X: ^8 D. v6 p% l6 r0 @        P1 = 0xff;% ?4 u) n! V% d0 O
        P2 = 0xff;
: H7 t% N0 Y% M+ b( w        P3 = 0xff;# b/ f4 m* A4 l; f& q% s
}
$ l' c- e2 M% g
. l: u8 m9 r# ~8 b* [$ C// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz; t' X3 p5 @* a' u+ @  @6 W! c, h
void initTimer0(void)               
7 P( d7 l* _' i# j( C% \{- b7 Y2 f' E; k3 n4 N  {" j
        TMOD &= 0xF0;                //设置定时器模式
$ N; }/ q2 J  u4 D' {        TMOD |= 0x01;                //设置定时器模式3 U3 ]9 _; X8 U4 J4 R, A8 h
        TL0 = 0;                                //定时器初值清零
/ D; ]( d8 c, S7 Q# X% t        TH0 = 0;                                //定时器初值清零. h8 x) ~* J6 R: _
        //TR0 = 1;                           //开定时器0
, T; P/ |+ L. ^, X: K8 t    ET0 = 1;                          //开定时器0中断
4 i* q9 w& @7 u. m2 |2 k    EA = 1;                             //开总中断            8 x; M# m( R$ {) W" V
        
: j1 a/ [: d( B! Z& j" t* y2 h$ K2 f8 `}
7 n  M; F3 r( p2 i4 F% Z6 a: M% G
' C2 k% \9 C/ g/ o: a1 M// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz9 ]" S' e5 ^) i' {) u
void initTimer1(void)                //50毫秒@12.000MHz! [; j4 V) n8 b- c  i+ A
{        / l$ L7 S% n- Q
        TMOD &= 0x0F;                //设置定时器模式  D+ P6 ^8 f: s0 f9 V$ n
        TMOD |= 0x10;                //设置定时器模式4 g! g) G9 }- U
        TL1 = 0xB0;                //设置定时初值
; W( |! S* A' |. w+ j( N/ B        TH1 = 0x3C;                //设置定时初值        
( s) |+ S) P5 ~$ |0 m: R. o        TR1 = 1;                //定时器1开始计时
# }6 ~9 o8 M* l% s        ET1 = 1;          //开定时器0中断
- y4 P* k- G5 O' H: |( G}
9 `* H* t' b' s3 K: T! |% f3 E8 ]1 s3 p
//-----------------------------------------------------------------------
! ?: M' ~& Q! R& D0 Z//定时器0中断* s' o; Q; ~& u! M7 k. i/ Z; @
void zd0(void) interrupt 1                  
8 U* }. S  `  J8 c+ C) Y' S{6 S/ b: p. [2 C: z  P: B  I# |6 Q- b
        
& x# u- x  h; q% \! w0 ~        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
0 Z0 B" w& ]$ }% L8 f' V* t; D        if(++ucCount >= 8)7 Z  X3 Z" V3 l9 h' m
        {) |/ f2 r$ j* J
                ucCount = 0;
  `: H9 X# ?! T- M/ X' M* ^                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时
' J( Y: ]7 }! Z, g. |* x) [" q        }% @# S* I( i" t5 N, M/ \
        TL0 = 0;                //设置定时初值
( f  }5 N0 v, w9 m* ?        TH0 = 0;                //设置定时初值
  |: u% n0 c+ z6 [3 W        5 T! f: P/ J- W8 _! v
}
: c# P3 N& g. |
0 @$ x- `- O9 f, W' K6 d! V0 M: E) M8 [2 ?# K" W
//定时器1中断 定时50ms
8 M* m+ S( Y8 p# D, bvoid tm1_isr() interrupt 3 using 1
/ H: L) D3 h( Z/ [# K- A- x{' D0 d3 q  u6 ~$ e
        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S( \0 v5 l' ?: a4 g1 y
        static uchar uiCount = 1200;                                //                        = 1分钟                . Y! a! U4 Q! K- `& G
        static uint uiCount_BeepTimer = DATA_BeepTimer;
5 N0 C- P( P- z3 Z% S/ l! F1 f9 ]6 o( o" c
        TL1 = 0xB0;                //设置定时初值
! s% ~) e& z0 F. W& s        TH1 = 0x3C;                //设置定时初值
  }( f; m2 V0 f. w- z9 n, N& B. a+ S3 g) p2 Q1 K
        if (g_flagSwitch == isNo)
  R8 W* j2 b/ T; s        {
' {+ |6 Y' v7 Z' y2 c& q) s7 }7 J                if (count-- == 0)               //50ms * 200 -> 10s4 J5 W8 H' y6 I( s' K3 c# G
                {. s6 G- Z3 D1 s5 |1 X4 u
                        count = DATA_switchTime;% K" ?& ]1 @5 M% }6 x% O2 c
                        g_flagSwitch = isYes;1 s8 K2 i, Y5 V5 r  ^! X/ Y
                        // TR1 = 0;5 c' ^* i% C5 [! t2 z. a# M6 ?
                }; P; G- g. l& \2 x/ g/ S' R7 Y/ `/ E3 ~
        }        
5 b* G' H1 N5 k% e% \" k        
, f* h, r/ ]' q6 s; H( U1 t        if(g_flagBeepTimer == isNo)" _* t$ `1 E& g3 j6 F
        {
' R7 e. r0 J9 S) e/ i" M                if (uiCount-- == 0)               //= 1分钟
. Z  }0 a% F+ U" ~2 B0 d                {
6 l: S4 r; ~7 {. G                        uiCount = 1200;
, D3 e# r: N- l' {. a                        if(uiCount_BeepTimer-- == 0)- L7 o4 X  }' j6 M
                        {
  L/ F6 t2 h, N4 G6 Q4 k) n  @; r" g1 M                                uiCount_BeepTimer = DATA_BeepTimer;
4 h6 O' Z# \; j* U# f' g' H3 Q                                g_flagBeepTimer = isYes;" h, _. e0 y6 J" g4 s2 |
                                // TR1 = 0;. Z8 P* x2 E/ T8 _6 G" o
                        }                        - @" h  V6 i8 l1 m. }! _7 _
                        
" k; Q1 m/ _. I$ W3 D* J                }
' U8 I1 d+ w  f) o
! C6 P/ m, I( O5 a        }9 d9 {4 s# R1 k6 c2 [/ p
}
6 t! \  v. W# g. A4 S
6 s# M# |  U* U0 E$ z//-----------------------------------------------3 f# _, p' a0 Y1 ]& M
4 M5 a. S2 R7 L; }- ?' [

( q8 y. e: |" K$ @( P% Z3 S' L7 p, a- K

# h6 ^2 t1 e3 G( G, H& H# U5 L# _5 r% @  ~2 S8 D4 x
//外部中断17 m% }' Z7 {% r, ^5 d( p2 ?/ A5 b
void exint1() interrupt 2
0 s! l) N) H) M, H9 b{
, Q" @0 O6 ], p    EX1 = 0;                         //关闭当前中断3 s0 q! G8 v7 W- }" Q
        TR0 = 0;                           //关闭时器0) p0 }; h4 n2 r
        $ I# e6 [8 ^) _7 D" @' s8 P$ q
}
' G0 m0 F+ C, ~6 d( S3 h9 N2 l3 H; y//-----------------------------------------------------------------------  }  r. D/ E9 l
' Q; |- J' y  i0 |' ~4 l
//读LCD忙状态并等待忙状态结束0 H  ^/ }0 G. D2 t+ _0 D7 X
void LCD_waitNotBusy(void)
; I* n  [+ w( k3 P' X; l( ~7 Z; K{
5 z& x7 D) G7 N        IO_LCD_Data = 0xFF;
% q. N8 [: O* ]) @        io_LCD_RS = 0;; v& w- n$ b; ~) U' r! W
        io_LCD_RW = 1;8 F1 I- x, Z$ u: }, r: t
        io_LCD_E = 0;
/ V! l: J, l( Z7 r7 _9 [        _nop_();2 W  G' L' k" S: W
        _nop_();
: L4 d2 Y3 F4 V        io_LCD_E = 1;
" r: D3 a, Y2 \# C+ ?" n        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙
% T: d8 F" x, V7 Z9 W4 f: n; W" F}' p) R2 F6 d" g# |$ P
" d( ~" U6 v2 c. Q$ |8 P0 ^
//给LCD写指令8 Z' K, Y1 ]# D" h/ x2 K
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测% |1 p0 u" W0 f
{. O: D0 `2 N# T' V  S+ \
        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙
6 ^6 K$ t9 H. @9 A: l        IO_LCD_Data = command;
1 ^2 [9 a% O) j1 A        io_LCD_RS = 0;( [) p( M% d# ?& M0 h* A
        io_LCD_RW = 0;        1 `( |8 l- B) o: |
        io_LCD_E = 0;: r  Y+ y% X1 h( ^
        _nop_();
; U. y3 [3 l1 J" B        _nop_();& h0 y7 o' C4 A5 _
        io_LCD_E = 1;        
. w; m7 K# y3 F}2 B- @. o( W) p# J

, l7 |" F! ]9 x4 {" H6 w+ n3 o//给LCD写数据1 G, ~; A, j/ B# D& C. A6 Q, U! ]0 }
void LCDWriteData(uchar dat) / m" ]1 L1 b' j  H
{) \- P3 d& J3 r  W0 w
        LCD_waitNotBusy(); //等到不忙
4 g6 O  x6 g8 y: h% K" P$ P" P        IO_LCD_Data = dat;
% @9 V3 R6 J8 `# g; g" k, c5 e% c        io_LCD_RS = 1;' I& Q& w/ v* C1 M# C
        io_LCD_RW = 0;
9 p" m1 s! {; x! }7 E2 ^2 g        io_LCD_E = 0; $ k7 Q5 g- B3 [; ^% ]5 R
        _nop_();
( F9 _0 [& O' i# V+ i        _nop_();  F  `5 V  {/ l
        io_LCD_E = 1;
' z; ^4 C9 h' B8 R0 Z}
/ y/ r; J1 p. k+ \5 f) }0 H( H: B4 o" r; c/ s

5 V& k8 l9 o. {5 d, i! F4 [
7 [5 F- Z4 E0 G+ S
7 c  S) M; |: K5 B+ _6 O3 k% A/ N+ U// 初始化LCD1602液晶显示屏9 X# b3 p9 c+ f7 N0 o; G: z5 E
void initLCD1602(void)
3 V/ V8 V/ }) N* O* \% K{1 V, B; ~: E6 N, G6 Y! r
        uchar        i;        
: n% D5 c, c; ?9 ~) O! Z        IO_LCD_Data = 0;                                                                // 数据端口清零
' s, {) q7 v4 `: C        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
0 R3 p: P% C+ b: F9 e9 p* A9 x        {
  p# k( R  }, o. \0 ]( f; @4 q4 p7 l                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号8 a2 r3 p6 K  J$ \/ h
                delay5ms();
+ x$ s" I3 q6 \+ |, ?2 |2 \6 F        }2 N& T( J6 P0 P! o2 v, [  i
        $ U) D0 Y( k! T3 U! l
        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号
5 p% j% ^4 _4 x3 z! ~! {  B        LCDWriteCommand(0x08,isReadBusy); // 关闭显示# \- N4 o7 V- S4 Y: `& n4 G
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
- N# v4 t, S/ \3 }$ I9 ~        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置3 T5 s8 ~' N! q  f  d
        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置% R  d* z. v, ~9 O8 ]
}( h3 D$ @0 O0 o5 l+ r

5 ~+ @$ ^' R& L# l: z, C$ M
, L: u) c( s& J4 v" g- {, b8 ^0 L6 [$ W' l
//按指定位置显示一个字符
6 f4 b: [% v, ^! \, A% ?' Xvoid putOneCharToLCD1602(uchar line, uchar position, uchar ucData)0 W5 J6 d" A! B/ B; A
{! H# m' l/ h) C/ w3 u" t
3 J1 l# V7 v" u( Q9 H; N0 t9 w$ a
        line &= DATA_LineMax;% A2 a6 H, k. Z1 d5 `5 _7 b
        position &= DATA_PositionMax;/ X$ p( v0 [% M1 J
        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;( Q' B% N) d6 E/ c
        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
! X0 P9 w& I% w1 s: i        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址1 z7 i# K7 x1 F" P
        LCDWriteData(ucData);                                                                  //写入字符的数据        / `0 i" j3 I7 V5 ?: D4 @* c. W
}
: q& \/ B( C- T, J: n- n9 {3 J/ F
. j0 b) K) {( x( p" c5 S. ~//按指定位置显示一串字符5 g0 I) U% M7 k2 ?
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData): P# i% l9 O$ D+ l( J8 m2 y
{
+ n/ B/ ^0 U' p! j/ c0 u0 z        uchar i;
& u3 i3 o" S2 k  o8 a        for(i = 0; i < count; i++)                                                        //连续显示单个字符6 n0 h1 y! b  L+ i6 s! D
        {, j3 Y, f8 d9 {( y
                putOneCharToLCD1602(line, position + i, ucData);        
0 }( E3 u. ?) ^; R        }9 n' D3 K9 V8 n7 h, g9 m
}
- \3 D  p. `1 h' g1 [% u3 F( Y
* \: h7 ^$ C* k5 p8 ?: k# a5 t' }, R' s' b* r
//按指定位置连续显示三个字符(三位数字)" E: u* l7 C5 F1 y/ j
void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber); x3 O: i6 Z8 J8 K
{- J0 l9 h0 g$ \1 }5 M
        uiNumber %= 1000;
7 H# m0 ]6 }- o# W7 Q/ h0 z  ?        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);: n0 U- ~2 V1 _5 F$ B; j3 U9 j
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
+ P) J- m8 }) _8 U7 C  ^        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
! A& ]0 ]" o' M4 E        0 A% J! a2 C7 m, A& ^
}
1 w0 H- E& a* j( e( n& ]/ i3 ?        
1 n: S. V: g( F* z3 q2 ?2 p
7 a  ?- P) c* z$ s9 v0 R1 {& m; D1 }4 D
* A3 T; P% H2 W7 F* N0 O5 m( s9 R// 按键检测子程序,有键按下返回键端口数据,无键返回01 X( B, f* y: C, D
uchar GetKey(void)
% U8 S" c( {( W- {$ p{        # z* I; i/ i$ W+ L, ~+ I* S( h" z6 @
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据          L" t& v% {& N1 V" Z, f- ^
        
! I1 Z# a, Q! Y        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空9 p1 N( c8 W1 A
        {
) r- L2 k( W: ~) P                uchar CountTemp = 0;9 J% v; \" I( J* M$ J
                do( R) r, I0 _4 W" c
                {+ V! h- a& H8 s  Q3 x- i+ e
                        delay125us();
# B/ N: M- O: a4 s                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
5 J' }4 y) a2 \: \                        ' J" Z( r+ Q& v# t* K
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动
- N  w: E( x8 {/ V               
  V' ~  r, P/ S                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
" f. Z8 {5 _( z                8 i" S1 ^& x2 Q/ y* Y
                return KeyTemp;        // 有键按下返回键端口数据: \- o, |* I) z' d7 M
        }, q" m, T2 |& f$ t* H
        7 G) F) j' n1 C; d& O3 n; _: ^
        return 0;        // 无有效键返回0. ~1 m1 _; R" i( Y4 a) [
}
# a. ^6 `. O7 h- U' S$ [6 S9 h6 l7 ^7 _* k; g: S$ j! V
$ D) _' c" Z" x/ q

# b( D' }) E- D2 K! D  R! }- v//加一0 Y  n/ ^0 e: t$ M% S
uchar  INC_Number(uchar Number, uchar Min, uchar Max)0 ~6 t4 {% n" X# |& K6 d" h, T- p
{
" G4 r- ~1 Q6 v( _        if(Number >= Max) return Min; else return (++ Number);: V" V: M! z  Q) K; }8 O4 i
                % \  H  E) O& u5 k6 M9 T
}
. l8 h7 y+ M, G
  ?% N% O4 j; d* d+ {' O* ?( l6 s5 s, w//减一- b7 N- o$ @; g$ U
uchar  DEC_Number(uchar Number, uchar Min, uchar Max)
" @/ j) x: t+ {2 C1 j/ T' C/ f6 d, |{# G# e7 M2 z/ S0 \9 U  g
        if(Number <= Min) return Max; else return (-- Number);
" ~$ i$ p6 Z) l! c' B  I+ X7 _                & z6 S) G9 S8 M7 M
}
) {3 g9 {& m, y& R2 ~) d* z) E
2 ]  E) K2 u6 m. s// 检测到有按键后 这里执行按键任务                        " I4 S4 ?7 y* s$ \* G3 S) ]
void execute_key_task(uchar ucKeyValue)        
% C7 c2 V% P; l! O5 p6 L+ \8 |{# x3 L. S7 g. g4 ~0 b1 ]
        uchar state = 0;                                                //定义调整数据的状态变量/ |0 g# b' ]# R) L
        uchar keyValue = 0;                                        //定义键值的临时变量
8 I( n" Q4 J+ p# f: x        ( }5 e+ L* n5 q
        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出
6 n8 ^$ H+ z* ?4 B        ) G7 i5 Q; Y2 P) a+ @. Z3 C
        //是设置键继续-----------------------------------------------------
3 [# s8 {# }3 z* R9 {        
2 T7 P0 N. |: ~+ |+ x7 M' q        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                " ?) C- l* X' s9 I& e) q4 ~
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        , F8 ]( h7 k0 O4 d& G  C8 `9 d7 D
        / H- j1 L$ I& M
        while(1)+ t+ Q" a; i: }4 U0 C4 G1 A
        {) P# R) b0 I( d4 L
                keyValue = GetKey();        " X% p) j, c, F3 k
                if(keyValue == 0) continue;' K! O- B9 f$ n8 Q7 m( v, E* ^; G
                $ ~, f2 m+ o2 P2 o8 y8 h/ W
                switch(keyValue)/ Y. ]# n" t/ Q0 b. Z5 [
                {3 H6 b( _  Y) ]8 z& v6 q
                        case DATA_KEY_Set:
: c$ j2 m8 O/ ^: ]  I% Z8 _                        {
) x& c* A" |* U8 l                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
7 |2 G  o$ \" b( B+ ~# X7 @; E: H                                switch(state)! N5 j) ]6 [# m0 S% A3 y
                                {
4 M. u! H0 w1 c6 K- G9 {0 @                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面9 p' i0 f  @) ~$ P' {+ d% K
                                        {% A5 |5 O+ G/ \, U% O/ u( N" k
                                                state = 1;                                                9 b1 L3 N4 j- c  `
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
, W3 e9 K# T4 U( N$ B3 r& D                                        }4 K& s/ h+ i. s/ T% ?1 Y
                                        break;
/ W1 l! Z' {7 H; C2 F                                        case 1:
& M% }/ V) I4 b& b5 k% h9 |                                        {
5 v" c6 A! _) G# T2 g                                                uchar tempMax = uiD - DATA_uiD_Min;
; g* W/ ~* M3 H& k; m                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                        - {8 T, G, K$ a
                                                if(uiH > tempMax)
4 S" y; W) n6 k6 B$ A                                                {! }9 O( y, t' k7 N$ n9 \5 P2 W2 Z2 ]
                                                        uiH = tempMax;
; |; f# F" A' k0 o. s( E% g                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
+ s" B; m. C* V                                                }
- o  d/ s! G2 S- R1 p* [/ b                                                else if(uiH < 2 + 2)
- _/ L1 ~! e7 \: W3 \                                                {7 t( @6 K: B: o, R& W1 u5 z/ U+ p. T
                                                        uiH = 2 + 2;        " g3 \; u5 _2 v. t9 n4 z
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);: c4 d/ v9 p- @1 K: P% `$ {: A
                                                }                                                        3 ]  a/ |' P- ~: ?5 a/ T8 W
                                                state = 2;! @" K, l" {3 e
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);8 V: C7 z6 a9 Y1 U# H- `
                                        }, Q2 W8 F# o9 r3 V
                                        break;  h4 P$ J0 f7 y9 L1 k- b
                                        case 2:
, z2 S# v+ i% N8 f2 [, O                                        {8 n  ~+ r1 \& O# R, {7 u$ ]2 r
                                                if(uiL > uiH - 2) + S/ C& u7 h0 [1 A, G* H7 n" o, {* U1 v
                                                {
" n' L/ p& L& S0 F7 K, j) o                                                        uiL = uiH - 2;
; X1 o, k3 i/ O, ]$ w; @) I5 w                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
5 D, _- p, F4 t+ R                                                }
! q% A+ c( _4 l                                                return;        $ r2 V9 ]- A% x. r* h+ N
                                                
8 Y; M* p4 F: U4 H, _" S                                        }
/ S3 q- R6 l# c( x; {" \0 a7 W                                        break;
6 o5 {( E0 _: o0 }8 k                                }
4 |' c% f8 W- p5 X                                2 g1 ]. I/ r5 \! b, C( _' i7 v2 U
                        }+ m( e8 s9 P6 R% |/ Y
                        break;
& f6 _3 B4 ^. [6 f' E                        // 如果按的是增加键,改变相应数据并显示
4 H) u) G! r6 E, Z5 g( l8 F8 |2 K                        case DATA_KEY_INC:) s. T" _8 w, u- V3 M4 N
                        {5 ?8 _! ^' ?# G5 S  _; d- v
                                switch(state)
* ^7 c/ b& h- F' T( U4 p. w                                {
! ], o/ D7 ?  _8 B& a- a2 k                                        case 0:
2 k# a6 B. P. G# C, i+ Y( \                                        {, H% |4 M' z% u
                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);4 B5 h1 l- h% R  e+ L1 s* ~2 j+ S( T
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        
5 m4 K9 ?, B% U' Y3 G* ^  J8 T- G" r9 t5 n                                        }, z( A- V3 r7 n, u. N) u
                                        break;
9 V5 Y4 b5 k. z/ \                                        case 1:
  J1 y' R  `3 G  g1 Q% h5 `, N4 W                                        {. r* C# J- @$ o" W- ?6 r7 i
                                                uchar tempMax = uiD - DATA_uiD_Min;' L' ~1 S" L: D: q  L
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
# ]6 l7 |7 f: R) ?) f                                                uiH = INC_Number(uiH, 2, tempMax);                                                7 m9 \) h* k# P  W: N0 ]. e
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
9 d0 l2 I/ f7 j2 `% u; }; b3 y                                        }
2 O2 M9 v2 I5 b) S. K                                        break;/ s% n4 [% c$ ^8 b6 y" ?' \4 D
                                        case 2:* ?# E  n7 g( A. ?& C4 S/ |8 D0 u1 R
                                        {
( i( S5 t# w" s, @, j* n& t% V                                                uiL = INC_Number(uiL, 0, uiH - 2);        
1 Q; F, V% S) H8 n$ g+ s  q0 @                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        " r: {6 X8 E1 T; Z
                                        }
; k# j3 Q/ N( F8 }+ }, x                                        break;. p$ M" H3 u) |8 u7 D
                                }; t- v4 q: w* g3 }( j. c$ L9 X
                                
# e7 P2 O' P7 Z                        }
+ R: e, _& Q% \                        break;
/ B1 D. O) t5 p+ u) d* R: M; d                        // 如果按的是减少键,改变相应数据并显示" r( @% j! N+ X8 d2 F1 x
                        case DATA_KEY_DEC:$ Y0 E) b1 p$ o5 M
                        {
4 ?  v) g6 W& c                                switch(state)
) F2 i  l/ d) @# O- o8 I9 ^1 W0 d8 X                                {
2 a" p, @4 W! r7 r1 I" `- G                                        case 0:" k6 y4 r2 R; h& A
                                        {# B7 g6 @* v. v
                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        $ I+ B; d+ [2 X! o9 B
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
- m) `8 h9 s1 m4 X+ e8 G# E                                        }; a8 m& y/ }* {
                                        break;
. X! p0 \7 E5 c9 n                                        case 1:
1 m! [4 t! p& S* `( s                                        {: E/ q: S! }: `. _7 D
                                                uchar tempMax = uiD - DATA_uiD_Min;
8 [( _6 B+ V7 `" u) X7 o4 b7 v                                                if(tempMax < 2 + 2) tempMax = 2 + 2;! h/ o( R: M- {( F
                                                uiH = DEC_Number(uiH, 2, tempMax);                                                
; c, @4 ]" g3 q+ k$ Z                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        : R6 e/ G7 ?& [! G
& r1 r( K9 z! a; F6 M7 l
                                        }* @, @8 ~2 r1 ]" i/ [
                                        break;* I( c8 Z; ?1 ^) K* Y8 r5 v
                                        case 2:3 y/ \, _6 C- Z+ H5 @8 N* h& ~
                                        {0 k: w4 p9 g: C5 p
                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
6 t% H7 P1 k# F; Z3 m( @                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
1 u" q+ v) s3 R/ K" Q; o/ M/ m' s2 I+ w# D) V& s* j5 }
                                        }
( g9 h  W/ D2 ]1 T. P                                        break;
) O+ a- J, e9 _# I* z: z& O* A0 z                                }9 b5 n) k& P  k5 {
                                
! e6 G. g& u4 d& r, P3 k7 B4 j2 S                        }
' ^! W; K8 N) ~- |; n0 N) j                        break;" b- y0 a3 p# \' I( L
                        ! ~$ F$ a# @( E/ B# T
                }
! w) ?4 {; }. p! {0 z                ) Q4 C8 i4 O- f8 g
        }
' |6 K) |2 o; {* C6 F4 R        0 y2 Q; ^. n4 o- u
}' y& ?. t& T: M: k) g+ w
  m) T6 H5 Q3 P& d4 c# Y; e

  R( L: a) X+ `1 G- ^, g( C1 Q! a2 m
* H4 @6 G8 O4 ~" X* p; h// 蜂鸣器        " @7 M7 R' n5 [7 r( f% l" c
void        buzzerCall(void): J  n" O* E3 @' _  `. ~
{, A' l! c. {9 ?. a; }
        uchar        i;  u/ Q) p+ {- S$ Z- B; p8 G4 c
        
- Q$ R9 o, K4 C) m                for(i = 0; i < 90; i++)) M+ P9 l% B6 i3 `( p" L2 ^
                {
) H  a* q# w, S. I7 D* s                        io_Buzzer = 0;  v/ q5 N1 ~8 _% t8 G2 l
                        delay100us();0 m! k$ v0 ?3 s, g) @% ^9 m
                        io_Buzzer = 1;1 y8 D- t$ j  |- Y% w) J$ T
                        delay100us();1 U8 G' ~( k/ c5 ?. [- W2 Y% w
                        delay100us();                " w: x  h; C- H
                }
) J; U# C9 J! Q, G  T5 I( R& f) V% r                delay100us();        2 W% t  M3 u1 ~; ^/ s! e" w/ t% y
                delay100us();        0 `: h5 A9 F, u' W1 s
}
+ r( f6 r$ }+ s6 e: {# T, _2 Q6 x+ p; j* b. w3 p7 [
//计算水位. F, A2 l/ F+ N( C
bool CalculatedWaterLevel(void)
" R2 t' X, w- a0 f- E# n5 m{
. k9 b- h* L+ x9 w5 Q        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置
% @7 x  r0 j# j& [6 W        uint          uiTime;                                                //声波传播时间6 B5 u5 P( t$ b+ ^2 ?- _# J0 N0 J( q
        ulong         ulDis;                                                //实时测量到距离        
1 u' p+ Q) u& `$ f! o        
3 u6 n/ I$ Z, c+ p. k        uiTime = TH0 << 8 | TL0;        
' P" ^+ t% U; N- k3 ?        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm& Z# J  b8 J" b  p" a
        
) a! ^# y1 X2 X' U        TH0 = 0;
' \5 W1 y4 J2 a4 j  ]        TL0 = 0;        4 I) Y, r* `& a* {& ~& q
        7 L6 A# m) A' R7 w4 y' e
        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;2 u, h  _+ R5 c: m
        {         
, F' P( ~/ A# P8 U$ V) s; ^                g_flag = isNo;               
; m7 H) r% j: j% K5 J* l9 U9 X" M                TR0 = 0;/ R3 F+ m* W0 R- z1 i& f0 }* m
                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 5 c0 i9 ?7 E- V" e- [
               
; e$ c1 d# K( {7 T                //阀门动作:                ! U- x+ S' D( H0 u" E7 V
                // if(g_flagSwitch == isYes)+ ]2 S0 ]* Y+ n# _) E5 R
                // {               
8 K* G# V) }" _, F6 C! l8 n" b* L                        // io_Control_Inlet = isio_Control_Inlet_OFF;                - L6 \/ @1 R7 z8 {1 e0 B- E. }
                        // io_Control_Outlet = isio_Control_Outlet_ON;
4 B  o) h2 z" k7 F, S( ]& {3 a                        // g_flagSwitch = isNo;
0 N2 c6 N! H  ~! w) C5 S                // }               
; n* I3 E4 w5 x0 }* K% l. m7 B1 n" _               
6 S: c6 h- f7 y; b1 t. E                //指示灯:
/ |+ b  r( H* E/ u: [# r: e5 ?                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮' w5 E) d5 s- t9 n
                ioLed_Green = ! ioLed_Green;; Y, R$ Y1 C9 |3 V# k4 w
                ioLed_Yellow = ! ioLed_Yellow;
0 ^5 b8 h/ K: s* I5 Q% ~                2 O1 H3 n' N9 _% O0 G$ n( ]
                // 蜂鸣器叫:        
  K  k: p' H; F5 L* ~                if(buzzerCallFlag == isCall)1 o& }! C! z" V( q* K
                {
  |4 x% g! \7 T( a6 K9 l. J3 K! B                        buzzerCall();                                        // 蜂鸣器叫        , p( l; q9 e# ^1 a, o! n" `
                }
8 a# \# [( {+ c( N0 y0 B$ |5 A% v                . }6 g5 g* v( Z* B7 f
                return isNo;                                                                        // 返回错误信息( A* x3 H+ d7 h( M1 [
        }
8 T& U+ c) {, o  R        else$ p2 ^. I1 e7 ~" b
        {  k( g0 U5 ?/ l( l& Q' ]# N
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离% X2 O) ^! Z8 _5 A$ d
                5 Q( N0 A! A1 o! Y, |: ?
                if(ulDis > uiH)                                                // 如果水位超高
% z3 Q6 l% g% G                {
+ i4 j9 i$ N! d. F  B                        ' Z, D9 M' j+ a. z& f$ _
                        //阀门动作:% A3 A, [/ P: t5 G% l& G
                        io_Control_Inlet = isio_Control_Inlet_OFF;
0 x& M, Y- q4 v# ]                        io_Control_Outlet = isio_Control_Outlet_ON;        & S$ F: b9 q0 u8 U% a3 N! `
                        g_flagSwitch = isNo;0 o( {* z$ o  p( u( [" E3 ^  a
                        " m1 g: R6 \9 l) p- X$ \5 D
                        //指示灯:% }, m4 ~, x) a' f) h9 {
                        ioLed_Red = ! ioLed_Red;                        // 红灯闪
6 Z! l/ N, L0 C/ `                        ioLed_Green = isLedOFF;                $ b- N, H4 w/ a4 J/ G
                        ioLed_Yellow = isLedOFF;                                
) O$ _. C  V+ j9 [1 U                        // 蜂鸣器叫:
6 `% x3 S* m3 C                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
  I3 y1 v& S2 ]                        {
/ s+ A6 C: U2 R, S; [7 X+ o0 h  n! Y1 i                                buzzerCall();                                        // 蜂鸣器叫% ~' `2 j$ R+ ?% i! r! c
                        }3 c+ ]( n0 |, B
                        
* q7 M0 q' C( f6 C; K, {# s0 |- \                }
% @4 z3 p/ S7 Q- G                else if(ulDis < uiL)                                        // 如果水位超低  [% a8 E; j9 Q
                {
0 Q4 h0 f7 r) y( x% L                        //阀门动作:        ) @# f: W/ b# E+ r: b
                        if(g_flagSwitch == isYes)
. e$ V$ ^, L5 b                        {               
- R. l# c' ]' k/ v                                io_Control_Outlet = isio_Control_Outlet_OFF;        
8 k! ?; ~7 X( u6 y! J% r4 O                                io_Control_Inlet = isio_Control_Inlet_ON;        1 D. S5 X/ V6 h8 D  e; N2 ^1 v
                                g_flagSwitch = isNo;1 n8 V, g7 Q% I& [8 H
                        }        4 h& P2 c; }6 W& ?2 A6 y- k
                        ; e4 |6 A: h' {! p
                        //指示灯:
4 U9 u% q8 R1 t9 E  d0 _                        ioLed_Red = isLedOFF;: M5 F* v" x  |, |1 j$ U
                        ioLed_Green = isLedOFF;
$ W! g. M* x; {1 P8 W0 w" Y" E                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪$ V9 k& z( ]" B' N  w' [4 b3 L: y
                        // 蜂鸣器叫:                                                , b" P# c3 R, @
                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警0 m! Y: ]# p( B2 C3 Z, x
                        {5 E$ G0 m4 G7 l0 }1 N! z
                                buzzerCall();                                        // 蜂鸣器叫6 {) u& P9 P( p) r  r" }/ s6 |6 c
                        }! Q. J! W; n, q: {& p
                        
% E7 u1 b* A) L) _% C: z                        ) D4 a0 h& ^. U
                }  l& R- v3 \  O0 G1 l! t
                else                                                                // 水位在正常范围 ; `) k9 N, ^# C  z: ~
                {        + X+ o8 ?* M. K
                        ioLed_Red = isLedOFF;
" R& G6 T5 F3 _4 j                        ioLed_Green = ! ioLed_Green;2 ^4 P) r# x6 j: Q# e9 r* S
                        ioLed_Yellow = isLedOFF;        
  v3 ~0 h$ S, k& c( L: Z) Z( I$ O                        
9 y7 g8 T1 O" L& c6 ]                }1 Z9 l- P' \% a) j( Z6 F
                putThreeCharToLCD1602(lineTow, i, ulDis);' g! \$ b/ Y& N& }
                return isYes;        1 ?- h$ c% I; ?# j6 e% g2 L
               
$ @  \& H5 T7 }+ [        }) S! I( f% x! q" p3 y2 v. l
        return isYes;/ @5 u! x2 R% A1 @
}
/ F, O1 D7 ~3 K5 G/ q8 w2 ?7 ^# Z! W( K, |" B' ]9 B
/*********************************************************/4 `  ~8 p  e- u; P" V4 h( ]
void main(void)1 g% [/ h3 Q- o5 _  x
{0 G8 w/ e: r) l& \
        initIO();                        //初始化IO端口        $ e9 ^. e8 }5 w+ Y5 C$ I3 h
        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        
1 M6 ~1 P, i! V' ^& B! A        initLCD1602();         //LCD初始化        8 h$ a0 k! \% z& H; W' G5 p$ r* @
        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D/ S) X7 k2 |5 s) i1 v
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值, S/ S" A6 \' c1 U- H( m$ v
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H( ~/ J; `5 y* t: x7 K; T
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值8 |5 g9 N: `, q( h
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L
8 J& o( `7 E5 x1 B) \" Z1 Z        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值7 R" R  U+ ?4 n0 p3 W4 N
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C! }* ^* i7 |( d& y, }% _8 z
        
* j$ q. M& h) x3 ]% v7 L        initTimer0();                //初始化定时器0
9 n& m9 b- q5 F        initTimer1();
* D& u/ q, E  W' k6 ~7 O        & y* f; }- i+ Q+ W8 L" ^# ^
        //阀门动作:初始先排水
  U1 k1 n" e6 ^* v" V* j, g$ K9 d        io_Control_Inlet = isio_Control_Inlet_OFF;        9 I: f  o; u% E+ _
        io_Control_Outlet = isio_Control_Outlet_ON;
0 s9 q1 A8 W( o        g_flagSwitch = isNo;        & o% Z2 Y9 Z. W9 S
        
. ~4 r3 `( ^& n/ G9 V/ T        while(1)
2 Y9 j( [/ Y. V# F        {
; j* |6 Z* ?0 ^                io_US_TX = 1;                                //启动超声波模块信号
8 ^7 \  P) ?* J' T/ ?2 x9 x8 S                delay10us();# l: S& B5 x& \; T5 b# `  q) m
                io_US_TX = 0;
1 S4 q; [# }* c& L( j' m# d! }               
( t6 f7 T7 f3 r' j& E# E; K                while(io_US_RX == 0);                        //等待计时开始* q. N/ n# x$ B
                TR0 = 1;                                                    //开启定时器0,计时开始        
/ d# F2 \* E: p4 [                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)4 \" M( ?' S- F* ]  t
                EX1 = 1;                        //使能外中断INT1                % D( ]8 d! S9 e2 J: D
                3 s/ Z5 @+ g/ w3 V+ |/ \- j
                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        
. |3 n( f! h; A& [                {$ ^) f" ~% Y# I) A* U
                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
5 K% B8 s+ A& u+ \                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
2 e8 k$ {3 L& q# X" n9 G                }
' d+ B3 J& I$ g# Q                  F/ _" @1 y/ j4 k6 n- B* z
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环               
2 C8 l9 C2 u2 s( b2 g$ h- x                5 ]( {* {/ v- ?2 \! [! p2 H4 w
                TR0 = 0;                //暂时关闭定时器08 v" j2 C3 u7 k, i% T" f( d
                //清零定时器和计数变量以及标志
% u5 U" _: h% _- m5 `, o                TL0 = 0;               
" x  M. X# b4 `! D2 u  W6 v2 c9 e' o                TH0 = 0;               
/ H# I, E3 N( E; c                g_flag = isNo;" p/ I4 z# p0 @( C3 C& X% A
                ucCount = 0;, E1 }' l, X) k0 {
                g_flag05s = isNo;
* [( l3 L/ d5 z3 j6 [) j* j" o               
' }  U3 V  E2 ^3 U                TR0 = 1;                //打开定时器0                                       
; z; |, a+ o) u                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果) v1 S4 b- o+ b4 J: |- f; l) w) _6 t7 B
                {                        - u* {9 T$ W4 R" O$ Z9 P
                        uchar ucKeyValue = GetKey();
' z# `% W" H" b& H7 M3 d* t                        if(ucKeyValue)
9 F/ F. K( o9 O1 q! f8 n: ?                        {
" I' w; G; f, X8 v4 O                                if(ucKeyValue == DATA_KEY_DEC)3 P" @; ~( i! p, h: N. k3 |$ O
                                {
( F- R0 P/ w6 n/ o9 V                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志2 B- }% G" y5 h; @2 ?5 ?
                                }) |1 T, h  \" S4 S) s& S& z/ A! z, O1 D

! ~9 H4 o/ w2 [+ v/ l                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
" B# C& Q' l8 F' f+ y; Q; s                        }                                
1 B; z! Z9 k4 {4 s7 U- ?
7 c, W% H- t& p  [4 c                }        $ A- z1 I7 k& ~
                TR0 = 0;                //暂时关闭定时器02 o9 v( j! u0 t+ p
                //清零定时器和复位标志
9 p0 d7 V* L9 z* j: q; L                TL0 = 0;        
7 G8 d! ~8 `# l% ]# F, T+ M                TH0 = 0;        ( G  R1 x7 p9 I+ c8 q% S
                g_flag = isNo;               
, ~7 \) k; h, P& r. S7 _6 t% \                & k8 Y) S! L( k) o, d
                //-----------------------------------
' {* W8 v% s) S6 B" J2 I7 p                //水箱清洗提示:7 j9 O% S- d' y) B0 \1 s
               
% a- o1 M: {$ }7 D                if(g_flagBeepTimer == isYes)
& Y+ |9 }" H/ r) z0 |& _4 E" J                {
! K7 t# Q$ s  [0 T, J* |                        buzzerCall();               
' _" _4 `. \+ r* l( j& y2 k                        //用减小按键取消报警标志" `+ {5 k9 T  O% V! _; K
                          H7 E1 o9 ~. z, S6 @4 `
                }
. L# D; v" h5 k  O3 Z* w                //-----------------------------------+ b: V8 `! ]0 q, f+ E4 t
                , Z1 k" [9 x6 d" q2 C, R
        }- T7 Z* D" n: A, l
}7 M3 h' ~! H7 f9 U" X

. L- S/ s- y. f% r2 {2 P( F5 j* ?* y5 X' Z' r
#ifndef __MAIN_H__0 D# B' n8 d" |3 a, I% Q  T3 k/ z
#define __MAIN_H__4 c6 m5 M7 p, R" A0 y, M: T

' d2 b9 E7 e; R//-----------------------------------------------
" S! t9 [4 c$ w" ~% G8 \2 x; C' Mtypedef unsigned char         uchar;        //为了方便书写定义别名
( `1 }" y+ y) p! {/ k( Qtypedef unsigned int         uint;+ Q1 O2 Q. V- b3 \; F# S
typedef unsigned long         ulong;
7 C% t' Y7 w+ O6 ?. V; ~typedef        bit                                bool;9 ~4 }* N" W- E, |- g& ~

8 F* [/ V7 K' A) c! Lsbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口! _; Z. J+ t1 X1 |! G, \
#define        isio_Control_Inlet_ON         0
) \; C* e1 s3 C' t0 I#define        isio_Control_Inlet_OFF         1  A( u+ C2 R* S( V3 d

  J! |) e3 n# r3 z/ C! Asbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
0 m4 ?# i; X5 f- j0 e#define        isio_Control_Outlet_ON         0
" [4 k* v8 M8 y#define        isio_Control_Outlet_OFF         1
& h4 `% U% I, b) U7 P) t0 {2 U. P- \2 y+ W9 S
#define         isYes                18 N9 v3 i9 _* {3 l! ]
#define        isNo                0
6 Q! \. I; l7 f+ l, S//----------------------------------------------------, `; `. \1 c# G) M2 A
//定义超声波模块引脚& g* T( H! }1 c
sbit         io_US_RX          =        P3 ^ 3;        
; n. b6 @1 |! {5 s7 m! Vsbit         io_US_TX          =        P3 ^ 2;
  j) e2 l- q3 |; q- t//----------------------------------------------------
  E! r- R2 h3 D' w; }//定义LCD引脚1 m& h" R. M" N, c) z$ T- K' S/ k
sbit         io_LCD_RW          =        P3 ^ 6; " G8 t, n. s+ x! K# {
sbit         io_LCD_RS          =        P3 ^ 7;3 b% p6 h5 l8 T  k
sbit         io_LCD_E           =        P3 ^ 5;             ' z3 `3 O3 ^2 k( x6 o
#define          IO_LCD_Data                  P2
5 y) }7 D+ ]' x# x7 v$ b- \#define         lineOne                        0
" d$ t0 T) [8 H  V9 @( N, X' Y#define         lineTow                        1
! f8 z5 }3 u: U% j" O% H1 V  k& x! s# ~( r( J
#define        isReadBusy        1. r3 k7 d7 c8 c" p3 E2 `- e
#define        isNotReadBusy        0* x1 g$ D) w/ ?) S
# F/ [8 S$ a* m6 Y" c4 d
#define        DATA_LineMax                0x01                //LCD最大的行索引数$ n6 t" {7 w% Z9 ~9 L4 I# `5 V1 K
#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置
! \. J% p4 M4 u; |& r. }#define        DATA_LineTow                0x01                //LCD第二行的索引值4 _2 j0 J% z& ~) t8 z
//-------------------------------------------3 G* v& T( I3 t' ^0 x
#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时
  h& l: j7 k6 t; v& P) K$ g9 a//-------------------------------------------------  z+ H2 O( ?# Z# r# U. D
// 定义指示灯端口+ K( m( X+ b+ H  I9 s/ d
sbit        ioLed_Red = P1 ^ 3;0 R! N+ k4 ]9 [5 d& Y
sbit        ioLed_Green = P1 ^ 2;* O8 S8 h$ D) [' A1 d, E! ^
sbit        ioLed_Yellow = P1 ^ 1;9 W  e/ }- w/ k

; p, A/ W' c4 e. a% f7 w1 {) l#define        isLedOFF                1                        // 关闭LED+ v. S# J; H; D. o9 W, Y% ^
#define        isLedON                0                        // 点亮LED
$ B3 m+ v3 `2 I( A# X//---------------------------------------------
3 G4 U6 m5 g" U, ]: D//定义按键端口
+ g% Q# H, [! _" f0 ]; }3 i: o#define        IO_KEY                                P1        $ S% F" f$ A8 b
) d, K, Y# t5 g! K% e& Z2 C  M
#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据2 E' ~) R0 S+ d# i
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据
9 P' T8 ^# {1 A8 N. E# v+ H# O3 U& ?0 c
#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据" ~4 z/ [: R- Z+ E/ D4 f& s; X7 [
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据4 E0 ~" y& p1 B$ H% i
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据
8 j$ t3 ~+ o; j& P, `, E" e2 x//---------------------------------------------0 N3 f3 ?- h1 |# S# O9 ]) ]
//定义蜂鸣器端口5 _# G. S% ]; z9 K5 o
sbit        io_Buzzer        =        P1 ^ 0;        - r5 ]5 C) ]. H  T2 n$ ]1 ~
//---------------------------------------------+ Q& _* j' n" O) Y7 q! c4 o& Q
//定义检测探头到水库底部的设定距离范围 程序.jpg ) n/ W( o7 s) j9 n
#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
+ f3 v: H6 G$ [& E#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm1 `; c7 {* U+ f. J% Y2 Z2 Q2 b

3 I5 i: G2 r' ~! N  g; H6 H#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
2 w  U+ K& ~8 g; [( C3 m#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)8 o# J3 \4 s5 h, ~- ^- t7 n" R/ w
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
+ e# S/ t8 t% _
5 |- T8 I8 W" }! Q9 `3 ]  a( lsbit        buzzerCallFlag = P3 ^ 4;
% R+ j$ d+ x( l) n: K1 ]: h2 I#define        isCall        0& K+ }) l2 @2 n4 m1 T
#endif
5 Z, Y2 x9 }" V: B4 g# b* _% H; a
& s3 \; T! Z+ {( B$ V
9 J+ r2 u8 U" E5 }
. [6 ^8 |" b5 D5 J- G' A# d4 q! Q, ?6 s

基于单片机超声波液位控制器设计.zip

18.27 MB, 下载次数: 25, 下载积分: 一乐金币 -1

点评

又下载一次,打开跟你内容不一样?  详情 回复 发表于 2020-12-11 20:22
回复

使用道具 举报

发表于 2020-12-11 19:05 | 显示全部楼层
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

点评

是的、是物体都可以检测到!  详情 回复 发表于 2020-12-14 08:40
回复

使用道具 举报

发表于 2020-12-11 20:22 | 显示全部楼层
leishidianzi 发表于 2020-12-4 09:56
3 d, V  j& G( C9 i6 g/***************************************************************
1 ?2 A1 ?( m, Y( R        名称:基于51单片机的超声波水位 ...
3 M7 P" ^9 c& Y7 x5 x  P% U% Z
又下载一次,打开跟你内容不一样?$ m+ p- O* D7 u* ?% y& ]$ t! ^
QQ截图20201211202119.png
回复

使用道具 举报

 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05: X1 q7 M# `( h8 C1 f  C8 c6 q
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?
8 b" l; m9 X0 h; R
是的、是物体都可以检测到!
  w* }  z5 \( c4 s, o9 t( h# O
回复

使用道具 举报

发表于 2020-12-18 14:55 | 显示全部楼层
程序Keil、Protel99下载不了怎么办呢
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2026-4-17 19:24 , Processed in 0.040803 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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