一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 3343|回复: 7

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑
" F( f9 h2 e; T  j, \3 o4 M% Y5 g( g+ D* I8 E
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)
! o0 V7 |. }# e4 v
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

0 I4 w6 n5 Q6 `% q" r$ ?; B8 S
按键功能分别为:设置键 增加键 减小键 复位键
8 Q+ ~7 B7 U' F
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)

+ A0 w* I: S/ N$ r2 h7 {% W
发表于 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 编辑 $ ]' Q2 q- B: e2 B: a
tdc31224 发表于 2020-11-24 20:58# c. x1 t$ G% W+ R3 `* U
没程序?
; X: ~% z: T$ V' s% |( ^4 Q
: w2 Q9 C/ d) D
/***************************************************************
5 o9 m) Z5 z% X( r5 X        名称:基于51单片机的超声波水位监测报警系统
2 F5 P+ s0 O! o8 f        单片机型号:AT89C513 F: ^# X. i4 e+ g
        单片机设置:时钟12T,晶体12MHZ' Z" W( ?% O: w! t7 W! Z7 M3 Y
        注:修改增加水泵控制和排水控制,即双继电器
0 k! M! q2 \; V/ L***************************************************************/
- W; N6 v) D. F6 E9 F$ o4 T4 q; P
#include <reg51.h>; Z4 w$ L/ y3 U, O! x
#include <intrins.h>                // 包含循环移位:_cror_6 ]) b3 D) T$ d) u
#include "main.h"     
+ d" [; H4 d& k- H6 x//----------------------------------------------------------------------7 `+ b3 y1 d& m5 ?. U, U

3 L- u9 H3 N2 Q- t- W0 G6 H+ kuchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};" `* k6 F7 |6 c+ V$ y7 M9 A7 X
  k- m3 j" V  s, B. W
bool        g_flag = isNo;                //用于标记超时(65.536ms)           
2 X) U5 \* O& z* dbool        g_flag05s = isNo;        //用于标记0.52秒  
  f' g6 `: W, P+ J; ]uchar         ucCount = 0;                        //用于计数0.52秒     8 }4 r0 f# a% P
; Z/ ~6 S) r& T# O
uint        uiH =  86;                        //设定的最高报警水位 H
- J4 a9 P/ ^) {# U- ~7 v( wuint        uiL =  73;                        //设定的最低报警水位 L
# R: M& t* ^6 F+ t' `0 j& ]uint        uiD =156;                         //检测探头到水库底部的距离 D
8 A; i% f/ ^  F' m3 p8 \: c# `. E0 J
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志% j% k& ^' g$ N# k3 w4 @
bool        g_flagBeepTimer = isNo;        //定时提醒标志
8 }1 D9 C$ Z4 ^0 ^* S8 p# S               
; P. n8 j8 k# D4 }! o+ e, C$ q4 w+ d  Y7 n. r) i* p
//-----------------------------------------------------------------------
% y2 M" h3 u" @2 T// 延时10us( Q; R5 K, o& M: b
void delay10us(void)                //@12MHz& X! K, j3 X# J1 }' h2 e& ]
{
: t* G- p/ N" G1 J/ ]        unsigned char i;
) r2 O% i- _& N3 x: |) c$ C' @" M7 Y
5 _+ o* G+ p6 L# s        _nop_();
2 V% L6 z$ T  L4 q- @        i = 2;
: q, V2 p* T/ B3 ]6 u4 J+ E' G        while (--i);
. j; O# f9 ^6 i, h. B- h/ X; U( d2 l}
/ U2 ~. U4 B" ^. t3 W
8 C* o' e  c/ Q, d// 延时100us5 n. I5 m8 A0 {# P
void delay100us(void)                //@12MHz  u& I1 g5 p& u/ [6 i" o
{8 n3 t. G/ M- m7 }1 [5 \3 g% B8 \
        uchar i;
6 |6 R0 o0 l: A2 h5 |6 |
. N8 V% C# D% O; G' H( S        _nop_();
+ t% k/ ~8 ~* @, d, F; u5 ~& s+ W        i = 47;
& g- h. P6 m, f2 t3 V        while (--i);* Y4 P7 j% S1 D6 L' p
}
4 L! ~3 E+ ]1 R5 L; w) f: W
- L: h! d( @+ H( j. }// 延时125us9 U# [! s0 G+ z: M1 x
void delay125us(void)                //@12MHz
* u4 T, S# ]7 C{
0 j& w& {8 E5 R2 x, W        unsigned char i;* Z. P4 z: k8 @( ?( _
        i = 60;8 l' G3 }5 g- B" U' z8 g
        while (--i);( e. g- `! P+ D" I6 s! {; {
}
1 O1 d! o3 L; Q5 N6 m3 c5 _# Q
. n! z6 c2 K+ c* C// 延时5ms
+ y' G$ i* A" j. j9 Qvoid delay5ms(void)                //@12.000MHz8 f4 b: o: O0 h3 E. z
{1 |: |/ J# U" E& z2 h  F" {
        unsigned char i, j;4 T) C( i) ]% s& B4 P1 E: t
4 h) U! h# V0 H2 S+ k4 \% q
        i = 10;: z& u- g: R6 B* }+ @
        j = 183;2 O) D4 \& _/ g. Y  X( N* f* \
        do
- [. @+ s& w$ h) \* L: z3 _        {
# e# I$ W4 x5 ?& [$ w& V4 |5 O                while (--j);
# h& X( l- P0 M2 f2 B" F7 F, j        } while (--i);
3 T$ `) G+ V+ u5 k# S}
8 e  v" L( f9 F9 A6 e
/ m# f( O1 x  J/ z2 h// 延时500ms
/ E3 a; G4 s6 d4 b# g+ Bvoid delay500ms(void)                //@12MHz
/ G+ C+ B  C1 Z1 f{9 L- O2 ?8 A% U$ N1 u) ]9 z
        unsigned char i, j, k;
2 T1 q( W/ {5 ]; Z/ s3 G3 H
0 ]1 y. O6 U, E, B        _nop_();* S( q# n" q, l
        i = 4;1 [) p5 i9 Z, d9 @, N
        j = 205;) k8 Q: I0 v% _: ?1 Z$ s' F4 q
        k = 187;; E& _6 d$ Q: P* U
        do( j; {! m* m# y" K- Q
        {
6 e- d  L( ?1 `9 [                do6 S. m, v! Y8 b* c- h" k
                {
8 s1 L! [/ ~& z+ n$ c                        while (--k);) Q- H! S/ }2 F( M
                } while (--j);. X2 L- D5 W+ K
        } while (--i);
1 O9 a  ]) V- q3 w3 |4 c. }, _! J}
% v5 R9 a2 u: c7 p1 d3 u" f7 v4 }
' P+ K9 a, q& _; S9 R' Y//-----------------------------------------------------------------------
9 a) T( \. ?: I1 z+ @) M( `//初始化IO端口                        
. Q; {: P- T8 n' M2 ^1 ]0 v  O! j5 {void initIO(void)                                       
! m4 ]$ T' p2 y+ T! S/ ~- m  a! E) ^{# z+ m8 K5 q! x! y1 k5 w3 b- k
        P0 = 0xff;
& J( O+ t' Z; m7 s        P1 = 0xff;
% }1 P; e6 s1 K1 Y* m' M+ w- E        P2 = 0xff;
; e8 u% v! @  Y$ {' R        P3 = 0xff;/ S' c- ]; O5 p
}# }( I3 p6 D$ Q& z6 }: M

( ]$ B" F$ W8 O3 J0 F// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz8 n+ \0 p2 o8 a) H4 p
void initTimer0(void)                " R+ y4 t1 J0 L( R' l& \
{
4 K: J- N- _2 e5 Y( y3 V, I        TMOD &= 0xF0;                //设置定时器模式: t+ r2 f2 s% F9 Q
        TMOD |= 0x01;                //设置定时器模式
; C& m2 A8 r0 q' q        TL0 = 0;                                //定时器初值清零
2 K5 t8 c0 D0 W3 y3 {        TH0 = 0;                                //定时器初值清零" f" ^2 R; _# _
        //TR0 = 1;                           //开定时器0! p& b4 n/ a. W% i9 S( }
    ET0 = 1;                          //开定时器0中断
7 o  K6 Y: i9 H7 p1 G    EA = 1;                             //开总中断            
7 v# T; I/ E3 n, d* @) [: e% x        ) ?5 F) q: E9 w: z' l0 L
}
# N  V7 ~) h- r3 i/ x3 m/ e2 Y- [2 a7 Q( n- w: w
// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz% m+ b  U$ ^: _0 R. d
void initTimer1(void)                //50毫秒@12.000MHz
- B/ I# |$ _, h& K" V" w{        
8 s1 N$ K# _3 r: g2 A1 K' |, v4 n        TMOD &= 0x0F;                //设置定时器模式5 h. d# f8 t% y. N" n2 _- J3 [
        TMOD |= 0x10;                //设置定时器模式
0 d* C2 C+ y4 X0 y        TL1 = 0xB0;                //设置定时初值
6 ]2 I9 [; @8 H4 v8 J        TH1 = 0x3C;                //设置定时初值        6 F. ]! I$ w) Z. f/ `
        TR1 = 1;                //定时器1开始计时
4 X. l9 q; ~3 P        ET1 = 1;          //开定时器0中断
6 @1 \2 L$ i- B. B+ Q" q" ?}7 n+ o) O1 @/ ^6 ]/ T$ l) C
+ N. k, X3 I* A: b
//-----------------------------------------------------------------------
1 m$ [; S9 B" y& k+ F& d; g//定时器0中断
( ]5 `0 g1 t% N( l# [6 ovoid zd0(void) interrupt 1                  0 x) X" S* a; }. `( w& r
{
9 ~' c6 V# q" o        
6 w9 E7 ?8 s' P7 X' z        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
/ C5 v8 s) C" N, K& p        if(++ucCount >= 8)- G% W3 s( Y( g' K9 `
        {0 C, [4 s) s# x
                ucCount = 0;0 g+ F$ e0 I6 `- B# \4 i
                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时% c% z& K/ [" w3 ?* H
        }7 C- W! R1 Q9 m+ K" A, Q, D
        TL0 = 0;                //设置定时初值
! h& c7 Y6 d7 C" X        TH0 = 0;                //设置定时初值
2 f5 l- b5 d& E5 [+ R4 B        
0 ^$ T9 ^0 a5 t, ], W}5 b; r0 o/ h( h; n2 r( c

2 }5 h5 h3 b+ j. U
( c# g. M3 e) G; L9 Y2 j//定时器1中断 定时50ms
! O# J3 Y6 T. G2 mvoid tm1_isr() interrupt 3 using 1
- Q2 D. }& F  ^% }" E{
( E- d8 n/ u# d+ G8 V        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S8 r8 k- t9 a) O3 w9 ^
        static uchar uiCount = 1200;                                //                        = 1分钟               
# B- j/ W) l' A- p& g        static uint uiCount_BeepTimer = DATA_BeepTimer;# O+ u, l! G9 C4 o8 m  e/ r  o. r
* N9 _/ c* _: w6 M1 F6 O* P
        TL1 = 0xB0;                //设置定时初值9 G4 l$ C9 ?+ i
        TH1 = 0x3C;                //设置定时初值2 Z8 r4 H  w2 s3 F- F
& j3 p  U  X9 v7 J% o( ]+ }( [
        if (g_flagSwitch == isNo)! a8 Z) q: X4 D5 u1 X
        {2 l9 z! R* {. D* h% C
                if (count-- == 0)               //50ms * 200 -> 10s
! N" T& y- Q0 v0 e                {% Z& R! P; R# r, ~& k
                        count = DATA_switchTime;$ ]0 i2 D* V' k
                        g_flagSwitch = isYes;/ w! s3 \+ W) t" p
                        // TR1 = 0;2 m7 m4 H1 w$ X( E, j' l3 P
                }
: Y1 u' i* |' v3 t9 U' C9 R        }        
) \! J/ k3 p- K; j$ C- J        . G$ ^$ V6 y6 d3 I( K9 |( ~
        if(g_flagBeepTimer == isNo); t) k7 m. P# w1 c6 R$ M8 A
        {* a! T+ i; }4 {$ R$ Z0 @" D' Y7 @
                if (uiCount-- == 0)               //= 1分钟
4 H5 O9 O& p1 F7 e2 D                {4 u* I5 c% n$ X" [% L
                        uiCount = 1200;
1 o3 A1 Y, x- {! {" y6 }                        if(uiCount_BeepTimer-- == 0)8 X0 L  G7 A' O* f
                        {
. H0 X# v1 {, t5 ?+ q3 P/ o$ [                                uiCount_BeepTimer = DATA_BeepTimer; ( U/ X* Q1 \4 R) x0 s2 q
                                g_flagBeepTimer = isYes;
, ?& T. g& v( S9 w* l4 T                                // TR1 = 0;
! O# s, b- l# r                        }                        + w! v) T; t' V' w! t1 e: ]* E, Z
                        / _* ?( q3 {2 Z( M5 Y' }  V
                }. s; V/ ?2 m8 a/ h; w

: u9 }' t6 k: e        }
- `( C5 S- R" {" a  p1 K}
3 I; ?1 f, b/ o9 l. M6 y, w) @& x+ `# `# F
//-----------------------------------------------
3 L2 b) P  N" r- Q& j4 X: Y* P& _7 S4 t) \% G3 I  e
: V" L2 D& K1 U1 t

  u0 m$ N3 K, w: C9 n' P- V. n% A) _0 t( p* `. N% D
1 ~$ g; |! [  y: D4 i
//外部中断1
$ l  m' E& Z1 C; h& _- d$ yvoid exint1() interrupt 2
7 o# N: K7 H, j# Z! I3 ?{
" m9 ?& x0 B: i, i& z    EX1 = 0;                         //关闭当前中断
1 G) I: l9 |; _* y: C5 ~        TR0 = 0;                           //关闭时器0( d' e6 \9 X/ f8 ?4 h$ M
        # B9 N7 \8 G- U( F" q# B
}
# b8 M- H3 y  ]& K& t//-----------------------------------------------------------------------" \3 ]) ?: W. F8 i
1 s8 U" ?: |+ |
//读LCD忙状态并等待忙状态结束. k, \' p' J+ v" ?  b  R
void LCD_waitNotBusy(void): ?9 u7 L5 [7 D! R1 [/ P
{$ \! E9 N& n+ T
        IO_LCD_Data = 0xFF; 8 L1 r2 R) B6 z  O* v
        io_LCD_RS = 0;( J9 c' h0 n! |0 x' O1 o9 m
        io_LCD_RW = 1;
2 Z7 f/ m% J5 ^        io_LCD_E = 0;) [! K( N- T& h& u& u, y
        _nop_();/ A3 E2 b3 }* J2 A( J
        _nop_();' s/ h8 A& y$ H- u. V
        io_LCD_E = 1;. \5 v2 ?5 g( `# d* D) x) j% C  N; |
        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙" k# x/ Y" I2 o
}0 A* O7 B* B" E' D7 G& C* k

/ M8 A( K. h* l& `//给LCD写指令
$ U! h, X7 }# x6 K$ r4 jvoid LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
+ C6 I/ X! N1 a: J2 g& n{% v' z/ \- R8 A1 M" h, o$ f
        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙: O, a2 m0 ]7 d
        IO_LCD_Data = command;, z4 l5 O- N. }. u" U7 H. l7 l
        io_LCD_RS = 0;4 [# i6 d! Z+ k
        io_LCD_RW = 0;        ! \2 ^/ _% w- m& ~0 O% `
        io_LCD_E = 0;
' }( D$ I- y" W        _nop_();
, ?" b9 U# r* v        _nop_();9 C3 }, ~; K; U# r  _6 N
        io_LCD_E = 1;        ! q# L; o/ r7 i" J8 K
}4 F! s6 j, f# |8 Y1 h
- ^. Z, ]- H( a8 }& i% K
//给LCD写数据* _" o6 B& `% |; R; H- J5 L( d
void LCDWriteData(uchar dat) ; {& [6 B- S- ?
{
' P6 |/ p) T$ S; _        LCD_waitNotBusy(); //等到不忙
& A7 M5 H" z, X1 }        IO_LCD_Data = dat;0 C- d2 `: b# }7 c' G% [7 M
        io_LCD_RS = 1;
* o% S3 a- ~' y- S) l  {; u        io_LCD_RW = 0;: u/ K) p, j7 x9 g
        io_LCD_E = 0; . V$ b0 h1 D! }! B/ G7 J1 e
        _nop_();4 O6 S( V+ u3 I; g
        _nop_();: |$ E2 H4 Q$ G- ]6 a
        io_LCD_E = 1;
; A1 Z* ?* N) R}6 T' Q9 b5 @! @+ L. K' ^( i0 b0 _

1 g/ S/ l  a7 V& w( K( `  @
8 P$ ~( W( U$ q/ k0 m. j( |
/ j% y5 N+ ^* z/ A
0 j1 M, f+ C+ V- _  P! l, G// 初始化LCD1602液晶显示屏: _2 F) g/ m" y* m9 A1 g
void initLCD1602(void)
: N; x4 w# i5 ^1 h7 b7 [{
8 q: Z* i- E8 X3 b, Y        uchar        i;        " X! S8 F- y/ R7 A( d
        IO_LCD_Data = 0;                                                                // 数据端口清零7 e- N6 [5 B3 J7 C& g- N
        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
+ q  e5 D+ z. o, d1 ]        {
; y7 D9 {8 Y- K3 z+ |                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号/ z7 n$ j! l0 C0 ?, O$ w- ?
                delay5ms();9 H& k( `0 w6 E6 ^2 t( ~
        }
0 N7 I; s) T) O- _6 r: _        ; f5 J5 J8 e8 U' F3 p6 Q, Y7 x
        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号+ L: l, v7 I6 h: F1 \; L' [$ O) W
        LCDWriteCommand(0x08,isReadBusy); // 关闭显示4 f; Q$ P4 S& `0 s
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
6 x1 O/ y& F& q+ U. t; }        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
: i7 l0 J3 n3 b, }. i: P" y, x# V        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置7 {! d8 y  t9 }( y! J& x+ }! D
}1 \+ m; H8 b" D

  y: S: O5 R: `' s- C! a& h" Z  G
  N$ e$ R! D' A9 Q0 x
! W, c5 P5 _. G8 g# [& `5 A//按指定位置显示一个字符; `6 c. g: ~7 l' p
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)- Z% T. c2 y$ T+ n0 g0 K
{! j7 E6 @4 U( v& p' g: O6 p2 q1 E# Y

% c- l+ \. Z5 d) x2 z, c        line &= DATA_LineMax;( Y; }& ?, ~; Y, R3 e& U: N2 j
        position &= DATA_PositionMax;# a0 Q! g0 v' Z9 X: Q# v
        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
: d! q0 _: k6 c( N3 t* R        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;3 d, s* ]9 t) X; t5 D
        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
: u5 m) a4 K* ~$ M+ h        LCDWriteData(ucData);                                                                  //写入字符的数据        
: f# V* e/ o7 H! s7 a3 A}
6 f/ u2 S, ]* C. l, }: w# `/ T5 i' n# `' `2 j; C: k; U/ t
//按指定位置显示一串字符/ M3 U3 G0 Y6 s% q. _' u/ t7 x. A+ F5 ~
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)$ N: t/ @( `( ~4 {+ k
{8 X8 p# a  d4 [& }1 Z
        uchar i;
. F4 V) }$ S3 u7 v" A6 h        for(i = 0; i < count; i++)                                                        //连续显示单个字符
) T, s6 x, `7 d6 ^- M8 w        {
; o5 ?& b5 u' j7 j9 z% q                putOneCharToLCD1602(line, position + i, ucData);        
; \1 }  S& I% n: _" R  o( }1 A        }8 V* K' x7 X0 L8 I- j* L
}' [7 k7 }' q! ]" t$ y4 ?
* {% ^" k7 I$ O" J0 T
- Z, r# I( G: U* C# j4 @
//按指定位置连续显示三个字符(三位数字)
7 R: {# ]+ H6 P$ F' H6 kvoid        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)2 Z$ I% m" V8 P3 k+ P
{
5 N" x# `3 Q. n9 |) D0 p        uiNumber %= 1000;
/ j* e7 V+ J  I2 i        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
" R" O. K: o/ s& d$ K3 P* ^        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);3 j4 o8 h3 g/ x% _& f) j0 P1 o
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
3 S. W- b- h% Q. k% J% q! K& a# r        
& @8 Z. g: E% [$ w' H}
" \: t% G- o& S, q! r        , O' v% C- q3 v# G4 t
2 R. m" Z, q) u5 g! F, i6 M1 O# C

3 f9 |: e* W! C; S0 \5 w5 j! T// 按键检测子程序,有键按下返回键端口数据,无键返回0& J7 E4 t2 V- q4 ]
uchar GetKey(void)5 q- y7 \1 U! X( p. ^* Y; w
{        / ]" B& F0 I! w! D  E0 s( v. y" L" K
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        " _5 x6 T: \( A- M3 M( ?( i
        . q6 J& p# q/ w+ O' G
        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空7 R  e, B$ t3 Z( K' N0 F$ w8 R
        {
3 b; ^+ p9 Z7 {; j" J2 \" z, n; B! K2 U' k                uchar CountTemp = 0;! ~; A1 \  N  t9 I; y
                do% u, `" ]: h' W4 T1 G% U
                {/ t$ q" p4 P0 q8 ^+ Y) D3 B0 H
                        delay125us();
$ N5 g$ _6 |* r                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
0 N( U7 o) g5 I. S' `                        
* G' p+ k7 b& N" F                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动   z" U% J7 U/ J+ `8 ?
               
/ ]4 o3 j8 F3 O9 \$ V' u( C5 A. K5 u2 }                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放                : a! \* I3 E; r
                2 n9 S6 u; Q8 |1 h
                return KeyTemp;        // 有键按下返回键端口数据
9 I# \* \, Q% o' w+ W        }/ l/ N' i# K3 l+ J, V9 P0 S
        
+ q" M6 c* m4 P, \        return 0;        // 无有效键返回0+ N+ [( L/ j( y0 o5 o0 W( z# o
}
+ M4 K. `+ g6 }; }. e  ~7 U* C7 f, E4 v  l7 [- I- d

0 D9 |# J; V; f( L7 G6 n/ C) l5 v6 j0 G0 H# f' k0 {: U; T
//加一
6 l. L6 q% _2 z) r5 ^: L; e4 tuchar  INC_Number(uchar Number, uchar Min, uchar Max)
) x$ d6 E) N1 n* Q( H{/ |1 r, p+ T4 H
        if(Number >= Max) return Min; else return (++ Number);
1 j- ^8 \" S2 [2 \& f               
/ _* K6 g1 s$ X6 n7 _3 g- m# `, x2 ~}* C( i( @6 T. o( R) r

  d  m; l. o0 |& N7 \+ O2 [//减一
. u% b3 |7 ]. |/ s' Euchar  DEC_Number(uchar Number, uchar Min, uchar Max)* Q2 V- M$ K; D; F/ @
{
, ]6 ]3 @/ c0 v* w$ J        if(Number <= Min) return Max; else return (-- Number);( L$ O; N' t% Y% i2 e1 ?: E
                * c5 f, p. F) |3 ^$ W
}) s1 i# y! W2 r

  {$ N; ]; W. ~, M$ G// 检测到有按键后 这里执行按键任务                        
8 a6 Z! D9 ?5 S& w. j; Y% tvoid execute_key_task(uchar ucKeyValue)        
3 _& Q4 a$ d2 ?4 K, V5 T{
; s7 z8 L# k! F. M. t; V3 E9 _        uchar state = 0;                                                //定义调整数据的状态变量
5 g. U. k0 a7 `+ d        uchar keyValue = 0;                                        //定义键值的临时变量
6 f0 @* b- P* d" b. X6 y        
. r5 z' j% U' l8 b$ q! r        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出5 ]! o4 a4 E: s$ a& x$ b
        
5 `# ]+ |( Y9 _3 x. ?        //是设置键继续-----------------------------------------------------
$ \# A: ?% x/ `" a, e3 v- A  E        
# l- m* I3 _- s0 b5 r        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT               
, {6 U2 ^0 U. i8 s: i: m        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        - R0 h; y- c* t( _
        1 S+ z8 a4 C. L' _
        while(1)
+ U) i8 u+ L7 P  @) M        {" t6 e; w$ x  \. X; l+ ?
                keyValue = GetKey();        % v. m3 t( K- c' Y4 V; B
                if(keyValue == 0) continue;2 v  I5 F* T8 |1 B" [7 S6 J
                / A! @: |& q; w5 z
                switch(keyValue)
/ K& H5 D# F! O% `                {6 \0 o" d+ j7 i
                        case DATA_KEY_Set:
- {: m9 e! Q2 H+ P- B- x# E                        {9 e* g, w% N( i1 u1 ^) g8 s; Q
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出0 c, P  x1 e4 a& V6 E
                                switch(state)
6 S" q" Q' W- `2 K                                {
4 E/ \! `* x/ A8 t                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面
) Q* F& u* ^7 v                                        {
& Z5 M4 Y7 G" u& k  P& N+ ^                                                state = 1;                                                
! b- G( I+ |+ q                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                7 j+ o- H4 G  [1 e, [4 q  J
                                        }9 X+ H; Y" ?1 C
                                        break;/ ~% D  b5 m0 W  G% e
                                        case 1:" T  S9 |& f$ a5 _
                                        {
( o1 O, r+ @% \5 V1 f% B* O                                                uchar tempMax = uiD - DATA_uiD_Min;9 ]' h- l! D& |- N: z* n" f
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
6 P% z4 z1 E* m5 o4 q1 f8 P                                                if(uiH > tempMax)
: a" _' a0 Z2 k8 e, S- V* d! I                                                {6 {4 T4 t  E- M, n' c" I4 P% h- K
                                                        uiH = tempMax;3 o8 Q5 H5 K( B0 e
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);; G: c+ i% L% U1 F
                                                }, E" i) @$ J' H& \4 G* }4 X
                                                else if(uiH < 2 + 2); F1 H' V9 w$ l/ \3 h; X( P
                                                {
3 \. o# O1 j2 v( P/ r3 a                                                        uiH = 2 + 2;        
, w3 e# q5 c5 Q/ f0 x                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);3 {& j6 J" b3 w: w0 P) X  O
                                                }                                                        
* B% g: S, f! m6 ?6 F# G                                                state = 2;' h9 K6 B# q/ |5 L( _# |( {; B! S
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);* }- e* C; Z( [/ r
                                        }
& s1 F) u0 j& [# x2 X$ E, C9 K                                        break;6 {$ z/ ?- J6 d1 p* V. N! A
                                        case 2:; w3 c. k0 G1 [- K) b/ v
                                        {% T& _/ S0 v* T& V. s
                                                if(uiL > uiH - 2) 4 b( H  o, c5 r, Q% C8 i
                                                {
, G! F6 I( n- z" J" V                                                        uiL = uiH - 2;6 e, Y$ e3 z) m6 I+ x
                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);6 W; q- |7 H, H" Y
                                                }
% o) Y% Q5 I) o- v4 f' m5 s& y                                                return;        
4 s9 t- Z7 C/ E0 x: ]6 X                                                
7 l" S  ~2 m0 P7 T+ X7 y                                        }* q3 |1 y* u2 m9 ?: }) s6 U6 o! ?3 d
                                        break;
8 r8 t$ @3 W2 D& ^* |: V' s                                }3 B  p8 F& U6 c$ I: {. o" ^, z
                                ( V- w  R8 x, @- w$ |
                        }0 k8 n( v% y$ x& }( \! \( F
                        break;' z4 |; `5 \4 s4 F3 P5 v. I+ o4 K6 S
                        // 如果按的是增加键,改变相应数据并显示, S9 d  O! k$ C* M: `
                        case DATA_KEY_INC:
, d8 E. L: C4 Q. S. j- H& D                        {
4 @& L2 t6 K- k1 B4 E/ R& ]' A                                switch(state)! N* v: u4 f1 C1 K3 x
                                {
( ~4 m+ z5 B1 X8 {* z2 i. p1 k                                        case 0:
, D- R+ ^2 }3 f' B: A7 Y. H                                        {# h+ [3 b0 u& C2 h% Z* e
                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);
7 h4 J0 ]2 a6 c: g) T  C                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        3 ^: t+ y5 g. @8 p
                                        }" X8 Z+ G8 N# s
                                        break;/ j1 I) N" h% O8 H4 B% C8 g- x
                                        case 1:, t, W8 i( Z7 H8 h9 h3 j; g
                                        {
) J3 J+ m& y9 T3 X9 d7 E                                                uchar tempMax = uiD - DATA_uiD_Min;
/ s) f3 U1 C" G  k4 @                                                if(tempMax < 2 + 2) tempMax = 2 + 2;' b$ R" w7 U8 O; N5 ^
                                                uiH = INC_Number(uiH, 2, tempMax);                                                
+ z  U; y- ]) P3 v& M  p                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
6 X: a- i5 S$ D                                        }
) n7 o7 i. q' M2 Z0 c                                        break;
1 `1 S5 X, y) M4 n9 p, N  F3 _                                        case 2:, F' \0 r( o* F7 _9 Y
                                        {7 h- _7 A* g" z+ Y$ \
                                                uiL = INC_Number(uiL, 0, uiH - 2);        
0 w4 V, f. {. Y2 M, E7 m4 F                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
. e( L1 S9 d  J' i% i                                        }
4 b, o+ ~" x  E                                        break;! p- i1 |' G/ X4 }
                                }  f# ~+ J% k* @
                                3 i& L  e% W  Z- Q
                        }9 G7 [' x( p9 h3 [
                        break;& |3 b. Q1 d5 l5 R1 f/ N# j
                        // 如果按的是减少键,改变相应数据并显示* q( U; A  h9 ^) A
                        case DATA_KEY_DEC:2 T! I( z3 C6 z$ q: x
                        {
6 k, a  t9 Y& s) E: G; _                                switch(state)
: E8 o# k# i6 p% O7 p5 W                                {
1 [& d5 B9 N$ ]: }# ?4 p7 y  o- J9 ^  K                                        case 0:# x' c8 |3 A  o5 {4 N( r
                                        {0 O* q6 R  S. ^) T# S
                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        ) G5 S- \$ P, Y, c/ M: t: p
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);8 W+ z$ O1 w& m
                                        }. r6 ^' v% X7 ]% S2 s# O
                                        break;
& s! `8 o" j4 X+ m4 }& M1 R: }                                        case 1:
8 ^% u, g0 R, U                                        {! ]& M+ H8 @1 `* V6 b: J1 ?5 l
                                                uchar tempMax = uiD - DATA_uiD_Min;' N% i3 m# v4 y+ y; h: R# \3 D
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
8 I6 U: j1 r' l6 J: |                                                uiH = DEC_Number(uiH, 2, tempMax);                                                
# k1 H. b9 M9 V$ @: d7 x- ?1 M8 I                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
. Z3 ]1 T4 ]$ j8 E! V' P2 b, f* C; S8 t  I  m+ @1 Z
                                        }9 r5 L2 X, ?  Q* J, a% z& K
                                        break;
9 _3 O" T% k& i1 j, {# m                                        case 2:( A4 y- H+ U' ]* G4 G' F) _+ j+ S
                                        {
. w9 }. X$ b1 a% v                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
9 z, o5 Q9 C$ o$ s                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        , S  f3 J/ F; U6 s8 r$ i; p6 E9 G
, z, m9 k; _/ `
                                        }
- ], p! l7 O5 i0 [# f                                        break;- t5 J+ B  p, s! q) @/ p( L
                                }
- D1 ^( K7 ~- j& x3 o  `                                
, d* m8 u% e8 ?7 I$ y2 [                        }! F: A( ^, \5 E6 R) b
                        break;, O; ?. e0 _$ q$ s6 e
                        
# B" g3 H" E' E1 o/ d$ k                }
' \* a1 k4 J# q* _) o$ g" G                & V& C2 h. y  |: R' q
        }
& r3 f% V5 N7 u  Z0 s! Z- t7 p, x          }$ x8 y3 @" |/ X: q
}
8 h) M$ _! _3 U5 K
, b3 E( d- L* _! a) f! j$ E
5 L5 q5 n6 e4 K. l% Q
" ?' k4 v+ U" s// 蜂鸣器        : V& U9 y% d+ B4 D' E. M
void        buzzerCall(void)
$ a. L# k3 O1 t* Z  A7 j{' I" |! ]  l6 ^# M7 |
        uchar        i;& ^- `; K- L# a; V. u; x% c# Q0 a
        
1 c/ r- `8 J. u% b, T( Z                for(i = 0; i < 90; i++)
' l# k" ]$ m' U- B: z1 d# G: u                {
7 z& u3 p1 s+ W                        io_Buzzer = 0;
. W5 i) G* Z8 y                        delay100us();& j7 \/ N, T1 H0 C% y$ b
                        io_Buzzer = 1;- ^$ |0 f. \+ D0 \8 K3 W
                        delay100us();2 s3 r) Z) g7 ~4 @& V
                        delay100us();               
, o# g# G# D8 c4 q0 }                }; K" ?/ o: v( h$ n
                delay100us();        ( U& v7 i  X; B
                delay100us();        * v6 X7 W  O( L+ V+ s0 p9 `1 ~, R
}
6 G( P  v; E7 e/ f$ [) Z
6 o4 l1 m$ e- G9 _//计算水位& i$ S, z5 E% |6 S$ G
bool CalculatedWaterLevel(void)
4 V3 e. ^5 v, D1 B- F{8 B# }/ ~9 h4 u  o3 ?
        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置( Q% g. O5 q5 [/ L+ M* C" T
        uint          uiTime;                                                //声波传播时间
8 E8 s* I- L- D7 R        ulong         ulDis;                                                //实时测量到距离        7 l" U1 f& T2 i( j+ i
        ( y* }, y4 U" C9 }: Y5 o
        uiTime = TH0 << 8 | TL0;        
$ l" l& s+ K: s, B9 O- z9 Q$ z        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
0 T# D1 ]" A1 L8 R        , W2 E, {5 _6 Q4 J( S$ H9 V6 T1 Q
        TH0 = 0;
) N2 O6 c6 U% U. f        TL0 = 0;        
8 s, o2 ]0 b4 y  i, k9 j5 n3 Y        
! ^; e5 c% F: z% V3 C1 n0 e        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;2 F' g  g/ D1 C" G
        {         - X8 N* d+ ^' I% T8 O: c( t
                g_flag = isNo;               
) e% ?& I7 x& b( x7 a5 T                TR0 = 0;! u1 K& V! a$ L  X% {7 c6 Q
                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
1 [! I; Z: d  {8 C& |$ w               
; g2 I5 y2 d5 F" w                //阀门动作:                8 D7 o5 V. ~" O6 n
                // if(g_flagSwitch == isYes)0 `) K7 n/ {1 V8 T
                // {                9 p& l$ H( L7 Y* i8 B0 n
                        // io_Control_Inlet = isio_Control_Inlet_OFF;                6 b8 y: x) Z3 b# v. ~# }: O0 Q
                        // io_Control_Outlet = isio_Control_Outlet_ON;: C1 a2 P  |) |3 N! ?9 U6 k3 g
                        // g_flagSwitch = isNo;
5 R* J3 G- ^2 ~! ^& i$ i: `                // }                4 v$ M" W8 `" H9 G+ \& h
               
6 Q% N- w% p  N8 Z5 l7 p                //指示灯:
3 ]+ F% q' j# o7 A6 i9 q                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮& O( J! L. d6 s" A
                ioLed_Green = ! ioLed_Green;0 d. [! r8 n( q; c, A$ |0 w
                ioLed_Yellow = ! ioLed_Yellow;
: f" V3 J+ d9 W+ n( m% @                ) |- X( }+ k9 B/ r8 J
                // 蜂鸣器叫:        0 G0 w/ v1 C6 f9 N0 A8 a( A' L
                if(buzzerCallFlag == isCall)2 a' w. o# s7 Y
                {: W4 |( F# l% ~. |
                        buzzerCall();                                        // 蜂鸣器叫        
4 W8 n  x0 l6 t, d; V                }8 a; m0 s% b$ z4 p$ U: H. d- {) p/ [
                ' M7 G5 M: h4 a' I4 g/ u
                return isNo;                                                                        // 返回错误信息+ O( Z. b, q7 K9 v" X" H
        }2 \4 N, I" r* J1 {! e. v
        else
5 A/ C/ e- T2 k4 Y8 j* z        {
# t: J  `7 H: b8 l                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离3 {( [! n- r6 o+ G% E
                0 k3 a) y9 _7 ?% }& B
                if(ulDis > uiH)                                                // 如果水位超高
$ O7 i' d; Z/ Q. _" R$ w, W                {
+ V5 a  o' G7 ~, |, B' B" D                        
% g4 @7 E) X2 m; E1 H4 k3 t, h                        //阀门动作:
- [6 c% V# j9 u7 D                        io_Control_Inlet = isio_Control_Inlet_OFF;
' _$ h. v0 k# [, N% L0 p                        io_Control_Outlet = isio_Control_Outlet_ON;        
0 l0 y# u8 k6 G6 R/ I- D. b                        g_flagSwitch = isNo;, G1 R8 E4 v9 P+ f3 X" l5 R; y
                        ; \# U: s+ v1 R; n: ?
                        //指示灯:
) U- n/ @9 y8 b$ _! \; Q# `; d                        ioLed_Red = ! ioLed_Red;                        // 红灯闪: R+ `) i; t3 d9 c; ?: ]2 n
                        ioLed_Green = isLedOFF;               
2 s4 @: L( d* E7 d. l/ s7 u                        ioLed_Yellow = isLedOFF;                                
  ]/ z3 A4 Y+ O% r, I5 m& P' J                        // 蜂鸣器叫:( \, j3 s$ F; p$ V* ?
                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
& T" r3 c1 `' g  h8 t- ^+ {                        {
7 K0 U6 {* [! E7 n2 G% t, o' ]+ }                                buzzerCall();                                        // 蜂鸣器叫# H9 G! s3 p4 A7 K
                        }! b: ?2 [' \% k8 R- l! R- m) j$ @. s
                        * A0 ^$ X3 ~  ~7 E2 i" z* P; ]
                }' w/ W# W& u% h. T. b8 y
                else if(ulDis < uiL)                                        // 如果水位超低" M  V- A& \5 f) L3 W# y
                {0 ?" ]8 Y2 M. v( [
                        //阀门动作:        
$ k6 {9 q  y# n  h                        if(g_flagSwitch == isYes)
$ z' L7 u* F! X& v* B                        {               
$ ?. l5 K3 ?/ ?4 o6 d. {                                io_Control_Outlet = isio_Control_Outlet_OFF;        ; s6 E- a8 N- E/ B( b
                                io_Control_Inlet = isio_Control_Inlet_ON;        
9 y: h6 o1 a! X8 }                                g_flagSwitch = isNo;9 }" j/ `" T8 y$ A* K& z' D
                        }        . @( J! S+ q0 K
                        
+ y, p& o1 N; [5 t4 |                        //指示灯:
8 o7 r- |4 C/ d$ h                        ioLed_Red = isLedOFF;) r; b4 v% Z7 A9 Q# ~
                        ioLed_Green = isLedOFF;
& Y4 y# `2 L3 y. h                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪
: j. f" `, W) B* w1 X1 N, P                        // 蜂鸣器叫:                                                + G' d' q; n- O/ f$ e: p$ d
                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警
$ z" {9 E0 w5 A                        {
5 J, B) ~9 Y' @                                buzzerCall();                                        // 蜂鸣器叫
4 g2 t4 }) a9 J) i                        }
8 h: o7 H& k% k$ z  e' S5 U                        
3 |9 p8 Y; O( L0 e5 s' {% X5 n                        
! I9 C7 O! U' f9 s; H# ~                }% ^5 g9 q) y* j
                else                                                                // 水位在正常范围 ( h. ]) H2 w# W9 t6 a
                {        
, ]* L; V+ k* b- M- L. P- V                        ioLed_Red = isLedOFF;! s% b9 v: t+ b0 g' u2 h. |1 H
                        ioLed_Green = ! ioLed_Green;+ T( _! t( b& T7 v6 X2 L
                        ioLed_Yellow = isLedOFF;        . _. y/ }! F, u! f, o* Y
                        / m4 g+ s5 Y( t) Y- e! Z
                }
9 ~* G/ \8 A% e  v/ n; `                putThreeCharToLCD1602(lineTow, i, ulDis);
, R3 [2 w) S9 W) S# F                return isYes;        0 O- k- j( h, D, q1 R& W! {. T- y
               
; {' a7 C8 e' z' M; T        }+ L; t) H2 R. L2 t) h5 F
        return isYes;
" Y$ [. J3 j% R: l}
/ @: e& j% r: R3 f& X/ b- d# t! p; f: w" j
/*********************************************************/- S7 V: a" w3 R; _3 `5 p* d6 z
void main(void)0 ~4 i# E, p4 Z0 p8 W
{1 ~/ c. J( M* J# i
        initIO();                        //初始化IO端口        
0 j' A2 _* I1 j5 X* B# T        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        , `- `1 h6 _- h. K" d
        initLCD1602();         //LCD初始化        6 g; |' n) J# a5 k  W: ^8 A
        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
  T7 b; {6 w7 f/ K3 W        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值2 l9 `" \6 N3 c3 p- e
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H
. ?4 u6 Z$ n6 k' j" ]        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值
, r2 \" Y: t" @, H        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L" v0 e2 k# A6 h7 U1 {
        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值- E# h1 J9 d, h7 t9 k- L# n
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C
5 O& A1 a$ L. G# D) X2 Q; Y        
+ u) ]9 m5 x7 Z, f4 Y0 N; n, m        initTimer0();                //初始化定时器0
$ e. S% \; N1 Z( b, t- |        initTimer1();5 m" H2 O# u' g
        
3 D7 A- p( S* S        //阀门动作:初始先排水& V6 Y: s) N7 ~7 h4 _5 r5 b
        io_Control_Inlet = isio_Control_Inlet_OFF;        5 P2 K+ P2 y1 O/ ?2 x9 p) e, u
        io_Control_Outlet = isio_Control_Outlet_ON;
5 i5 e- m0 Z+ a: |6 ]; ?: g  U        g_flagSwitch = isNo;          r5 C7 h  D" ]8 p; E. }
        
) K- }  d& f1 C% S+ H2 N8 ?. K+ n: z        while(1)* F* I8 f& D& c9 J$ N5 [
        {
/ c/ |: K2 C) P: V                io_US_TX = 1;                                //启动超声波模块信号
( e  N; J* H, a9 F$ x                delay10us();
7 |% l( L' e4 U4 V7 \+ e6 H                io_US_TX = 0;5 u* m6 H# _* O9 L) d
               
9 i: b" ?: S9 _1 `: _$ B                while(io_US_RX == 0);                        //等待计时开始
* V# o' Z7 l" |/ G+ I                TR0 = 1;                                                    //开启定时器0,计时开始        
, z7 B. N0 F+ _! ?% e                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)2 }8 c, ~3 O2 H) B* T
                EX1 = 1;                        //使能外中断INT1                ' o, I9 L# M% ]
               
2 M6 y2 q# F" k" H. P& ^) M                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        
; e) K) [0 E/ t' j$ E                {
- p1 X, t1 F6 ^  ?. Q                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
+ |' ^: P1 L; A" v8 S                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
% V2 c" g8 ]2 v" d                }
( `* z9 C; C7 E/ v2 n2 ?9 t: @                9 q+ {1 O) P: K  I8 L
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环               
. A; W1 ?. e: n/ h$ k/ [9 K               
# {) a, b$ o: L0 l                TR0 = 0;                //暂时关闭定时器0
. {  n* I+ q0 s$ Q  q; [" p                //清零定时器和计数变量以及标志' y- t$ ]& E$ l% Q; [" U, ~
                TL0 = 0;                : r" v+ W3 `7 S, X
                TH0 = 0;                4 K' ~/ o- k" F8 B' @3 k, W/ P
                g_flag = isNo;; L4 F) z2 D+ [% @( V) k3 M4 Y
                ucCount = 0;  D  Z1 N5 H- i" \/ Z2 ~/ I; t
                g_flag05s = isNo;
  E, f% j8 E5 x' V; z               
' p* [3 }6 g) `: }9 h/ C                TR0 = 1;                //打开定时器0                                        6 k) R4 Y, O! A2 S+ z2 k/ x# e/ ~% C
                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果0 H, t% F8 R+ {! b/ n
                {                        
7 V3 P: j) O8 }1 r  ]8 y3 z5 b  A& V                        uchar ucKeyValue = GetKey();
% m) H1 ~9 M) u: I                        if(ucKeyValue) 3 o2 l5 ]& Y9 r! o& A
                        {& _" L2 ~& G: J* u* z2 z
                                if(ucKeyValue == DATA_KEY_DEC)
4 G( c) M/ [: N, D5 n5 M4 r) P                                {. n4 M" s; P' q( U; V$ q# _
                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志! i, P8 K: z2 z
                                }
! ~" K# }8 U+ K" o. o' x% F+ F
$ }* l9 L2 ~* r/ t! c2 A                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
5 w9 z+ [; B8 x8 W                        }                                
# E2 P* i/ |0 ?! m& L- i* p0 h
6 {8 ], i; O6 y' D1 V( ^6 _                }        ' _/ ?+ N! A0 G7 ?0 x- [
                TR0 = 0;                //暂时关闭定时器07 H4 g* Q; O/ W& @7 ^5 n3 s$ N
                //清零定时器和复位标志
% [9 f' J4 _4 H4 [- C2 d6 Q# {                TL0 = 0;        
( p5 U+ ^& q& t, E3 j9 C$ I                TH0 = 0;        4 v' N6 ^" U1 S* R  b: D
                g_flag = isNo;               
2 H# W5 r6 n- L                ) q, b0 @+ R. M- ~8 z
                //-----------------------------------
$ I, t8 t! v5 ]/ x                //水箱清洗提示:
6 @* `) M5 d( n, f2 O: \                , b5 S* i/ J  T! e% u& w
                if(g_flagBeepTimer == isYes)
! c6 Q3 i5 t+ ?8 s3 `                {
* z# c: V" H% B8 j; G/ f9 d. _  y                        buzzerCall();                & d5 T# i* h4 Q/ X
                        //用减小按键取消报警标志
7 l  h+ x/ ~  Y+ S+ _& |% _                        
  Y  F, S& {# y; J: Y                }$ P$ G/ Y- P8 _- e
                //-----------------------------------# f7 {$ D  F  J
               
7 f/ C$ \1 f! u4 `4 m        }
9 K1 G8 W) O8 |: c* s}, S+ U; Z3 [* P$ }2 R2 p4 C# `
, l! x9 R" w; c( v" m6 c
; \" P8 x5 E9 _. F1 m6 t0 t( G
#ifndef __MAIN_H__
" o6 c9 Q. T- y( S( y#define __MAIN_H__
- s# u9 O% ~. ?5 Z- u2 E6 i  ^" A0 E; Z" U- L* j: H) [
//-----------------------------------------------. Z' W% |0 ~1 n4 @
typedef unsigned char         uchar;        //为了方便书写定义别名% P2 w& ]7 q' d, W6 N$ v4 K
typedef unsigned int         uint;
4 U+ u# d# [3 @/ E  {: H5 }* W2 w1 Ftypedef unsigned long         ulong;
; w2 k  C% _7 }) utypedef        bit                                bool;5 O+ Z, G; A3 k
' X& T' T7 ]. |/ O0 f
sbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口, B0 F: n+ w* i3 ^6 R, S
#define        isio_Control_Inlet_ON         0& c6 q. r* K/ }
#define        isio_Control_Inlet_OFF         1
6 Z5 ~8 D! X8 T1 }' o" H& ~5 j6 [8 `, [( U& H
sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
1 |/ M" w" B& y6 n& C6 ~% |( @3 L; s: l#define        isio_Control_Outlet_ON         0
# N8 l  Z  `1 k# {9 k#define        isio_Control_Outlet_OFF         1' s* o/ R$ r2 b1 |

" z( _0 d# b& E#define         isYes                1
5 L9 F0 b7 f, k/ ~# l#define        isNo                0
  F( I/ c  ?9 @' i' j9 }) ~//----------------------------------------------------' y4 |- Q  {: y* l7 P
//定义超声波模块引脚  Y7 H2 R  b1 P. l. Y6 S6 g& x6 o4 r
sbit         io_US_RX          =        P3 ^ 3;        
6 d: S$ J& M4 L/ w% Psbit         io_US_TX          =        P3 ^ 2;
: M& j' t1 P( S- `% i6 y& P//----------------------------------------------------
0 b+ o, |+ P' [1 ?0 P4 y+ @, r//定义LCD引脚
2 O) z  Q5 X( Gsbit         io_LCD_RW          =        P3 ^ 6; ! s) z3 O; b' R1 l) T" G
sbit         io_LCD_RS          =        P3 ^ 7;' N  P7 L7 B- k% g; I
sbit         io_LCD_E           =        P3 ^ 5;            
( u$ m2 O3 A. I+ H0 f#define          IO_LCD_Data                  P2
) x2 ], j( Q: a' F#define         lineOne                        0. }& C$ Y- I: c% d  X
#define         lineTow                        1
$ w& V# p. O9 ^5 X% Q3 g. I3 A) G! \: r- @# I4 }
#define        isReadBusy        13 w9 }& ?' j3 T! {9 u. r* E
#define        isNotReadBusy        0* f( N& M5 Q; R

- x0 t7 K* b/ `5 b4 G#define        DATA_LineMax                0x01                //LCD最大的行索引数3 r" S" S% R3 M* t, |- n+ l3 }
#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置5 n0 O1 _9 f5 H: A; P$ X: e. @
#define        DATA_LineTow                0x01                //LCD第二行的索引值  T; c- _1 t+ {4 A
//-------------------------------------------
+ m! N0 }. Z0 g) T#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时
1 N- W4 W# s2 `: ~//-------------------------------------------------: a9 v- |3 z7 v8 T- [" `6 [, ]& j& }
// 定义指示灯端口# h5 a# F, |5 z" R  f& |
sbit        ioLed_Red = P1 ^ 3;
$ M. A' `" B% T& C# l# M; @7 dsbit        ioLed_Green = P1 ^ 2;
% Q$ T0 P4 A& V/ j( i% w8 }0 Y9 hsbit        ioLed_Yellow = P1 ^ 1;
8 {) r% i8 p# k5 k) R
' |  W0 V$ ?- V  Z) W! W: F#define        isLedOFF                1                        // 关闭LED$ y6 X( z9 E0 e4 |  d
#define        isLedON                0                        // 点亮LED3 n" B$ m' h8 i+ W0 q  k
//---------------------------------------------* {* K  k! p; ^6 R* }
//定义按键端口
$ L, Q4 p0 M! p1 E2 j0 \* P% v#define        IO_KEY                                P1        8 T# i7 g9 {  e" Q. y

5 |1 C, k2 h; K2 m# l" a. _4 V#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据. A6 J. h. s+ h1 w# d* b- ]$ W
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据, j& o5 \+ q0 l4 r- s; {. D3 d
, X$ F% x& L" k9 a) f; x
#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据
9 \; ~/ t  K8 t* k* T; f#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据2 h& t0 I7 q% f8 j6 @7 b1 R
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据
; ?0 w1 d+ M% ~( T  S//---------------------------------------------
$ E% D, d" d9 v//定义蜂鸣器端口
0 Z2 A# v" v# O$ d5 C/ a  m" H& Rsbit        io_Buzzer        =        P1 ^ 0;        
6 R& F. [9 F6 I. H% h/ S6 ^2 W//---------------------------------------------; x8 }1 k6 k) |* ~: a. m0 K
//定义检测探头到水库底部的设定距离范围 程序.jpg " ^4 @; C1 y* z) U6 g$ w, [5 K
#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
  e# E2 w2 E4 A' U- B$ [% v( v  Y5 _#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm
2 E* \3 [" a+ s5 o- Q9 V& S; D* z! w1 n
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
. j2 f4 D* @/ U+ Z#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)3 K7 P" C, ]! D
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
" ^- x- N1 v6 R) p! p7 a  K  M3 y* a
sbit        buzzerCallFlag = P3 ^ 4;; b4 S& k, I% c
#define        isCall        0
! V0 S& ]& b8 N. e, }  J#endif
+ |. P+ O! J- g4 N" W
: _- S, Q) U% B6 o5 u
. v4 Y, d3 P. h1 L. j
8 D: Y  X1 u' `; O; V4 A& q0 d& y+ L5 g

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

18.27 MB, 下载次数: 4, 下载积分: 一乐金币 -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
6 \, L+ t2 h' k! m$ g# u/***************************************************************, S/ A# c' r2 O7 t% T, A
        名称:基于51单片机的超声波水位 ...

8 C8 W5 }, M( A+ T又下载一次,打开跟你内容不一样?
% j; \$ @" _8 c+ h7 K' A: e
QQ截图20201211202119.png
回复

使用道具 举报

 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05. o0 e: L& N5 _+ c# A
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

/ R1 G$ V( [6 o" T% D是的、是物体都可以检测到!
1 c* e: k$ ]7 S/ K
回复

使用道具 举报

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

使用道具 举报

本版积分规则

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

GMT+8, 2025-8-20 09:06 , Processed in 0.044534 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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