一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 2850|回复: 7
收起左侧

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑
. J! h. w1 J6 b: W/ D
' t) q6 J. z+ @8 P+ y* A
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

% r$ A: O* h( [9 B2 `+ }' @6 I
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

+ y1 ]3 H& i( m" p
按键功能分别为:设置键 增加键 减小键 复位键

. T+ K$ N. V; J1 x
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)
2 ~$ E6 A% s% n: ]- M' R; }
发表于 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 编辑 : G3 m( A" R' i- W* h$ W
tdc31224 发表于 2020-11-24 20:588 K1 Q2 H9 S2 I! E7 R: R' b
没程序?

% B6 {  E  \6 u/ n. A3 p  s. U$ s3 p' E# C0 l0 [5 q& I8 R
/***************************************************************! E; K9 l7 n% B& r! u( L, ~' e- o
        名称:基于51单片机的超声波水位监测报警系统* ^) S" V* a$ B& A: C
        单片机型号:AT89C511 R$ v4 m* H0 u# m. W
        单片机设置:时钟12T,晶体12MHZ2 T. W: w$ g  a$ E* G
        注:修改增加水泵控制和排水控制,即双继电器9 _; z* m. i! R( ^. Z
***************************************************************/+ O; k) T0 F4 |! |8 C# k7 P

, G' ~4 V2 N+ k% v5 N+ _9 Z#include <reg51.h>; T8 z- W* P$ A# l# G
#include <intrins.h>                // 包含循环移位:_cror_
. x1 o( _# r* }" w#include "main.h"     
3 B/ }+ {. C) ?. }3 E' [//----------------------------------------------------------------------
/ {. Q* B, ?! v( [- G) o0 J  F/ _- w5 {7 t* Q- o
uchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};
+ f! [$ b8 {1 }/ l' y
% @4 {1 Z$ f& C5 q2 fbool        g_flag = isNo;                //用于标记超时(65.536ms)           
; @9 J& |( j6 ]3 Y# fbool        g_flag05s = isNo;        //用于标记0.52秒  , m2 J" a, K0 Q+ H, a
uchar         ucCount = 0;                        //用于计数0.52秒     
" M5 B% k1 c5 a: `3 d) R2 j3 L( D" r; r. j1 u: M) |% `
uint        uiH =  86;                        //设定的最高报警水位 H
4 g$ [" X( H$ `; _) o$ Duint        uiL =  73;                        //设定的最低报警水位 L
' N3 `4 r5 y1 m0 N: Puint        uiD =156;                         //检测探头到水库底部的距离 D / p9 C; {, q% D0 q, E( J
6 ^7 ^5 o( l9 z; s1 ]
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志
% \) s, c) \* R/ _7 Jbool        g_flagBeepTimer = isNo;        //定时提醒标志
. F$ i: b9 P# Z                7 Z: V# K% z: O; k' z" x
4 T/ l/ m  x9 p$ S# s
//-----------------------------------------------------------------------
0 ~2 Y. O. Z; a0 M& }// 延时10us: u7 u1 N: y, ]' y, g+ G! g3 q( Z
void delay10us(void)                //@12MHz6 W2 w. d# K7 p
{
( [: K/ u) ^) a9 U' a4 E1 P        unsigned char i;
/ g$ l/ G. b* `0 h) c( G$ B2 \5 T' N6 u7 F" a
        _nop_();
: \* T* ?0 N* H) K3 ^        i = 2;- w8 V! O# d; h. r0 v% c  O/ `: j
        while (--i);0 ]/ C) z- J, T
}3 A# K8 Y) H" \$ _9 V

& X9 |% @4 m/ X& [% u$ A// 延时100us: c, U' p8 Z7 u9 n
void delay100us(void)                //@12MHz
. W# h7 D/ ?( _* G{
7 C% h6 `1 W1 s4 k4 V, [' b        uchar i;
. \8 V' F/ L. R& @9 M9 J3 f: j  `6 r/ j6 D+ x
        _nop_();9 Q3 W! A3 I4 `2 p2 T
        i = 47;4 R8 C  B- g' i  N8 j/ g( u, _
        while (--i);8 O0 a1 U* h! |5 [" P" p
}5 }# F5 D. q" Z" A5 z
9 H+ h  x* H- b
// 延时125us% c5 G+ L; y. o  B
void delay125us(void)                //@12MHz
3 x! A: a/ c' ]{
, f/ R* s6 e- A        unsigned char i;
! q/ g0 Q- r0 g0 Y& d5 i! G$ b' u. C        i = 60;" d1 R) K, s" I) ?" K
        while (--i);8 V! c4 I  @! \4 C7 {, l0 s; Z7 A
}6 J5 u5 O2 r. B8 j

  b) b" H; Y7 c8 R% A5 [( I3 c// 延时5ms
& `2 M- Y1 W% v: ~- a1 xvoid delay5ms(void)                //@12.000MHz2 z" i9 D/ P. D" Z* K) y/ ]+ J3 r
{' w3 J( J0 i6 p- m
        unsigned char i, j;) ~1 N6 M- U) _7 F% J/ C7 Y4 ?( Z# ?
& |1 v9 L/ N) ^
        i = 10;1 r3 k4 n6 _! {. F" ?
        j = 183;
  S9 b, X8 M* V+ s        do0 ~$ ^& y* j3 v7 W9 C
        {8 |; K5 D- R, [1 L0 s1 y: j1 }0 H
                while (--j);# E6 J+ T9 t+ j% S2 u0 ^- f
        } while (--i);
* U9 w( y3 \( O, W7 N}7 q! ~) ^6 R+ @, f  ~) g, X! e

$ }5 C3 N& u: |' c0 p- I9 S// 延时500ms$ G4 Q) H! j4 @; ~% M$ z
void delay500ms(void)                //@12MHz
9 @( j- q& P8 g3 _{
% b! F% u' N7 v% M5 ~7 l" `; F3 \        unsigned char i, j, k;
3 u1 I5 B& ^( b0 _$ F. p6 m, K! T1 a1 X
        _nop_();6 l/ D: O+ [8 w& t; S
        i = 4;
$ f$ Y% z+ @$ s: F7 z' h        j = 205;. Q  F% Q" o; H! [) i1 R( `, C
        k = 187;
8 k  Z3 q  B) o5 F        do
# `- ]4 P4 E/ [        {; V# n! A6 L* q+ ~( g( |: I2 X2 U
                do
. W& N# V% J- K7 e" b4 K                {3 X& w) b! L. a! `, K+ @3 H
                        while (--k);6 w  D4 ?7 x, c8 z5 v' u6 j, s
                } while (--j);
/ F7 T. I% ]8 M        } while (--i);" y. Y2 b5 p4 }; [
}! ^( c8 y% L3 z4 t  @

: e& h! V: m3 ]" t+ j//-----------------------------------------------------------------------
) J7 G  `" a0 |* O; M//初始化IO端口                        
7 L* G; J' L3 D5 ], |) Tvoid initIO(void)                                        0 u3 U3 d& m2 @/ l7 S/ ^7 s
{) O$ R, N. V, Q, |+ U! y. _
        P0 = 0xff;
+ u/ I4 T  {$ `3 B+ Q) t$ ]        P1 = 0xff;- b) l6 C# ]! B2 q9 A
        P2 = 0xff;9 J6 q2 Z  b6 \- B9 |8 @/ n
        P3 = 0xff;0 x; s8 r* z  d" a) @2 |. g- h
}
3 U+ m$ {* a; F6 {6 Q" o, `8 ~( a& P  v! ^
// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz5 C% M3 b2 C  p5 C; E/ G- B: f# I5 J% A
void initTimer0(void)                ( {" @6 z) @% o1 X( G
{
7 a- D6 p- @3 t. \& N$ R        TMOD &= 0xF0;                //设置定时器模式  I8 u( ]# ~, [2 X
        TMOD |= 0x01;                //设置定时器模式- h- |: ~7 K2 s  O
        TL0 = 0;                                //定时器初值清零
9 B0 o5 v% Y$ A" x8 W  j        TH0 = 0;                                //定时器初值清零2 r0 D$ N( w8 ?# _; ^% d' a
        //TR0 = 1;                           //开定时器0$ n1 L3 N7 \6 `/ }. c2 j3 z& R; w" J
    ET0 = 1;                          //开定时器0中断4 ]% C1 q/ V( K- f  H3 ~8 ?
    EA = 1;                             //开总中断            
, R) |" F9 e, [: S        
2 A1 V8 C1 D* e% G1 M, @/ c' W, I}
1 ]( R% o! o1 Y) w% j7 G: m
2 j( N3 }6 W7 [- r// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz0 O9 m8 n' w& e& X! M
void initTimer1(void)                //50毫秒@12.000MHz
- W) {- a; u; T# b" r{        ' i6 M4 ^0 S. i4 Y, ~0 c4 u
        TMOD &= 0x0F;                //设置定时器模式$ ^+ \  r% M$ W/ n9 J
        TMOD |= 0x10;                //设置定时器模式( X& o0 o( Y; O# o& W
        TL1 = 0xB0;                //设置定时初值
6 t: G+ }( Z# R7 w4 t        TH1 = 0x3C;                //设置定时初值        $ ]9 V! E% D( Q' I- V/ \
        TR1 = 1;                //定时器1开始计时
% I' P7 E& G/ I        ET1 = 1;          //开定时器0中断
/ {/ Q6 j% j6 e4 d" d& k. m1 i; ]}
9 |/ G1 {( Z9 j6 k$ o* _4 t' d' X
1 v8 |9 x: x) e//-----------------------------------------------------------------------7 u0 W6 f- K4 Z" P; G$ i4 V) d
//定时器0中断8 [) t9 V7 _+ j7 w* J) ]
void zd0(void) interrupt 1                  
5 p8 D9 }7 z% ?) T" M' z5 \{
0 x+ c7 q& F' [8 L$ ~9 N. y        7 {/ {& ^$ Q4 Y8 Z
        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围- y+ ]* i" J' e- U2 S& s; x* J
        if(++ucCount >= 8)
9 H( j# m( l2 J3 Z8 Z& i        {
1 M; d/ W+ q3 z' k2 }, _                ucCount = 0;- Z3 o! Q; ?/ G+ @: T9 _
                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时: a4 \' E! W" M0 O: l5 X* {4 N
        }
- V% I/ I6 \; x9 z# s* o        TL0 = 0;                //设置定时初值$ T, t0 e& i( t+ u1 i( q5 l/ J
        TH0 = 0;                //设置定时初值
) D8 Q) S0 `# u/ O+ y        $ d) x$ ~, Y; i
}! k3 _6 P9 L6 ~& n+ Z% L# N6 a
" q+ l4 [. p- M: m; ?- H2 U
1 w! |8 Q5 r2 y/ M% Q
//定时器1中断 定时50ms2 d0 U, ?" v- h) ?2 v
void tm1_isr() interrupt 3 using 17 l4 N; }, m1 K9 e
{
4 B) }3 P, j; S- ]: L; f        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S1 d" Y  F5 _& C$ d6 S
        static uchar uiCount = 1200;                                //                        = 1分钟                % c/ P; R8 q8 u9 r( N. c, C& O  c
        static uint uiCount_BeepTimer = DATA_BeepTimer;6 p! a5 g! J5 {( Y/ a

. Y2 c/ d/ n& Y        TL1 = 0xB0;                //设置定时初值
. Y- _5 E' H0 {  S6 @        TH1 = 0x3C;                //设置定时初值2 ^0 v" `# e0 H# T! W& o( `, F

5 s( C- l9 d% K9 T. M        if (g_flagSwitch == isNo)
7 c* @2 ~% n/ u% [3 m$ h1 l5 T        {* e% x0 a8 h9 V4 M" G2 E
                if (count-- == 0)               //50ms * 200 -> 10s( g2 `2 |" P" ^0 w* u
                {
; ]) I, q+ ]# ?                        count = DATA_switchTime;, m4 Q: P' T7 h
                        g_flagSwitch = isYes;
, d0 Y6 W+ @$ y, j7 b5 \: ~                        // TR1 = 0;* q% U8 L# l6 h5 V
                }
# L6 |- C" S2 M$ \* t        }        
; w. h+ Z+ W+ O  R/ Q; ~        
$ |1 {, O$ Y# z1 i2 d3 V0 R  I        if(g_flagBeepTimer == isNo)
9 F& v, H, K5 k1 K' x        {
, D2 h: \2 v# v                if (uiCount-- == 0)               //= 1分钟
' F2 o& S: V$ R+ i! e/ V) n' u                {
' o* w% X' b$ f6 d$ l- y                        uiCount = 1200;7 I( S5 x' o' h2 C- I" o3 w8 e, o
                        if(uiCount_BeepTimer-- == 0)- _$ i: O% j7 R8 V9 {# ?
                        {
% g6 J2 c: B4 j5 ~! @3 X                                uiCount_BeepTimer = DATA_BeepTimer; + J+ m6 w! A2 i4 t% v
                                g_flagBeepTimer = isYes;
3 u/ H2 f) ~. p* P                                // TR1 = 0;
/ T# @! Z7 Z; s# ^8 B- A, w                        }                        + @8 k9 U: H: L5 G% A# @9 L
                        
; X: Z2 j! S9 G, `' Z7 B                }
4 h1 }/ d, }, @; i6 O7 ~& d* H! a6 l% o  p) a
        }
4 Q: q3 F) `: e' V  q}
, U  W! D$ L. g% r' @
! a* x8 M4 S( i4 n0 m; Q' X5 U//-----------------------------------------------% n+ [" F5 _- g5 G: P% {6 f" D
8 p. P7 M# T0 W7 O
1 k& L- j6 t0 h* h) S0 M3 T4 T

) t5 e' M" U' O; h, R& V  x
  R, n) P& z" }3 w9 K5 V! e4 ^* E6 _' Q* d8 B
//外部中断1$ P. [4 s- H+ q- G. ^6 {
void exint1() interrupt 2
/ X. r* I9 g* [9 ~2 O: n{0 G" @6 }# c  {1 |" A3 ?2 D3 c6 w
    EX1 = 0;                         //关闭当前中断
5 a  m$ I# z$ _$ w& c) m        TR0 = 0;                           //关闭时器01 M* q4 i; x: {1 w
        5 N; @" v" q# \5 S
}
  Q1 |. U! o3 c  a* m  w//-----------------------------------------------------------------------( F& {' d3 `# J9 w% [  n
% a, ?# M4 q: h3 g
//读LCD忙状态并等待忙状态结束
* R) ]4 e0 g! z  C+ mvoid LCD_waitNotBusy(void)) y# V7 T, u) g9 E% p0 Q$ ~& W, w
{0 i2 a' x" e% O# F) o7 w- w
        IO_LCD_Data = 0xFF;
! T7 p% d& ]1 x  H% W# W, b, g        io_LCD_RS = 0;- @6 I5 b2 x! L8 X7 g7 R, \$ T5 S
        io_LCD_RW = 1;; H/ A' A# B7 B2 y7 E$ S, ^
        io_LCD_E = 0;. B. H. c7 M- j
        _nop_();
8 D7 E/ ~2 I. B4 R: ]/ O" _        _nop_();
) }/ p* s+ J9 q0 z- X3 }4 E        io_LCD_E = 1;/ z; p4 F" U# {* ^, U- l
        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙7 a: C2 f2 b* s9 e
}" e. r+ |% H3 g' M* N

: C5 w, `, O3 X) k//给LCD写指令% V/ J7 m: |& j$ d! a0 U' L* G9 S  @
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
0 i7 T  w+ t  e; b- J{
, t- P0 Q" s7 C$ @# Y: C1 j        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙
/ ]; y' h9 m9 `# c: z5 J+ o        IO_LCD_Data = command;
, s7 I6 X" H) d) K: o7 N        io_LCD_RS = 0;% `$ d9 t# n6 `' F! \
        io_LCD_RW = 0;        
# v+ o! W8 Q6 p8 j* }        io_LCD_E = 0;0 {' |: s* {5 }' p
        _nop_();
8 e" h" Q! W8 o1 Z1 f        _nop_();, K9 q8 |! M( L3 d/ H
        io_LCD_E = 1;        
3 n' H% ~' a+ P9 [! E5 w) A7 t, U}
4 w; o1 X$ K! Y2 P$ Q
8 u* R. r7 p$ s% ^//给LCD写数据3 N# w- f, E( I) }" V/ E
void LCDWriteData(uchar dat)
. ^; m0 S6 p% U{& j) p# o2 ?  s% ]1 |( ~/ M
        LCD_waitNotBusy(); //等到不忙
9 ]9 l# V8 G# \! z9 ?" t% k        IO_LCD_Data = dat;
7 _7 O& w3 x' c        io_LCD_RS = 1;
) R% [9 v1 e4 K) R3 d        io_LCD_RW = 0;  P! I  K# c3 p, N9 f
        io_LCD_E = 0;
" q+ c# F1 l7 T/ @* s        _nop_();
0 _3 ~8 T) s5 R8 `0 O' ^1 k        _nop_();9 Y4 t* s7 w2 Y, ?" k( M
        io_LCD_E = 1;
. f% l* i% Z; R}
* F% c) e/ A  @2 B5 Y( B' i1 z# ?6 [

4 w5 f, d" e* c% G8 c- @% o/ E
' g7 e3 L# o2 i( ?$ F) `( s3 s! X2 ?; v0 {
// 初始化LCD1602液晶显示屏3 D6 S3 L# [6 U$ D$ k/ `. \2 ^
void initLCD1602(void) ' o: {8 p. b! a( [
{7 E( U* H! T+ R" r0 O  F; q, u5 a
        uchar        i;        $ N$ R( |$ m$ K: E. T; p
        IO_LCD_Data = 0;                                                                // 数据端口清零
! M6 [; w+ I: Y$ L        for(i = 0; i < 3; i++)                                                // 设置三次显示模式- f  M/ A# u7 ~# L& c; Q
        {. ~( J& x# l! `; j; _0 q
                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号
- C& f2 F# L( g; v- c                delay5ms();
' {3 C& u0 d9 A) p        }
2 z- F+ y& t/ C& @        $ i8 a' [: M- [# M4 b+ v: q
        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号& E2 P' w) z% x# u. B' x2 z
        LCDWriteCommand(0x08,isReadBusy); // 关闭显示& y1 x+ ?. h  I( j, T# x" k
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
" |: c* O- k( [7 O+ k- |  ?        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
$ z, e1 `% G. b: m* M        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置  S( s3 T$ t" ^. W
}
& h" C& ~( Q: E  V
* ^7 }, f0 c* _$ ~& W& r; z* p3 r
9 k0 V3 Q8 G: Y5 r' j! F- P& n
$ H. k! ]( y. T//按指定位置显示一个字符' X* S# f+ S! _7 L
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
2 i! ]2 R# ?3 |{
3 o2 z3 m8 C* w: N0 \4 S+ }) o2 b$ ?5 u* t8 s% `& R
        line &= DATA_LineMax;
" t- \0 k0 E# z- p- {        position &= DATA_PositionMax;4 J7 ]5 y4 }, K3 Q0 u5 ^/ L
        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;  w" Y1 I1 u2 |
        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
) a$ ^% W' ?/ g- H        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
+ w8 S  y) J! J; Y5 F; A2 S3 m        LCDWriteData(ucData);                                                                  //写入字符的数据        % H( l/ o. ]1 W/ }3 O
}" P( s' K, V; y; _' o
6 ~: T9 \6 i( \$ C3 L& {6 J  o
//按指定位置显示一串字符% c9 f) O( M& N; P9 m
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData), M0 [( ?. I2 ]4 J9 s
{# \8 r2 R" g1 L8 o
        uchar i;
# B3 U& z. r# F" N, t        for(i = 0; i < count; i++)                                                        //连续显示单个字符' u% j, `0 ?" K. M, Q1 [
        {
& Y8 R4 B/ d# W3 A( D( [                putOneCharToLCD1602(line, position + i, ucData);        
) I7 Q- W# x7 }        }
% R! p& |1 N& ], G; @}
9 {: o' C% ?" F2 i+ g9 {, G" q5 Z4 B: t& r
: d6 h& ]( E' E9 A* f8 q8 @
//按指定位置连续显示三个字符(三位数字)
2 C! t3 t: J' q" ]9 }void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber): C8 c% l( N# T+ q. B. M# @
{( i8 m, @" D. M. R8 B5 }( ^
        uiNumber %= 1000;
" t% `) r, M8 D# W$ N2 Q        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);7 T( r9 w+ d& C8 {$ v3 k1 @, [
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
' u4 p& `/ C0 T) C        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        + b6 H0 |1 E# `3 P
        * ]/ |" D9 X* K5 u* k
}" A: {+ P6 G" ?% S4 _1 ^9 }
        1 g, j( A, e6 K% a4 R* c1 J5 K

5 J5 s! ~, a& `1 L, d* N
  M! `' i4 T! c# I// 按键检测子程序,有键按下返回键端口数据,无键返回0! q; b+ {4 D0 ]* E
uchar GetKey(void)) F1 j' @2 c3 T+ K) }$ a4 n- i
{        / L, _$ M# b7 W
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        ( c! g$ O7 w8 n* `3 `& P! C
        
0 Q! G3 q) g; p% `# H' M        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空- ?  ~& t) @8 l9 `" y
        {; w* U6 \7 _$ I4 [
                uchar CountTemp = 0;
( @, q6 {6 Y7 |                do
! ]/ r2 q9 \; y: w# g! _! W                {
7 H- M+ j% [! l& m* ^                        delay125us();
. o. R* h0 E- a: _! H' P                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
/ _+ ?% u' S8 S9 e0 L/ X" r. _                        
0 s. s, n+ ?2 g5 G, \, @                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动
1 ]7 k0 M& H- D1 Y; E# }' v                ! Z! e! M2 R/ K- {& [, c2 m
                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放                1 v( }& b0 J- T! g, R7 H  t
               
" n. \0 U. Y6 f8 O, N+ p5 F1 U                return KeyTemp;        // 有键按下返回键端口数据3 i: F: ^0 ]9 G
        }: @2 z+ ?) ?6 F2 S5 q9 B
        
. E1 w3 p% f+ C: ]# O        return 0;        // 无有效键返回0
3 b( w, |, k6 E- {1 Z/ t}
3 ?( ]( a& `6 ~2 b+ r  Q6 v; \4 D5 w' _& v" I! U

' Q6 ~9 M3 j8 k( D. R/ F. f$ r
6 O  M! c! {$ b. I8 g  g9 F//加一
( r! E& z% |6 U' {uchar  INC_Number(uchar Number, uchar Min, uchar Max)
5 P6 ]% v% `2 o( I{
: v- p& r; v! N6 O* R9 d4 S+ f        if(Number >= Max) return Min; else return (++ Number);
0 j  y* z6 n. p4 j% Y6 \                9 H, x* v  E: g, K6 R
}/ a/ h9 n5 W* V% T

7 G( w7 o7 _- p# q1 u//减一
2 A4 {  [$ }7 e$ z, C" Tuchar  DEC_Number(uchar Number, uchar Min, uchar Max)5 Z. F% U1 E0 p$ g% g* i1 m8 \6 H
{2 M6 i6 n1 W; R( s3 t( m- a* u
        if(Number <= Min) return Max; else return (-- Number);4 B5 k: \! ~! G. A
                ! D( N# ]* t% @/ Q& ^+ m! @
}8 Z& ?( |9 e0 {3 q2 |) E+ x+ m

3 I. R- C7 P  r9 z// 检测到有按键后 这里执行按键任务                        
# u2 ^, ?+ w' n  W1 I6 mvoid execute_key_task(uchar ucKeyValue)        
9 t  W( X3 A$ y0 J* H1 p* R. s/ j{( T+ C& u, V' q: f
        uchar state = 0;                                                //定义调整数据的状态变量1 a1 V: t" |& S$ r) _% r* N
        uchar keyValue = 0;                                        //定义键值的临时变量3 [5 P+ Z& N4 ^# X9 Q; L4 S
        
+ o) K% g8 r" `: h: @        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出
1 X+ z# R0 q% T0 F9 {        
2 L. P2 G/ [# ^6 D) [! P6 k        //是设置键继续-----------------------------------------------------
6 Z0 u2 R: J+ N1 D! n        ! k# O% q* @) \$ ^4 ?' \
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                ! D( D. h$ W0 m2 \9 |' L1 p9 G
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        ' @' V# B1 l1 _
        ! u* }% C: {. O8 z9 e
        while(1)
9 z$ Q. K+ z* ^, H2 T        {
% V  R% q. k$ m1 N                keyValue = GetKey();        ! j2 `- a# l  l' I$ X' j5 u# N
                if(keyValue == 0) continue;) I# i1 @" E+ a9 F
                6 B9 k# C0 B- ]
                switch(keyValue)7 ~7 D, p( T0 E' Y9 {5 N& X
                {
+ _/ m+ M% b3 t% C                        case DATA_KEY_Set:
, \3 ^4 ]  R4 ~/ ~! R, a                        {
1 F% p. S2 D. t" F7 M- h8 E                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出( S  ?( A0 w7 m
                                switch(state)3 d8 y0 `+ P% Q1 T
                                {7 Y/ c8 N/ r2 l$ G4 Z7 E6 t9 m; [& |
                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面
0 L# P5 }3 V. D) c                                        {. ?6 s/ @, E3 o# ^
                                                state = 1;                                                * n+ O) j3 ^# n7 S7 o5 N* |
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                ' d: J% u! _2 X
                                        }
( g2 a9 e& J) j3 `2 Z                                        break;- b" ]) f6 [: _* r+ D
                                        case 1:
6 T' r* q8 v! G- t                                        {
! D1 o- u1 ?1 W# B# D1 m' H+ a                                                uchar tempMax = uiD - DATA_uiD_Min;
4 ~& s6 p: E: p' ~) d& b                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                        ( ]% t% S0 O" f$ Q  i
                                                if(uiH > tempMax)
. ?3 s" f- ?" h# m. b! W8 H                                                {9 [  p! s+ t5 K, M; N: J/ j
                                                        uiH = tempMax;
+ w- O& d  |  P8 b& ~7 F- w3 J! Z                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);3 y) i, D9 t, V6 p# f5 G0 |
                                                }
) o- \& J  \% |4 C0 S# `: G                                                else if(uiH < 2 + 2)1 T# }& i, W# I/ Q6 R  g, c3 @
                                                {
4 I; q, j/ K, D% T  |$ T: q                                                        uiH = 2 + 2;        
6 Z8 V5 B5 |& P; J* T# W9 V% D                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
, b3 U) `2 J+ w! s' M* z9 z& G                                                }                                                        $ m( _& J$ Y, e; t
                                                state = 2;) `4 Z) v7 S' t
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);' ~2 E' r& V1 S: B2 s- N  k. i
                                        }
; W5 m% [* a% H: Q" j                                        break;
3 S5 X: g1 V4 U                                        case 2:
2 |2 r8 Y. B: m! A# v                                        {) g) ^) B% D1 x5 R5 z; }% I
                                                if(uiL > uiH - 2) % s( a" z6 S" d- w( h+ @- D
                                                {8 v" n. z! a+ j) ?
                                                        uiL = uiH - 2;9 K) O/ z, [4 O9 n, e% Y& s" P
                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
2 G8 D: v' _0 I8 q& x                                                }
% _& ]' g! |" b- C" g1 F8 ?7 X& p                                                return;        - `& B- n3 _# I& s0 b
                                                7 H/ T! T7 ]6 m6 r1 _/ v0 d
                                        }" Y0 ?2 U9 ^+ b* n, J
                                        break;9 o4 V  b5 x* F  T* ?
                                }1 t1 C, |4 y  \0 e- W
                                # q1 r8 L2 D4 c
                        }
' Y9 k% q! y, _                        break;
) T4 N8 C% N5 F                        // 如果按的是增加键,改变相应数据并显示
" z% `- Y- U/ w9 @6 ?                        case DATA_KEY_INC:$ i4 W" _& c  Q# F# O2 ^
                        {
2 `" }+ S: H+ u* U* o                                switch(state)4 ]9 ^+ d2 H  S' x
                                {. W+ Y' j3 M9 ^, U7 \7 c* a5 m
                                        case 0:
' n9 |  [& S- s- Z  s                                        {
* F/ G# _& y: a8 A; u8 a                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);3 p0 z  i: u& D! {7 O9 u( b
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        ( W# `7 `7 r! P9 Q8 O& V! p6 O  H
                                        }
& q* w3 y  R2 ?) Z9 @5 L                                        break;$ X) t& c1 f+ H( H* b, f
                                        case 1:
5 e/ ]+ N9 @& w; f: X: Y. n! p8 L6 |# ~                                        {& ^5 D: k1 x; h& m0 ]' p
                                                uchar tempMax = uiD - DATA_uiD_Min;
* j3 m0 C4 m. N" |9 Z1 n                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
; U3 }/ ~  V- p& F: w7 n                                                uiH = INC_Number(uiH, 2, tempMax);                                                
5 l+ Y8 d  m1 N8 O5 E; i7 [                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        6 ~/ w7 @$ }- t
                                        }
, D9 G/ c# R7 C5 k7 R                                        break;
, U) i" S+ C5 b. R+ s                                        case 2:8 K3 `- {9 [7 G0 j  Z; C
                                        {5 p$ C% ~  g; Z- O" ~
                                                uiL = INC_Number(uiL, 0, uiH - 2);        + l7 G9 ~3 _# q0 a
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        6 z' @, _3 u- {, }$ }- b! D
                                        }
4 [/ C: b* @9 R# k. j/ G8 v2 V                                        break;/ k, ^& M* {, @; o4 W4 Q  A: ^+ M
                                }
6 Y2 b5 D: b/ o1 e                                5 _5 w% |4 ~$ x5 t
                        }
- @) e1 O) E. e( _* m5 ?                        break;0 c0 N5 W1 s& v3 X8 }. x
                        // 如果按的是减少键,改变相应数据并显示
6 T4 r) \" E7 Q/ y. `/ V                        case DATA_KEY_DEC:
$ S3 F+ u! C# b6 ~                        {+ ], \  L( p2 y5 d; j
                                switch(state)* e: p1 n1 I5 Q. {% R# c+ j
                                {6 X: G( y0 r8 R/ Y7 J8 ]
                                        case 0:
" q+ `% L* T3 m                                        {
% I" D  O( J4 ~' N) J                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                       
$ ~& W0 I9 _' |1 X) o                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
/ P4 u+ `$ \, j( f/ z; x* v                                        }& d( X+ T9 r, N, s
                                        break;
' j7 M# B/ p* u                                        case 1:* c* y' P" Q* c# d( |  `% s
                                        {
5 L4 C0 u$ {- h" X                                                uchar tempMax = uiD - DATA_uiD_Min;9 E4 T+ Y. g- d: o0 U1 C( ~' W
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
0 {7 Y8 y5 E  P                                                uiH = DEC_Number(uiH, 2, tempMax);                                                2 P4 D" b5 h/ [! u& o6 d
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
" Z( @# ~. F$ ^& E( G5 D4 }3 f9 a7 G) |5 c' p
                                        }
) x% ?' S$ E2 }5 ?1 c) H" |                                        break;; h# S: M/ K3 c; {8 r
                                        case 2:
7 D) H% m. [# J" \. t3 u; |                                        {2 V" `1 j0 x! o% ^1 W" i
                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
# T/ x1 t, V. g$ |                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
8 _' E5 V4 ~0 Y, t: x
5 L3 @+ Y2 r4 Z1 I                                        }
4 I% a+ b' ]7 a6 B' W                                        break;
( A5 J) K* V" k! g) x5 v3 ]; W+ t$ p                                }' `+ i  ?: L6 `0 [9 v, `
                                $ @& n$ C$ v# a$ t
                        }
8 u0 U8 b. q. U# W1 J% ]6 s                        break;* k# C/ ^+ |/ i% G7 w% x/ v6 {9 K
                        
% o, r$ B2 \9 i! x+ {                }
8 V6 h; |; U; S! ], Q0 M               
6 x) U: ~- U5 P, p) T4 l        }# O. z& k% l# b
        , g% B2 ?) w6 \+ S
}. G) E, i  N' v+ @- E

6 T0 a. }5 p' N* F+ [4 N8 z, z+ D% ^# s" E: F+ T) [" {

7 K" N9 ?: X( N$ c: }5 k" |" M( C0 @9 j// 蜂鸣器        1 V: ~1 {8 _3 X) o
void        buzzerCall(void)4 c7 \+ G# ^; d! E. B, k* Z
{+ }! _" K2 b" o2 D5 U& x& Z- }
        uchar        i;1 G8 T' x$ Z4 {6 h
        # h1 M' L8 b' E9 I2 ]
                for(i = 0; i < 90; i++)( C) P3 i# Y5 r7 B
                {
6 Y: Q6 G! e0 x/ h. L4 ^7 l                        io_Buzzer = 0;
: c! ]* J8 w4 U' T5 j: L                        delay100us();% s9 j; m7 n4 o6 d, X
                        io_Buzzer = 1;9 Z; l: K" A; v
                        delay100us();* s2 q8 |) y) `
                        delay100us();               
( u3 J5 g- _! Q3 l3 W) ?8 A, a- \6 Y/ S                }5 G0 Y+ y$ D; N- G
                delay100us();        " j. f: Q( J, |; W9 ]
                delay100us();        
$ Q+ |- \# J- \8 U" M}
4 u' p. W  K: O  D" H0 }: T, ~/ W5 n  V: {
//计算水位- ?0 d! q5 h7 d2 q" N. q
bool CalculatedWaterLevel(void)( s$ P$ n0 Z7 f/ A5 t$ D
{8 J( U/ l* t1 [
        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置- J3 z5 ~' x  k7 Y- l3 t
        uint          uiTime;                                                //声波传播时间
8 h* |' A* o2 g0 u5 D6 ?9 V- t        ulong         ulDis;                                                //实时测量到距离        " U, H' J2 D5 E% J2 f
        
* L& }& }- E, [        uiTime = TH0 << 8 | TL0;        
: R; M/ c8 ?6 q- `        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
+ W& I% o- W2 g8 M7 N" m6 U        
1 ~$ v7 T7 e8 Q9 {" j+ a        TH0 = 0;3 o, V% c9 v, k6 e
        TL0 = 0;        - G7 a. S9 R6 u( I& d) o
        ! @' I7 D! n6 S2 K
        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;  y0 {3 L- ~/ j) P- f
        {         ! S% g7 q+ Z  a# N3 A3 p4 X
                g_flag = isNo;               
/ [5 `; z- {. S' k; f: u  x                TR0 = 0;
: p1 ^2 |2 H7 |                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 2 D/ }* {& {% m' i* `% D5 Y
                6 n: V6 n( N0 z
                //阀门动作:               
3 Z* s% S6 s7 K% k; N                // if(g_flagSwitch == isYes)
, e) g# f9 G( X" H4 f                // {               
5 Q( a% a8 @9 C                        // io_Control_Inlet = isio_Control_Inlet_OFF;               
7 Y) g) B. s' V' d1 R- G! t5 a                        // io_Control_Outlet = isio_Control_Outlet_ON;
  }3 Y9 X. F% D                        // g_flagSwitch = isNo;! I& i( V! Q1 N7 ~9 w) ]9 [1 N
                // }               
9 I$ P# v8 n8 S1 o# Q                ) p4 b- X' c5 o+ e4 o
                //指示灯:
/ A2 `7 R1 J4 _" X3 C: L                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮- x7 H" F9 d; F  g$ b/ T
                ioLed_Green = ! ioLed_Green;' s0 x/ Q0 M& z0 [( f
                ioLed_Yellow = ! ioLed_Yellow;
* x& ]. G# H; X  h8 a# \1 z+ C               
0 A& }6 x% ?4 n/ M2 ^: c3 r                // 蜂鸣器叫:        
3 w3 n1 n$ S8 ?! v                if(buzzerCallFlag == isCall)
; m. |9 ^3 o& i8 |5 M( o8 J; K- s. f                {* h7 ^. B% k; R* H9 |
                        buzzerCall();                                        // 蜂鸣器叫        
: g& M4 `6 K- H; F5 c3 J% z                }
; _% n" T' R$ i* M                $ C2 K5 ~) ^9 C% v0 y  @: M; X# O
                return isNo;                                                                        // 返回错误信息
; ~+ a$ n3 s7 y" e5 `        }! u% C( r5 H6 y0 T; t! Z* B: q  v
        else
& |1 S2 O  u0 Y2 i/ l% }% }1 @) k7 W        {
6 T2 \4 y" ^: `. N5 F$ S                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离; v, h+ X; L- t8 ^9 y# |3 A5 B
               
4 d+ ]1 d2 f# J                if(ulDis > uiH)                                                // 如果水位超高
- C/ R5 Y1 n9 m8 q) I9 l. o- o( u                {/ D  C$ G% V. N( Y9 F4 c
                        
& |2 J9 G; v. B' M. e# c                        //阀门动作:1 M2 g+ L+ Y9 k' b5 k, g0 O
                        io_Control_Inlet = isio_Control_Inlet_OFF;
+ p6 b: R: |2 L                        io_Control_Outlet = isio_Control_Outlet_ON;        # a+ i5 H7 y: M" c: o* v
                        g_flagSwitch = isNo;1 m8 C! z/ l2 a0 _) q9 z; ?0 D2 @
                        2 I8 l/ |: N4 L( j" v) F- j
                        //指示灯:6 Y! d% }3 M: a/ B- u; t4 R
                        ioLed_Red = ! ioLed_Red;                        // 红灯闪( G! ?" F  v  V. p4 R
                        ioLed_Green = isLedOFF;                5 E% Z9 P2 q1 G3 X5 R) \6 w
                        ioLed_Yellow = isLedOFF;                                % p& ^, r" }) O$ P* _: y( ^# l+ P1 K) r
                        // 蜂鸣器叫:
- x" Q1 r/ t! @0 I- y4 o) }                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警5 P  i- `% F: e0 h4 G$ L
                        {2 f5 V7 i1 P1 S5 a+ J2 E
                                buzzerCall();                                        // 蜂鸣器叫
' d& W% s- `9 k1 r! ?: a  Y                        }
7 J! r. \: W/ E3 i; w, y/ x                        
7 M0 d6 Z2 D8 _4 E  D/ @  D. l9 o                }
7 `* y' Z+ B% r0 I6 }1 t, H                else if(ulDis < uiL)                                        // 如果水位超低
' f. a/ q6 c0 Z- E# m                {* a/ ]; }" B: M/ M
                        //阀门动作:        
- S% @- y2 Q4 Q$ ?                        if(g_flagSwitch == isYes)
) [1 L# |' S2 B: p- M6 t. [                        {               
2 x; @1 J+ K4 y                                io_Control_Outlet = isio_Control_Outlet_OFF;        
  [0 i' \1 U# u% y. f( h2 U                                io_Control_Inlet = isio_Control_Inlet_ON;        
7 M6 E- `6 [3 W& B; z4 s                                g_flagSwitch = isNo;% ?+ `% `" b* M
                        }        
4 z3 T( m4 n% g  P                        & y) [" C$ h6 c$ |; ~
                        //指示灯:
/ I5 n! n: G# S* i9 p. d3 P8 P                        ioLed_Red = isLedOFF;
9 L3 C1 T6 n8 E3 w4 h7 Z$ T7 R                        ioLed_Green = isLedOFF;0 p3 I( l; Y8 U, u7 p" T  c5 A
                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪6 ]) f) L+ W% y1 p3 r" s
                        // 蜂鸣器叫:                                                1 ^6 }) m1 I. G' @( p: N9 k3 g
                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警( w; t) E7 d9 i6 v3 W3 x
                        {- N$ ~$ m! f( O
                                buzzerCall();                                        // 蜂鸣器叫
* }3 G+ ~; f. {                        }
6 ?! O- J0 w2 F$ T8 Q( u4 A                        
9 I( A6 C! ?* s6 B6 o                        " y$ B0 o5 y8 v
                }
9 s: d; S* O' }; X/ P: Q                else                                                                // 水位在正常范围
# s& n3 @' r1 c) f                {        ; I6 O: `- Q/ Y0 L' ?& v
                        ioLed_Red = isLedOFF;
( L8 Y' t8 ?; _6 B1 }7 z" L- ?                        ioLed_Green = ! ioLed_Green;
) |( t1 W+ b0 _7 q& ^% `                        ioLed_Yellow = isLedOFF;        ' ~% M8 R; ^- ]
                        3 E/ [3 a# z& A" ~  l& Y2 c# N
                }; U% a( z( |. {
                putThreeCharToLCD1602(lineTow, i, ulDis);+ D- e7 s% o7 q* p
                return isYes;        
- d: n; Q9 m, s, S) J               
$ |- ]! W) e; V$ v' }1 B        }
; c+ t# n* p+ ^        return isYes;9 g" u* i, R) c1 \' B& _
}( j. {# b0 Y0 S" N" }% }# ~; w
0 J* i. V4 J, t3 k. T0 U0 ?7 f1 E
/*********************************************************/
) J3 _5 W/ c- s' a7 Jvoid main(void)$ n( {8 y  i$ I
{8 w7 C  J% {/ A
        initIO();                        //初始化IO端口        
  t' g* W' ^3 [5 p% Q+ J        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        9 s0 p8 v% P! ~' i7 J! v! L8 `. C* b' a8 F
        initLCD1602();         //LCD初始化        0 t8 D; b" @6 A% C
        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
6 ]1 t" j( z2 [- {$ a+ s. \. W! y        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值
% Z3 L" z' L6 b/ P& }' |3 b$ [0 l; J        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H; Z  ?! z* ?- t6 I+ n' Y7 C/ A) @3 H
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值# T3 x7 c  X! Z  s: P5 \; `
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L
$ ?2 O# p; _: A0 l        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值% G) p) i" i+ k  H6 U' b6 ~7 ?- u5 j( n
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C0 g4 N6 c0 n. e) Q- }  H: T' _
        6 d* \; Q  n2 w' S* }
        initTimer0();                //初始化定时器0& R! e3 @& T# i% B
        initTimer1();
. S8 ^5 _' H+ N+ d8 R/ `1 |        ! X. ~% P. G5 T  J1 I! C; D& U
        //阀门动作:初始先排水
0 P$ P- r: ~- d5 H0 E( [* q; \        io_Control_Inlet = isio_Control_Inlet_OFF;        
. y3 o& ^5 |7 k. B: C1 ~+ \' Y        io_Control_Outlet = isio_Control_Outlet_ON;/ w' c* _# Z& O; ?
        g_flagSwitch = isNo;        
: m4 d5 W1 K- _; r; I        
5 V7 q+ X4 {& Y6 @; P- r4 P, u7 H        while(1)
9 V/ c$ d# H9 R' K+ g        {
2 D/ ]- g1 P6 N3 @) ]4 I                io_US_TX = 1;                                //启动超声波模块信号' x# k' ~: N# O0 k* _3 B; g
                delay10us();
# f( A1 g3 k( b) c1 v                io_US_TX = 0;, @1 v; @" j6 c& h
                9 K$ `# f' z4 |' I
                while(io_US_RX == 0);                        //等待计时开始
& A2 |; D; i# Q% o% l% ^                TR0 = 1;                                                    //开启定时器0,计时开始        
9 I$ Z9 f8 G+ O8 G: g. O                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
; h; _1 h. t; M, d( B                EX1 = 1;                        //使能外中断INT1               
0 x0 D# N7 |, j- [8 y' X                + o2 y9 \8 J8 l
                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        3 D7 u7 C; C: V+ K) `& }2 M) _! g
                {: O3 c& a; v& U  L7 M
                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
  Z1 M3 C. f. L1 r7 w9 B                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
# B  K, A9 ~8 x7 K# O                }: f8 h: a; X# b  R- v+ ^2 _
                ! `! Q5 O, N. A$ V3 _
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环                " C2 d; T' F' l) F+ s( B
                2 R+ V3 g+ A. R( S6 j% B6 u( n
                TR0 = 0;                //暂时关闭定时器00 ?9 X6 B% r3 D! p! F
                //清零定时器和计数变量以及标志
9 ~+ N. z  \% e+ s$ i. f6 |                TL0 = 0;               
/ w0 d' w. O. P: v$ \                TH0 = 0;               
6 W7 S; d! w) U( Q. o6 K                g_flag = isNo;
* b. Z( l' H' u- N3 g                ucCount = 0;2 f9 y7 G! t- I$ V/ I6 |: y
                g_flag05s = isNo;; A1 l* R4 Z7 V4 c/ x
                ( R' Y% j4 h4 n; `# t5 h: u* a
                TR0 = 1;                //打开定时器0                                        7 L0 \: l! w- }' L  l
                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果: K% s, v' @' Y3 L
                {                        
3 F! S: b- f5 H# V/ K" D2 r                        uchar ucKeyValue = GetKey();
6 a+ x" F# f% y  M+ L                        if(ucKeyValue)
2 @- W9 L9 [4 C                        {2 h; J4 d* t7 d* F, U. h( q* I0 G
                                if(ucKeyValue == DATA_KEY_DEC)! b, b# n& [) S5 j9 q6 r; }! f
                                {
  H3 U8 [. D$ w4 |                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志
8 r% t( @' e$ C9 l  [. T' ^4 K" {                                }
0 |/ F  n1 T) L- ?" h7 _  }
, {& h" c& W0 A8 u8 @$ `0 P) R8 y                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
) l# [1 Q' ~4 ?3 D1 `% P' R& T                        }                                : e" T9 @  L! e, E8 ?6 ~7 K

! S- O% h! l4 W: q$ `3 {                }        % J7 m$ G( Z) ^
                TR0 = 0;                //暂时关闭定时器0/ j5 i& g- e0 x/ M2 j
                //清零定时器和复位标志
' g, |6 o5 ?( U; u, P% r                TL0 = 0;        
; ^2 D; t/ ]- O; S# B                TH0 = 0;        
2 P8 `! @1 v! n7 x- S                g_flag = isNo;               
0 h2 l; Q3 \# K- L2 A% N                " R* B1 e% [4 V' Z5 u. a
                //-----------------------------------
8 y' l/ J; k. Z, K                //水箱清洗提示:
/ \5 q+ |+ W4 }4 v                : T( P& l8 i; B) E) l$ ~. U
                if(g_flagBeepTimer == isYes)
% F& Z8 t: X3 E$ W. m6 g' R' q                {5 I6 W# L8 e3 B2 U
                        buzzerCall();                0 q( l9 I7 ^' S* \
                        //用减小按键取消报警标志5 G, i8 n% Q* D) p& Y7 ~
                        
, t7 n& `# v; A2 R8 [7 z. q                }+ }( H5 q4 ?# J% J8 }& b- a% Y9 C
                //-----------------------------------& `. X" p6 P2 z& c! l5 ]" [
                + B4 [7 E6 _# v/ b
        }1 S* ]' \" R8 F# p
}
% H3 u( _: f! I" Z$ E5 u
4 r9 o) E; o! K" H3 B
- ]* j; \' u: G# o) U5 V& Z#ifndef __MAIN_H__
6 [: ~4 G' W( A#define __MAIN_H__
( L# q6 x  t7 l: \: t6 b2 V: J0 ?& {# C6 |
//-----------------------------------------------% Q' v5 A0 u3 m4 b
typedef unsigned char         uchar;        //为了方便书写定义别名0 P1 m" k3 E; ]4 ^1 s
typedef unsigned int         uint;
9 W/ R3 w- w: `' m+ E: _typedef unsigned long         ulong;
1 V1 U3 D& V) l) l( {* U# Stypedef        bit                                bool;! `5 U& L4 ~! ^0 j$ R7 M; [

+ G3 @9 u7 s, ^: H. i# osbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口
+ P5 y* z# s$ I' N/ t" v#define        isio_Control_Inlet_ON         0
5 T. l3 j4 o$ K* K#define        isio_Control_Inlet_OFF         12 m1 Q% p# u: c8 d, u1 ]
8 O3 p3 q" Y9 S, t, T# s
sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口3 H* r5 l$ A  ?1 X
#define        isio_Control_Outlet_ON         08 m: v& n" u2 R/ s1 v
#define        isio_Control_Outlet_OFF         1
3 I' `4 K4 v. ]; {8 @" s: ^. g" y5 v+ b9 u7 y& d3 U% u% [
#define         isYes                1
- t( w" f7 m# h5 z! A; V#define        isNo                08 e' j9 X; N6 n& a! R
//----------------------------------------------------
: M3 [/ z/ q$ x  h3 V//定义超声波模块引脚  D. z( |& K1 l4 f4 B8 f
sbit         io_US_RX          =        P3 ^ 3;        $ d) F9 z! ]3 Z4 f: W
sbit         io_US_TX          =        P3 ^ 2;
9 t5 k# \! u: z# g1 w4 r//----------------------------------------------------6 E4 G0 n$ E% ~* v, p' }
//定义LCD引脚
; ^) n$ V; B2 j, j# ?0 }7 k* s0 `sbit         io_LCD_RW          =        P3 ^ 6;
$ ]; x! Z" l/ w5 s6 d7 {; G1 p0 Lsbit         io_LCD_RS          =        P3 ^ 7;
- L# R; v7 u4 K3 _6 ssbit         io_LCD_E           =        P3 ^ 5;            
/ w. K( d( T' z- X#define          IO_LCD_Data                  P28 h) R* _  K* t4 l
#define         lineOne                        0
: k4 w0 _- E3 o& R, O' f# M6 c#define         lineTow                        1
5 G  w# G5 V. s  J7 U$ S  I/ h, J1 p( B; c9 T( k
#define        isReadBusy        1& }' X4 J1 O0 @9 M$ R' {
#define        isNotReadBusy        0, q0 a0 _/ X2 e1 q8 y
8 C) |" T: x0 J5 H
#define        DATA_LineMax                0x01                //LCD最大的行索引数
& e0 M# ~+ a1 u" K#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置
% i+ U7 Z; X% E#define        DATA_LineTow                0x01                //LCD第二行的索引值
. `5 \) M9 y. H# r0 V& d//-------------------------------------------
0 g3 h$ ~% ^- H  ~; G1 Q#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时/ ~, o7 \" r: X+ q% _
//-------------------------------------------------4 S/ g' |- U! `) p2 U! ^, p
// 定义指示灯端口( x( l  b- z8 |" D2 m# d3 b
sbit        ioLed_Red = P1 ^ 3;
5 j# f7 f" Z4 S8 j6 l# S1 P. Wsbit        ioLed_Green = P1 ^ 2;# K: y6 E4 |; |& M
sbit        ioLed_Yellow = P1 ^ 1;# f8 P2 c1 X6 u& d2 t$ I' u. ~" m
( X+ k% V8 D1 D* N' W% r6 S
#define        isLedOFF                1                        // 关闭LED
3 `4 a0 L" \) s* s. H1 j' x7 j3 X#define        isLedON                0                        // 点亮LED! {$ B! b+ \3 v) X3 @
//---------------------------------------------
* S$ k) m! x$ W( L, k//定义按键端口( w1 B5 Y. D. c% F
#define        IO_KEY                                P1        
4 I  m& \$ @( T4 j* d$ l8 M# |/ T
* @) q6 H! U0 j& M) K7 ~3 i#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据
# R& s. s5 O' @/ p! W; S#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据
: `8 K4 I5 e/ p$ ]
5 E" B9 B  P5 u0 ^#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据, T6 b5 L6 e1 V
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据1 f, i" |2 e2 _
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据) [) f9 \& u; B/ I4 w
//---------------------------------------------
, |7 n! `. |4 H. V1 _. N//定义蜂鸣器端口
4 f" ~; k* z* A* W. z7 p. ?& B. ]; e# Nsbit        io_Buzzer        =        P1 ^ 0;        + n8 Z4 W% L8 O& h6 X6 ~8 L
//---------------------------------------------% B8 S/ q2 u9 p+ Q/ e
//定义检测探头到水库底部的设定距离范围 程序.jpg 3 n2 f' S, [8 r
#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm& Y% o' {' Z  S* d' D# s
#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm
( Y; h, o. U; }7 A+ V7 e7 {- E4 j7 R! X
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数( J# @8 @) D8 ?" {& I
#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)- M' b7 v! R/ e# K" x/ p: p
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
5 i: L" C4 Z+ I
% x8 k* U9 l! B5 y1 S% K: j6 Gsbit        buzzerCallFlag = P3 ^ 4;! s0 L" A# s9 Z- |
#define        isCall        0! s6 z: d% {  n  Q  U$ Y, X
#endif
" {1 p4 j* R1 h* r0 ]- g% z: n2 I) Z/ x  ?

9 S+ D) \; u# Y& k! n" M7 i
. [' ^' _( O+ ^/ `0 V8 _/ W5 f/ |6 y5 J! A) f) P; I

基于单片机超声波液位控制器设计.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- v; x/ z; L* \
/***************************************************************
. r. d- R8 P2 M: [# v5 M- d* I        名称:基于51单片机的超声波水位 ...
, Q  u( D9 \& w3 w8 P
又下载一次,打开跟你内容不一样?  A& N" |2 V3 r8 A+ J
QQ截图20201211202119.png
 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05( B; s( i4 }! S3 L
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

$ U: Y4 w4 s* l9 H* k8 x是的、是物体都可以检测到!6 K9 [; c* ?( D, @; _- o
发表于 2020-12-18 14:55 | 显示全部楼层
程序Keil、Protel99下载不了怎么办呢

本版积分规则

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

GMT+8, 2025-4-28 02:19 , Processed in 0.065709 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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