一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 3342|回复: 7

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑 + T8 N- P8 j( W; }+ v/ s+ X
" s2 S3 ^: J7 ^+ ?1 D! z. x+ S2 \
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

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

$ M4 n3 V) g, T! [3 o' e2 Q
按键功能分别为:设置键 增加键 减小键 复位键
% M  N5 E  h8 d5 E. h+ u
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)

9 g/ R% x+ a9 b; p
发表于 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 编辑
+ X0 A( G2 j; I1 k$ P6 L  G. {
tdc31224 发表于 2020-11-24 20:584 d# y; d6 I. h8 k3 \& a7 |  o+ V
没程序?
# Y5 Y; M6 N" i# E4 U! A
/ B3 k& q9 g* X# L
/***************************************************************0 T+ d8 b+ }$ H  q& e' B6 b
        名称:基于51单片机的超声波水位监测报警系统* k6 c2 k6 K4 L, ~" o
        单片机型号:AT89C51( H: e7 W8 l9 k1 a' q, {
        单片机设置:时钟12T,晶体12MHZ
, c: p* U& _* p2 i9 x        注:修改增加水泵控制和排水控制,即双继电器
; s9 |* C5 m. X***************************************************************/
" v# T8 A0 _0 x& f+ G2 O- x" P
% L* K2 M) X( j4 H2 c' a- L8 S9 ~#include <reg51.h>7 s& M. N2 c! D: F! M
#include <intrins.h>                // 包含循环移位:_cror_
6 g- ]+ x8 k3 d4 ?0 L#include "main.h"     
( W+ u; p; ~3 M# ?- C, c//----------------------------------------------------------------------7 [. C  W# A; K/ L4 ?3 k+ ?2 {/ H

" U% r5 ], r$ _& g' W( juchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};
0 z& h( d2 A. v. l- M/ i: e1 D( R& Q3 _
bool        g_flag = isNo;                //用于标记超时(65.536ms)           ( P2 P! R" M! q+ f5 n: x
bool        g_flag05s = isNo;        //用于标记0.52秒  ( H; M7 ]( l$ S8 }8 e: p
uchar         ucCount = 0;                        //用于计数0.52秒     8 o* B0 w2 |- N0 ~
7 Z, Q$ i# O& g. j. {7 }  w* F. W
uint        uiH =  86;                        //设定的最高报警水位 H
4 T6 x4 t2 K+ I1 {4 o% {1 X; suint        uiL =  73;                        //设定的最低报警水位 L
" m0 T4 Y, m1 ?; s, ]5 |1 \% buint        uiD =156;                         //检测探头到水库底部的距离 D
; _  ?! r( Y% v8 F8 C: G% e: X8 X, l8 e( Y
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志
, i7 t! ]: x' Y# V6 {bool        g_flagBeepTimer = isNo;        //定时提醒标志; ~' j/ K" D. P* y0 d% X$ n8 ^  M
               
, Z7 [+ o; x- x- j6 [1 i  m$ Y6 |- Y; E/ D2 U( U
//-----------------------------------------------------------------------, F# `, `! a9 @( T
// 延时10us8 [4 a3 q- x! ~( [% l. s5 P
void delay10us(void)                //@12MHz
7 D4 d$ y" g4 B{
; y* Z7 |3 o# @: E, t9 f9 k* V+ x        unsigned char i;3 @8 y& `  T5 y
3 ?+ `  x1 b' a% K  K* v+ O
        _nop_();
( @2 V( A  K7 A3 g/ B/ P        i = 2;! Q; |+ b5 e! K3 P. D5 U
        while (--i);
- \& [- t* G/ K1 h5 x9 j* ^% W}$ A5 x/ P9 ^, ]! @) \8 P
+ G& O. b# P4 ?* O3 }
// 延时100us+ X. r  l1 C  H7 }
void delay100us(void)                //@12MHz4 D' B- v, b9 P/ C
{9 g8 p, t" h. @, u+ J
        uchar i;
2 A. G8 J/ u0 [- [8 ?3 F$ F* T
# U* G; Q1 h7 B/ J) G2 y        _nop_();; y: t; i' p& Q) X. n$ o
        i = 47;' d& g& t/ z' g( M: b
        while (--i);; |) \6 {. ?3 B# r3 ^: j
}3 W. w  y" ?3 E/ {9 X* K

8 B/ m8 v' t+ u// 延时125us
( K7 V; X7 K0 q- l: Fvoid delay125us(void)                //@12MHz% w* L/ F( c2 x; D. x$ l" ^
{! [1 U0 w+ l) C* v
        unsigned char i;7 W8 x$ q* c( j8 c' b# E3 E
        i = 60;8 D  |8 y( i2 R8 S* W+ e4 Z
        while (--i);
9 s" }) z' Q" @! J0 U}
# }5 d/ I( e! ?% G* O
3 w# }% r. p- M- R' \// 延时5ms$ g8 E1 T) {" I, W, f
void delay5ms(void)                //@12.000MHz/ z- a: i1 J" b' Q
{
8 k# ~( R1 w+ B) j        unsigned char i, j;2 {( R; c. K! c6 U5 ?

8 N% u+ E1 H3 f& L7 b/ z        i = 10;  a) K6 F3 |: X! M
        j = 183;
) [; }8 j5 K% x        do
) r( Z& r$ H* }9 T        {' V9 `( G+ F4 C! ~/ P
                while (--j);% ?! W& }) s: P- r& D* I8 H  [% ]
        } while (--i);
. p5 b' ?6 D7 ~4 |. @4 b8 f3 ^}
- Z/ B! {' N; m5 T, d) m, \
0 W/ I! v, ~' |" ~( W1 B4 `7 ^// 延时500ms* v/ [! }% _; {8 T, M% a7 q) ?
void delay500ms(void)                //@12MHz( d, _" c8 r* g: C, y+ f) @7 c
{
1 a" I. ]' w( D. {, H6 g        unsigned char i, j, k;$ y, ~9 l& m" f

' \: U9 g7 H$ j- R4 }0 H        _nop_();
4 q7 K" ?9 g. D/ o' M6 V/ M        i = 4;
+ Y# u% W% l# M' Y+ [        j = 205;& v; ~% S$ t" o- |
        k = 187;
3 p0 K: e1 ^* u, D- h% D        do
) v3 |/ d+ l* h        {
! |" W( C" ?( a! c7 }                do
/ w3 f" U' n8 Z% a3 S                {& ?( d( X1 D& d& n! M
                        while (--k);
: D9 |. R" G$ s/ V3 `) k4 C$ |                } while (--j);3 v6 N( m! y; ?* t3 C
        } while (--i);
, L( X. b: g9 F}! [" F" P: V, t3 H$ J, L
/ P* F- u* J, z: `! X
//-----------------------------------------------------------------------. |1 }# k$ F7 K& M
//初始化IO端口                        
; @4 s* U/ N) Z+ Nvoid initIO(void)                                        6 R7 ?6 `; W& q- p# P
{
  ~2 J4 \0 V$ F* ~) M9 G1 _" _; T        P0 = 0xff;
) ^/ i1 [4 V- }: c        P1 = 0xff;
0 B% S" {$ Z3 L4 ]4 }8 _        P2 = 0xff;4 \* u2 \! d, \) s
        P3 = 0xff;4 n$ x4 \0 M. l, U% E2 Y
}& L/ D& a; S  f' p

9 t3 W( A" t$ l6 x. e. M- ^2 t; S// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz5 s, I: P/ N. N' ]# W
void initTimer0(void)               
% s' T3 `! d1 |$ {{
7 f: [- A4 u/ w+ d, z% o# J        TMOD &= 0xF0;                //设置定时器模式
  g  @0 s' \0 U% A3 R8 d) f) ?2 p" S        TMOD |= 0x01;                //设置定时器模式! z1 H) F6 Q0 f. j% i
        TL0 = 0;                                //定时器初值清零1 V, F7 E5 }4 Z
        TH0 = 0;                                //定时器初值清零
! S3 f) ?* \1 {; h, x+ z1 s        //TR0 = 1;                           //开定时器0
! w9 Y+ o4 Q' E# g/ Z) O5 `. m! f0 d    ET0 = 1;                          //开定时器0中断# j$ T8 r/ v4 f" f) N! P7 X* O
    EA = 1;                             //开总中断            4 g3 [5 G3 ^3 L. n' W9 X1 i+ j
        
+ {& M. P: }, L; d}! a% V# S8 P; @2 T

$ t( U$ x2 \3 q. {1 j// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz
; v2 N8 k5 G' m/ Mvoid initTimer1(void)                //50毫秒@12.000MHz
( E: @: d, H/ J7 O. r7 V, P{        # L* X/ ?" y0 b. e; o. M" `. @
        TMOD &= 0x0F;                //设置定时器模式
: M  |0 w* B2 W. v/ Z  T        TMOD |= 0x10;                //设置定时器模式; r, O- r" n2 g; @! S0 U
        TL1 = 0xB0;                //设置定时初值+ T) E3 ^0 K: P
        TH1 = 0x3C;                //设置定时初值        
( C0 a8 |$ e" r+ ?6 U: _/ c        TR1 = 1;                //定时器1开始计时
5 I  N2 D$ \9 g& z# A' s# z; a        ET1 = 1;          //开定时器0中断
( k: R6 G) ~" r2 [) W}6 j' ^+ g; S! i
& C7 J# V1 i4 c$ k: H, u, b5 \
//-----------------------------------------------------------------------
. U) X, f7 Q  w//定时器0中断8 g, ~0 ]! I5 P) j
void zd0(void) interrupt 1                  " Y8 g( T) T& o( T
{
6 h$ G8 Q. f7 I; Z% [# v$ L        
0 |" k5 N* @, M3 H        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
9 l3 j3 l. r' ?1 F3 o' b: f3 x+ N        if(++ucCount >= 8)4 ?- Q4 X: _9 U  o" ^
        {# d4 p( {' l% d
                ucCount = 0;
1 Q  y3 s9 Q% ~$ @5 Y( s                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时6 N4 P# E8 s  x
        }$ f& n4 S' Z1 R; u" s2 |, e- X
        TL0 = 0;                //设置定时初值! d& h# q$ ^6 ^3 u# P
        TH0 = 0;                //设置定时初值
, S% }0 d2 q1 V3 F        : _/ c' u* _7 R# h0 l  z" L+ b
}
; q8 @6 _  M$ A- i: ]" ], c% d3 b! z  Z+ N& v. X, g

; X! |6 T, }7 L" X3 ^//定时器1中断 定时50ms
* [; ^# Y+ p) m. Jvoid tm1_isr() interrupt 3 using 1
' [- d; K) W/ v! a4 u( v{
4 _3 F/ Q: r! ^; l        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S
$ Q4 _; g1 ^4 e        static uchar uiCount = 1200;                                //                        = 1分钟               
; i6 V7 C7 u( {0 U        static uint uiCount_BeepTimer = DATA_BeepTimer;8 V& A$ L' ]! r, H6 F6 Q2 k
6 c1 q2 ]% O+ O* ~
        TL1 = 0xB0;                //设置定时初值
- V" a8 F& R5 m, Q/ i: O) f. x1 q; z9 ]( [        TH1 = 0x3C;                //设置定时初值
3 m8 v7 B( S$ ~  p
3 T. ]( S2 |1 c' o8 s! x) w% g! |        if (g_flagSwitch == isNo)
/ U3 x- ?3 M+ E/ @        {
( l0 p7 b0 \& Z' T8 [: G                if (count-- == 0)               //50ms * 200 -> 10s* I+ q9 v  F" m% j: _
                {
6 {  G* z. H; s1 i; t! k                        count = DATA_switchTime;6 J+ w! j- n, }7 Z; H7 s
                        g_flagSwitch = isYes;  q  \* ~$ x$ v
                        // TR1 = 0;+ {- Q' P5 c5 I, l% j/ n
                }1 F0 Y" y7 z* v+ @$ X  l
        }        & a* Y; O0 k& ^1 z6 H' _% a* a
        
% y# T/ S! E  B8 {/ ^        if(g_flagBeepTimer == isNo)
3 X$ }( G6 ~$ i; E) C        {
  s$ ^9 L5 Y  C" U                if (uiCount-- == 0)               //= 1分钟3 R: k8 |" T( d) O4 q% R
                {
  V; h: m# Y. `$ B3 X- g# p                        uiCount = 1200;3 }+ k4 i, V. S
                        if(uiCount_BeepTimer-- == 0)" h6 U& u3 J/ H2 n+ \; S7 p
                        {
, u2 R* P0 M4 w% w6 E" t$ V# Z                                uiCount_BeepTimer = DATA_BeepTimer;
/ a8 \/ N! M' c& h! V                                g_flagBeepTimer = isYes;- t. F& J1 {" |/ O- x7 J
                                // TR1 = 0;* A- X! |5 ~. H
                        }                        
  Z/ Q+ X  |" c                        " K" [" U. |. e! }
                }
9 h1 O: g) X, i' t* `& s$ |* O  C7 V) a
        }% T, U! Y8 y5 G! t0 N  I
}
2 I1 G9 _7 v; ]' t; l1 z
1 d0 o5 O: n, k1 ^- g//-----------------------------------------------1 _# Q/ Y1 k4 U4 L

1 y' ?( _3 |9 H8 A) @$ ]; M* J! Z' F/ _9 K1 w

' f3 Y8 x  R8 `" X# X  K; e& ?' G3 v* A1 {
& V, l  w4 C9 l7 l
//外部中断1* x9 G; h) l! F6 F5 C8 H1 N; @
void exint1() interrupt 2
# Y, D6 W; t) w- _0 Z# E# {{( x5 O8 |4 z) ]6 z; H. g
    EX1 = 0;                         //关闭当前中断
7 _- J% @& j; E, H4 [) O9 p- _        TR0 = 0;                           //关闭时器0
$ k9 m: Z# V: v        9 E) G1 D; i4 n
}# p8 i5 }/ \3 Z/ H
//-----------------------------------------------------------------------
( ~! {- V9 A, i) K# q- b
# U2 z! B3 F' F0 |! T//读LCD忙状态并等待忙状态结束! p# q$ y# a: r
void LCD_waitNotBusy(void)9 P2 D* D" @8 W% D. @/ E7 g, U
{
4 C6 Z7 q( f. M! e8 ~        IO_LCD_Data = 0xFF; 8 A" V8 X* ]+ K% E3 A, O0 N) O% X
        io_LCD_RS = 0;
! j) ]' G. j1 w        io_LCD_RW = 1;9 f4 h. F8 E9 W$ c
        io_LCD_E = 0;! n& x8 N& E& y) q) ^# D
        _nop_();/ w7 H* |, @' ~" u3 g
        _nop_();
. E& s! K7 T7 w# K" u/ K        io_LCD_E = 1;. d- m( H" P' P1 T2 R  V
        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙
9 v7 q9 e8 k  K: C0 M1 T  {}) V& O5 O0 I" h0 m  w
* J" A8 G' P* V
//给LCD写指令' P% q8 s* ^+ a$ }9 A7 D
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
/ \# @( Q2 R: C0 F$ b5 C  B{4 B& U$ J7 L. M" O8 W4 P
        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙$ O7 A& A8 p3 z2 A( Q- a. X* p9 y! Y
        IO_LCD_Data = command;
  z0 W) L% T: d: y( K/ J8 f' u        io_LCD_RS = 0;
% p/ q, s% L$ {% G: X( r7 w' l        io_LCD_RW = 0;          g( u7 J7 N# a- {' o5 _. g- C
        io_LCD_E = 0;
& ^3 ^. X( X8 M% f) V' D( X        _nop_();
. T. T6 ?% S& U4 r" l. c/ T! o- {        _nop_();5 i8 P# N* B% _. \$ _# b6 O
        io_LCD_E = 1;        % L& V/ V8 f- m) a$ k
}: l# l! C  @# l6 S9 b. ?, T; ^
) A1 _9 K6 U" r& i
//给LCD写数据
8 z1 j$ F4 n0 V8 M( Q* ?+ `0 Z/ \void LCDWriteData(uchar dat) : [8 s: J, ~! t9 t+ A
{
4 [9 f7 F1 ?' P: U* n# K        LCD_waitNotBusy(); //等到不忙  i5 ~5 N8 Q( _* W# P9 M3 v% K
        IO_LCD_Data = dat;
4 ^  L  l6 c  S6 S& B        io_LCD_RS = 1;
# v" V  U/ o* D: F. g0 T        io_LCD_RW = 0;
( `# ^+ f5 g, y' J* B9 ~1 y        io_LCD_E = 0;
4 {" Z6 k/ j$ R4 d! b        _nop_();/ K. B5 [% @, V. p. @" u
        _nop_();( O+ J( S, l4 a" c' {
        io_LCD_E = 1;
9 G  ]/ b( Q7 ]3 `}
% }! x( u; L* D6 [* I/ x: L
% R) |  z' ~& L" |1 q) S+ l) q; ^1 \* m. f5 P% R. `' N" t% P4 v& K
0 H& l8 R  n+ C1 f
. A% p  f( P1 P$ p! M/ ~2 |
// 初始化LCD1602液晶显示屏
4 R/ W: B/ V6 K0 ?6 Cvoid initLCD1602(void)
6 g' @7 y) {! J7 a{
* o* L3 o+ v* d        uchar        i;        
1 W7 A: O& l4 L  p* M        IO_LCD_Data = 0;                                                                // 数据端口清零( X3 @; m7 b) |4 N# ?6 c, [; l! m
        for(i = 0; i < 3; i++)                                                // 设置三次显示模式# B' u' w, K0 F' @8 p* R0 ^% ?: |
        {0 |3 o3 E  r; e' m! M
                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号
- s8 M/ _$ E, E& E* K3 _" x+ K                delay5ms();- X) X; l# d0 j. F6 T
        }5 n, k) Z% t- Z4 X- h
        
) n4 R% B0 O9 Q        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号
% c9 W- D! F5 w8 D        LCDWriteCommand(0x08,isReadBusy); // 关闭显示
1 M$ g" Y2 J6 H3 R        LCDWriteCommand(0x01,isReadBusy); // 显示清屏" f- Y" {. p! ]! C- n7 _2 d5 t
        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置$ j! [  N3 X$ S" x, k# x4 ~: U
        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置; f+ w& g+ l; z) c! ?
}
; a) h7 u' |3 k9 N
' b" U- [7 d6 D5 |) n# ]! Q3 ~3 ?0 d) c6 |0 Y
6 Y' d4 S) X" _9 L# t
//按指定位置显示一个字符
3 T  w3 P0 k- N/ w: Hvoid putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
( N! o* u+ w$ u{
5 T. y2 \4 K' y% S5 X- c9 w
0 |; y2 E. d& Y; u- v        line &= DATA_LineMax;
5 G% b- Z4 y8 m8 x6 Y8 j7 `        position &= DATA_PositionMax;
( m2 P% W' o( Q6 n5 K9 U5 L! d) k! O4 l        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;. e' O4 C$ R+ E$ i1 N7 h- \8 f( k
        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;) u/ W# @! J- C, ^3 g
        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址) h5 `( K2 {" R
        LCDWriteData(ucData);                                                                  //写入字符的数据        
  U( o: ~% l& R4 ~- F}
# x9 G3 @/ u3 f) R1 v$ }
  T4 v; \2 k7 q* m" K//按指定位置显示一串字符
, i" E% ]; C+ @" \6 h5 [void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)1 L8 l5 D9 f" x% l# H
{$ \/ U7 f& Q4 ?
        uchar i;
$ }5 n! A. K5 t. P' K  y& L        for(i = 0; i < count; i++)                                                        //连续显示单个字符) [' E/ Y( P: n
        {, Z0 U3 k9 P5 r  G$ a2 M
                putOneCharToLCD1602(line, position + i, ucData);        - i" c# Y9 M0 ^6 W5 D8 E
        }, X; q3 V$ C5 _8 i
}, c3 e( a9 i6 }" r% l9 S9 r$ D

" l0 z4 Y: i, H' Y0 L6 c
6 S5 Z1 [8 B' _: d! I  s% `; E//按指定位置连续显示三个字符(三位数字)7 ~$ c0 k$ i1 I- K" M+ h" n$ }
void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)9 l+ e0 G7 C  p" {6 m- r  E$ a7 F
{
+ \9 z9 A  E0 ]  e; M( C+ {        uiNumber %= 1000;) I* y6 k$ n( C% S/ u4 J  d
        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);; C. A, r+ g2 i% N4 u& c# q6 S; @
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
( S, \& y8 M# h+ ^2 t5 z% x        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        4 S0 W, `7 Q+ m( @- x
        
3 R% H% `3 E; I  i}
8 ]. y0 w/ |0 c        
9 y9 h  F. \. q3 z! B& \0 h* Q1 D/ ^4 }8 E1 ^+ F8 [; ]- C: m
8 }4 {! p6 ~% \4 o: x' H: F
// 按键检测子程序,有键按下返回键端口数据,无键返回0
. p: M8 M- e& [8 s, t6 X% luchar GetKey(void)7 f9 g2 ]3 ^- W
{        
4 @. _. L, X2 X3 r# |, V9 w    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        0 S! x. L0 E5 w* V; s/ Q
        . ~- w! u0 b: Y2 z. e1 v
        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空
4 t7 }6 d% S- @6 O: g4 k        {
% [- B! K" p, {+ ?5 J                uchar CountTemp = 0;4 T& z3 M& V  }
                do
% w- ~, u7 h: n) z1 N# i$ U                {
. Y% [3 q9 w; t4 M! I, L                        delay125us();
) `: W8 W2 q* K$ \7 B                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
/ {' q; X( B* Z5 {1 H& d' w' [7 d$ A                        0 ?+ e" ^) u4 l% X
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动
6 [0 d$ t9 Q1 ^               
( K! f; `9 F" ~; P; Q                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
( F$ `4 t8 G& @4 z9 @# }               
' n5 W; b$ }) p9 w, d8 ^& [+ b                return KeyTemp;        // 有键按下返回键端口数据! [, I* x  I4 F! j1 E$ @4 s- O, v
        }
" o( g7 ~" A0 A: n- m        
' e9 {; K. K1 `# N8 F2 X3 d' m        return 0;        // 无有效键返回0+ t( ]$ m  N9 b, P0 O) K9 j
}  E# O9 B  Z+ z$ ]: |

) M0 n3 ?0 u( d# V
2 h4 K6 x2 j; N9 u
5 ]$ Y7 c$ J/ x! e# C//加一
  d( z. g4 @8 \" \  }) c5 wuchar  INC_Number(uchar Number, uchar Min, uchar Max), F6 Y, k# ~& ]- t- J
{/ K  g% {( |4 I/ I" E5 g) L2 g
        if(Number >= Max) return Min; else return (++ Number);  D- b' O: t, x0 a0 V7 y" T% \0 n$ {
               
! w! ], N. z7 M$ t) g}+ L7 |+ N+ w# H7 a* j+ R4 `1 p

) g7 T8 v) _7 I! P, \8 z2 b+ r8 Y//减一0 v& N4 L' h1 S% T' W
uchar  DEC_Number(uchar Number, uchar Min, uchar Max)' V# u5 x5 d8 @" O! \) \
{9 k/ Y! g% m+ z
        if(Number <= Min) return Max; else return (-- Number);
  x1 U: Q9 s- `2 M/ E* I                  L  T0 W5 P/ k  ~1 y
}
& I4 m6 E+ i7 @. r& U8 m/ X, \3 W8 Y4 n" v/ C4 Q( u; f2 q
// 检测到有按键后 这里执行按键任务                        
* w! S2 w5 |" Ovoid execute_key_task(uchar ucKeyValue)        
0 Y$ J+ Z. {+ F% x! D: E" W{3 j' X8 X! ^, k' z" c2 ]
        uchar state = 0;                                                //定义调整数据的状态变量2 m8 U# g8 j0 o+ o( M% J* M, e
        uchar keyValue = 0;                                        //定义键值的临时变量
) \2 ^0 [9 C! @# B        
* V" {' O6 w, j) v+ ?1 A5 j        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出1 {* N( ]5 ?$ `0 R
        , ?6 Z. y7 R4 c5 ~9 O8 O1 T0 X8 M: c
        //是设置键继续-----------------------------------------------------
2 e+ D4 ^- H" k        3 Z" Q9 W+ z3 F5 z" G& b$ e' L: }
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT               
  D( G  L- T1 M& c9 B        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        : {+ g& F, T9 J
        6 N9 i1 O* y5 t* ?! e  u5 @
        while(1)8 N1 p$ Z+ o+ b3 B, T
        {- ~) i: b' ]/ [7 R4 D, U
                keyValue = GetKey();        
% O' g, W* f; z                if(keyValue == 0) continue;7 `8 T" p% K! d+ {: z& Q% L
                4 \' B2 r( x8 i7 p# D4 l6 l
                switch(keyValue)
# I, G, W8 G$ l8 I/ [  x" N                {- d" g- V6 @( y( T/ X" }' D2 V* A
                        case DATA_KEY_Set:( b  H9 A4 \! h. {( ]1 u% ~
                        {- G8 P* c% t4 D1 }2 G$ W
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出: m+ W% z  y+ M. N; G
                                switch(state)! H1 W+ H, }/ d: ]5 W" J) B% s) j, ?
                                {
; A2 k2 D# j2 ^5 I2 A) u                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面
8 C* S# W5 k3 u$ p0 \2 B2 O                                        {" [0 g! U% |: p! c5 H4 O) b" `
                                                state = 1;                                                7 o5 |) s) y( f9 T( w& g0 A
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
3 E. y- ?* E2 \, b' T                                        }
' ~. V0 X6 m" v) m9 F9 W6 F                                        break;
4 p; u7 k. t1 G                                        case 1:
8 w8 D4 \: |+ `+ f& ]                                        {
) A! W# b" x3 w: Q( o                                                uchar tempMax = uiD - DATA_uiD_Min;- o: F" {5 f# `& H# R. t# }' W
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                        ( x2 O; \! i5 {
                                                if(uiH > tempMax)
" z- r/ `4 O, _, W2 c" V# q                                                {
  J% P% `# x. |  w! W                                                        uiH = tempMax;5 B; k" |2 w; [: }* R! j/ T3 H4 P
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
3 U* J3 S+ ^7 e6 ], k) A  b                                                }
( b; b( G! W6 H& a1 r                                                else if(uiH < 2 + 2)- N* p, U4 |& l# e
                                                {0 m" d2 G; C1 o
                                                        uiH = 2 + 2;        
9 x. y# M/ o6 }# w; D0 u# S% U                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
. J; a! }+ A" E4 N+ I                                                }                                                        7 ]! t  c. f4 ~& P" p- }
                                                state = 2;3 t2 J7 z$ d: C: e7 d5 R) u( o* \
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
  \" F9 H/ ^! h& @  K                                        }5 F# k* ^/ b: x0 `& v2 |
                                        break;
. h. {& _1 g9 G/ C/ D                                        case 2:
  G( q" L+ J: k: v  e! Z1 S                                        {
! A" C8 o; R0 J$ j* U7 M; W" z; u. J                                                if(uiL > uiH - 2) 3 t1 V2 ^/ O: e! m( @" {
                                                {
5 x+ \% k1 a. x5 G. {) t                                                        uiL = uiH - 2;* }0 ^/ ~) s0 L4 Z3 E8 H/ F
                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);# h9 j1 z# K/ o$ ?  s% P0 \0 Y
                                                }6 J2 j0 O) K' p; i  U! a
                                                return;        6 W4 L8 Q! t  N3 o* ~
                                                7 l8 H1 b9 n) k" X+ e. O
                                        }7 L+ V* a6 D" i, |9 @; y5 b( B( v7 F
                                        break;
1 D$ c# ^6 k8 F/ t                                }
5 c4 o5 e! O- o$ ?& `6 N                                
) Q: z# `) e) }& V/ o+ M6 ~1 f                        }$ y3 [. l8 K. A6 h4 Z
                        break;2 m+ w' {) x* D& Z! ^6 n. \
                        // 如果按的是增加键,改变相应数据并显示
1 H6 V; R6 d, I$ l2 g1 h                        case DATA_KEY_INC:
4 |9 w( d) o" m/ y1 Y# f- m4 A                        {' F/ E/ ?% `- D1 h( v
                                switch(state)
+ Z. t6 X7 C% @                                {  [( N, J* }9 J8 R+ {6 G- v2 t
                                        case 0:
# E3 P3 ^: y( y                                        {
4 t  w" U+ {8 h% J                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);% S( N5 V5 j3 f6 T
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        
3 H6 w- J1 b5 I7 d9 ^% s  a% L  s+ J+ p                                        }0 ^' `( b/ R. _2 U2 ^
                                        break;. c  K$ `5 t: B# z: P, L, s
                                        case 1:% V6 K1 ^3 |& b" v  J7 J
                                        {
, X6 q( n5 {; [/ ?- ~- m( T                                                uchar tempMax = uiD - DATA_uiD_Min;
: g; G: \5 ~5 G2 H8 R                                                if(tempMax < 2 + 2) tempMax = 2 + 2;+ R2 j% ]& ^+ U; ]
                                                uiH = INC_Number(uiH, 2, tempMax);                                                0 a9 E" a* L- G1 n
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
7 M3 n2 L; P6 \" D                                        }
  y! g% }4 [9 Z) I  E1 o                                        break;
. A0 U, i/ |9 r                                        case 2:
6 S* f' ]3 a' {4 U2 L                                        {8 P/ ?, B) I7 Q: G' Y* D5 B& a8 P
                                                uiL = INC_Number(uiL, 0, uiH - 2);        % t7 F9 x+ k2 T! A5 n
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        / K" _8 ~7 g4 ^7 Q2 P+ O
                                        }" o6 I- @/ n  d2 ~1 f8 L
                                        break;
8 |! j& M  {7 t  b! a  ?                                }) w3 D2 g- o. g; z. I, ?! K
                                ) `: u% b2 R* w3 t, ?6 L6 m
                        }
) }( `1 c9 c! ~  W                        break;
  g* s5 Z6 Z- F4 C+ |                        // 如果按的是减少键,改变相应数据并显示
) K, E8 R9 ?* B7 Q2 D. Z                        case DATA_KEY_DEC:1 g1 A# [" D4 Z# x* U/ l# x* L
                        {
: @( N$ ]4 C5 m/ C& t                                switch(state)2 d) o( h3 ~# z6 l: y( C1 I
                                {% R; `1 ?. `6 w5 b
                                        case 0:/ i! n3 b. o, Y2 N7 b
                                        {
: E7 Z0 ~$ V& Q: H* K* q                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                       
, N; x. L" v2 H                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);/ V; d. T& q5 H+ [+ Y7 U9 \' I
                                        }
  d7 {+ [* f8 h6 m# k7 h                                        break;: V( x% g7 y0 P) `9 j' t, {" B7 x' H
                                        case 1:! A  o) n' b0 \# D; B
                                        {* e8 F( M& R2 y/ f5 E
                                                uchar tempMax = uiD - DATA_uiD_Min;: Y  L/ K" q& X7 i9 K9 G6 w  L
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
4 m/ R  O; @/ T- Z% m                                                uiH = DEC_Number(uiH, 2, tempMax);                                                # B/ h# [8 T/ k- r
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
) W( l5 E+ B2 \. b! W
1 A; P# Y" x( H# x. }                                        }
+ O' w& _" y+ n8 [$ ?                                        break;
( u; b1 p+ U- z# I+ g; @7 ]                                        case 2:
8 m; l5 ^0 q6 z6 n                                        {
: ?  R" M- h: w                                                uiL = DEC_Number(uiL, 0, uiH - 2);        , f3 ~$ L7 B3 ]/ x( D0 Z3 c4 Q2 k
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        9 b6 f* D9 b7 G8 r2 o. S

0 X6 g: }. K+ T, @% F' V                                        }
9 s4 d) `& Z' K& Z                                        break;. h$ V! C1 C8 D' B1 @: L
                                }) u& W  i' G% r4 G& C2 M
                                
; l% g7 [9 |# M$ i! O                        }0 z( N- S( v. X3 O: s
                        break;
& R  C, V9 f5 t( K                        
  T! g2 [# w3 m. m* N                }2 J3 W; K9 X! p
               
2 a) L3 c2 c: P& U2 m- ?: B        }, }; q0 k" b! h5 U# L' r" s! i3 {
        6 i# D9 m2 V0 J5 Z! O! ?' q" e
}
5 i; p- m& Q/ k& a7 q% U1 g$ D: j2 s4 W/ c* J) h. L
" }2 I9 [3 a3 z0 ]8 B. I5 d& L/ O

0 |: S9 D' }! j  H& H; H5 G8 p// 蜂鸣器        5 C* D3 X% F, A" c; w5 L
void        buzzerCall(void)  ?! \% W: ~$ C
{
2 i( f6 ]1 o8 H. l/ ]) E8 n        uchar        i;$ v' Z2 T" f, L5 U3 g9 S8 Y
        
* V9 y: C% b! h3 [                for(i = 0; i < 90; i++)8 S. Q! g0 C5 [+ i
                {
# T  J  l* Q0 q3 t1 Z' D, e0 T                        io_Buzzer = 0;6 v- h. w1 ]2 g4 h
                        delay100us();
5 J! G0 s4 f4 e- _. J* I8 f& q; B                        io_Buzzer = 1;5 k- L$ m$ u. h7 c1 x
                        delay100us();( r5 u5 ?; i: u. N/ H
                        delay100us();               
" [& l; y# o  W                }8 M* S. r# w+ H  T9 x6 b" \
                delay100us();        
) k8 d2 e# y% t" ]( }                delay100us();        
5 d6 o! c4 f0 W' d% f}
% K/ Z# m& r% ~% O  ^; c# E$ M' M" E! D( ~5 K
//计算水位7 G, t; b! U/ w; z7 `  u
bool CalculatedWaterLevel(void)
& t! m+ I" R( M9 S2 B* `{
& R& U9 Q! A  S: b1 C, N4 m        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置
' a3 [) H- i# N6 U2 X6 m        uint          uiTime;                                                //声波传播时间2 x, X7 c) _0 |- T$ y
        ulong         ulDis;                                                //实时测量到距离        
2 Y7 \- x- D* }" f) A& V, L        # H% [9 ]7 T" I$ ~4 s) L
        uiTime = TH0 << 8 | TL0;        % S- ]& t" m# {; S: o! V; v
        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
: W: i( A  p# w8 \3 U        
2 w; e6 J' z' F7 M3 J+ F        TH0 = 0;
! ^. O1 y: d+ N7 c) e; V+ L        TL0 = 0;        
; }0 A$ i7 I& ]6 \/ k$ E# z& @        
; J0 x: h, d0 L$ ]        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;
" u4 t6 m! K9 F" i5 Y        {         % \8 H6 o/ v+ P4 ]& o
                g_flag = isNo;               
% i* b; Y9 w1 E, v6 V1 G! ^                TR0 = 0;
) l$ A/ L% r! T% M6 Q                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 2 q& P3 [6 _9 }) y" w& Q
               
8 _; O; v' W$ u* M4 K* x1 A                //阀门动作:               
9 z6 v1 a2 Y- j; p4 R                // if(g_flagSwitch == isYes)
( M4 m1 K7 |9 f+ P% }                // {               
$ v( V+ }1 r2 T- p- S+ {                        // io_Control_Inlet = isio_Control_Inlet_OFF;               
3 N* P: K# I! z6 S" x$ }                        // io_Control_Outlet = isio_Control_Outlet_ON;$ Y7 `, G) P& y
                        // g_flagSwitch = isNo;
: n4 G* w5 r( E1 @7 S2 n. D; A                // }               
6 i! g' `' S% G% a  p2 H6 y                ) c: ~9 N( {7 \) A$ \5 _/ ~: `
                //指示灯:( X( x! }3 D7 O  J$ C
                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
/ p- U8 M5 c( [, ~                ioLed_Green = ! ioLed_Green;
1 T5 c9 e, L% s/ B+ c                ioLed_Yellow = ! ioLed_Yellow;
, y9 `2 ~& E& h# _" r8 S% {  @                + L! ]# B' J, r- |- [
                // 蜂鸣器叫:        
/ t" E! |8 j" R2 e: \                if(buzzerCallFlag == isCall)
) i; A6 r( `' E- {) r                {. ^* u/ I2 R5 ~% r: F. q
                        buzzerCall();                                        // 蜂鸣器叫        
: k; m' b3 p$ r9 |% S$ @                }
4 S7 E# Z; R6 ~! {0 s2 U% W               
- b; F$ h. X$ r5 m; B                return isNo;                                                                        // 返回错误信息
/ g6 D0 p) b4 p        }
7 }+ b$ z( Z  _# i( |        else
$ I8 W: t$ u, f' ^% g9 O  U        {
1 Y6 K- ^9 G2 O" W0 f. B                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离
% d! O& i' ]* d+ r8 j1 q# ^4 e                0 k# M0 q8 M( q+ H
                if(ulDis > uiH)                                                // 如果水位超高
3 A( ~. b8 `/ ~4 i                {
; U& ?3 n, q  i7 b, F                        * @0 q3 B6 c9 d! I! m
                        //阀门动作:
, ]9 M# Y% e$ o3 D' J2 ^& j& ]                        io_Control_Inlet = isio_Control_Inlet_OFF;
' o# |, }6 w' R, m/ w/ O                        io_Control_Outlet = isio_Control_Outlet_ON;        
3 F+ K0 _* H2 s, T                        g_flagSwitch = isNo;& ~4 H  ^1 \4 f+ U, K4 S
                        
, a  z' H  g( \9 \. Q                        //指示灯:8 B' l, N5 @+ {$ x: \: |% c
                        ioLed_Red = ! ioLed_Red;                        // 红灯闪
. E5 O1 s  S% @5 a7 `                        ioLed_Green = isLedOFF;               
  T8 Y/ r8 I" H# g! L. ?                        ioLed_Yellow = isLedOFF;                                
% |5 ]% Y& u1 M( \8 J& p                        // 蜂鸣器叫:
$ e. J, X+ p" V/ a$ p0 m8 Y1 o& r                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警( `( P( Z# a/ I/ ~" F$ n5 q
                        {
9 @9 C3 R* e2 l9 R' @# q                                buzzerCall();                                        // 蜂鸣器叫+ F, w/ N6 g9 G, _( b/ Q
                        }% b+ Z2 `0 N  t8 a. K2 w1 G8 t
                        
, j; @0 r+ ^) W, t7 t& r                }
6 j/ U/ S( Q4 a# T% ~# ^  e! {/ }                else if(ulDis < uiL)                                        // 如果水位超低
3 O( r6 b  r7 C5 T+ S: h                {& A1 ~5 }. A+ k& J& ]  g- o
                        //阀门动作:        
8 a* h' e" A  Q3 G                        if(g_flagSwitch == isYes)$ ~* g, X+ c, A# J9 S7 C$ N
                        {                8 s5 k0 y; M- e' |
                                io_Control_Outlet = isio_Control_Outlet_OFF;        
5 `& U$ T7 w5 c                                io_Control_Inlet = isio_Control_Inlet_ON;        % K2 \* g: k8 X% c
                                g_flagSwitch = isNo;
- e, n7 D# a' M5 E  `6 _                        }        
: ^- B# j+ @  Q1 j' j# Z, |                        
& y2 w: k- ?5 |" x                        //指示灯:$ U' H. U5 c9 w* ?2 W/ H0 a
                        ioLed_Red = isLedOFF;
4 ~6 {$ T7 R- W+ ]% g+ G                        ioLed_Green = isLedOFF;8 k8 p. C- T; X" w+ P+ J
                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪* G7 J0 }! R! t# C4 [
                        // 蜂鸣器叫:                                                
. d3 O. `( ^1 h0 k& M                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警- s( `4 z% ]% Z$ e* J
                        {- w! J+ A  l' p2 I  p9 V7 {0 u. I
                                buzzerCall();                                        // 蜂鸣器叫* K) k- O+ U- z& W- I; R( B' l
                        }6 v' L# [  I  Q( s* o8 Q
                        
% I4 h' u( b3 F' Y                        
3 e$ A$ G2 o, e7 Y9 g# h                }
0 _0 t% }, T+ c6 c! c6 U2 m                else                                                                // 水位在正常范围 ( h$ {# N$ T5 u1 @: J% I
                {        : z9 C+ I; s& J' g  P
                        ioLed_Red = isLedOFF;/ b) i9 m- n- ]0 T# [- }
                        ioLed_Green = ! ioLed_Green;6 I- y$ B6 u# W8 [$ O
                        ioLed_Yellow = isLedOFF;        : r5 J+ }: a. o
                        
: C9 h2 q( [/ ?7 N                }
8 v/ t5 q0 _/ ]/ J                putThreeCharToLCD1602(lineTow, i, ulDis);
$ Q. {  P6 a! t. o; x                return isYes;        
7 |0 ~& N1 E& }% {                0 C7 Q/ v7 A: |% ]0 G# `# O9 m% Y
        }( ~' E" e! v' X+ O
        return isYes;: Z4 \( s# n- S
}
* Z# T9 [0 z" ?2 ]% @, m8 T: c9 ^, S
/*********************************************************/
& a" q( [/ y+ R" evoid main(void)- h6 ?0 b& ~% q- [' ], U7 H$ }
{
0 _2 n+ V" K% R. |        initIO();                        //初始化IO端口        % k4 r1 B. d/ o. y; v
        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        , @5 D5 v1 D; B0 o
        initLCD1602();         //LCD初始化        
3 g" L/ u2 h* v) x' ^/ R        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D, {8 ^( c) M& u3 s
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值# ?- J5 x. O( F+ }( C! y
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H
8 `9 K  m0 Z  J# E- }        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值# J+ B0 d7 G# _
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L9 R6 \. N7 u! C3 L5 K8 W
        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值
4 O2 O9 Z$ P# i/ ?6 B        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C/ O# x  R0 W8 p- U/ y! v/ E+ A
          k* K: Q# @# V: ]8 |9 K& _! |
        initTimer0();                //初始化定时器02 p( C6 T% q) }. V# s% Z
        initTimer1();
2 i3 y3 D: v' x1 M        
2 n( p, I. G1 `        //阀门动作:初始先排水$ q- Z# d2 s8 L" ?7 w: G
        io_Control_Inlet = isio_Control_Inlet_OFF;        
, {2 H/ {2 F. j$ f$ w. l        io_Control_Outlet = isio_Control_Outlet_ON;
/ m4 W  d: a2 \0 B$ R8 ?        g_flagSwitch = isNo;        
& y" U4 d# Z- r. K" e9 v5 f        0 K8 O) a0 P0 `- j
        while(1)4 @) ~0 K5 O% e" o2 W7 c0 n7 g
        {
1 s0 ?3 I4 g, h6 J5 i( E                io_US_TX = 1;                                //启动超声波模块信号' h7 z; C: B+ u# _8 Y8 \8 H( Z- z* p- d
                delay10us();
8 x% E; P% v) R                io_US_TX = 0;
" H( G5 j5 U1 m               
9 F3 f" X# y6 o  J3 ~/ q                while(io_US_RX == 0);                        //等待计时开始
1 a) l  a. f* Q) [; y+ m                TR0 = 1;                                                    //开启定时器0,计时开始        ) [0 X) ^) ]6 m
                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
3 E! t5 f. f% {                EX1 = 1;                        //使能外中断INT1               
4 d2 c0 n' q/ D7 e4 g# v5 G# A4 ]: d               
8 g2 M6 v0 `2 V& |: q) r                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        - M: H3 U' F" s' B/ b8 R
                {
6 B3 |7 h* x, I; T9 T3 Z                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
2 r- v0 K* [9 M' P5 `                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
$ U$ w) }, P- n( H! e                }
8 r- n, w; c) m4 W% s: ^/ g                " W8 `  G, Z- B! c5 [- y; x: |
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环                " J. w* N2 q0 ~0 u
               
. L5 M4 Q# c6 S4 _/ e; @* P                TR0 = 0;                //暂时关闭定时器0
! [5 b( _" [! K* o5 z                //清零定时器和计数变量以及标志2 A3 X! D/ Q: p  y. ]
                TL0 = 0;                % j. I9 E6 @5 t) K  Y% P
                TH0 = 0;               
' f9 g2 [6 {1 p* v4 `                g_flag = isNo;
5 \2 x- X( M6 X1 q1 V                ucCount = 0;. {1 q! q  P& C  R
                g_flag05s = isNo;  d) J! S9 f! m7 M1 I
               
; D1 h5 H" K* s                TR0 = 1;                //打开定时器0                                       
4 H& a- ~* @* l) T: j0 T                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果
+ Z8 L9 c% D2 h8 x, R$ I                {                        ( m1 R& {6 {0 b* m; @# B/ |; Y
                        uchar ucKeyValue = GetKey();
4 t  {4 R7 U7 w' c' x                        if(ucKeyValue)
% A4 m7 `7 ^! @1 _7 M7 Y: u$ h                        {; U8 V; o% }8 H
                                if(ucKeyValue == DATA_KEY_DEC). A+ s8 J0 u% I$ T* K+ b5 ~
                                {6 _' ]1 P' e. j3 I/ l& h
                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志5 I# f3 v1 X' m$ D
                                }
! ~- K6 y" P+ p7 a2 `
7 o' H: @, m% A8 v4 S                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        ) L! ~+ p& e/ {8 J
                        }                                
9 D0 }$ S3 h% W$ k' `8 ^' f- A) K: j& p- r+ V7 u- P
                }        ( S. Y9 A' _- A: A4 g
                TR0 = 0;                //暂时关闭定时器0
- f8 X% h3 @* ?                //清零定时器和复位标志
' @. D4 r8 r/ B) t) C  U0 C+ n                TL0 = 0;        
/ F  G/ O* q! e/ ]: [                TH0 = 0;          D) t, D7 l1 L9 f' ^
                g_flag = isNo;                # R/ K, U& `; f3 y2 H* E6 c1 ?
                , n: _; H% X" P% ^. ^
                //-----------------------------------) f. a4 j$ t& P5 A
                //水箱清洗提示:* x, c: i1 d+ d& d! d+ N8 T
               
& F1 w. \0 k2 l; e                if(g_flagBeepTimer == isYes)
) I% b! j# N# e0 L$ h4 b# B" I' Z; K                {
% |; x# R2 ~$ T: O2 D$ s: L                        buzzerCall();               
3 O$ }& D) J3 m" F                        //用减小按键取消报警标志
0 ]- Q0 @: H& c& U$ e                        ' X- F) I% o5 i
                }& J( ?  ?( L" g
                //-----------------------------------
0 v4 L" U8 N/ y) L               
$ y1 f) U' v$ V" M        }
/ _# C  ^4 e6 K# ~3 g4 A( O% B}
, [  Y2 o1 ~( D( p9 t9 {; \, @  v/ T- [" D' d& m
; Q: J( ?1 v! Y* l  }9 {7 m. ^! q
#ifndef __MAIN_H__) a" @# }; m4 S9 z% j8 p
#define __MAIN_H__
+ ^2 ^5 t, Y  o* O( w! _# s+ E: l, O' w2 |: g; i6 G
//-----------------------------------------------) A' S8 Q. |% c3 M: Q
typedef unsigned char         uchar;        //为了方便书写定义别名7 W5 R5 M  g- R5 W5 a( ^6 x6 ]! H! z. b$ X
typedef unsigned int         uint;8 x  O+ v3 ~: y/ }% Y
typedef unsigned long         ulong;) M/ ~' V! s" \+ l" R& `! O2 Q$ q% d
typedef        bit                                bool;7 U; b9 E' q: y/ a& Z0 m+ ]( }- h
* E/ Z% U4 l7 @, f8 }8 R4 y
sbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口4 `4 o  I+ O* Q4 L, B0 U% i6 C. R
#define        isio_Control_Inlet_ON         0! p( R0 E0 b8 J7 h; ^8 Q7 X' q
#define        isio_Control_Inlet_OFF         18 H  V' U3 \( F( H& l
6 N& C7 v3 o/ E' X
sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口( o- M$ [2 h" m1 ?1 ]! I
#define        isio_Control_Outlet_ON         0
4 Z/ a7 |* V5 ~- |- Q+ ~2 U#define        isio_Control_Outlet_OFF         15 g7 Q2 [' O% J. T8 ]1 R" `
" x3 [. P+ Y/ d9 U1 e6 L
#define         isYes                1
+ {; A9 D. q! ?, W; H#define        isNo                0, {0 B6 P( W% ]/ ^; H
//----------------------------------------------------
$ A1 U( z" P4 ^//定义超声波模块引脚
" C% o; c7 y1 C& ^* Z. h7 H3 Jsbit         io_US_RX          =        P3 ^ 3;        8 J& T  W$ Q% P
sbit         io_US_TX          =        P3 ^ 2;
6 y; H/ H* S: I6 h//----------------------------------------------------( w8 A. i( v# ^+ k/ l
//定义LCD引脚) H# a; R8 x* }
sbit         io_LCD_RW          =        P3 ^ 6; ( v+ E4 T  K- y6 u" a. j
sbit         io_LCD_RS          =        P3 ^ 7;
" e/ K8 F# m6 }$ J9 \sbit         io_LCD_E           =        P3 ^ 5;            
: j4 z' n' ]6 H/ e  y+ a#define          IO_LCD_Data                  P2: x5 W( `" x$ l0 _
#define         lineOne                        0
! K% m2 e$ P. F#define         lineTow                        1
/ o5 \' @, ~) _4 c: y- _8 e- I# T$ i# |* Z4 a" a' E5 j
#define        isReadBusy        1
, [' ]- T  L1 h- h9 S#define        isNotReadBusy        0
/ a* X% h( r4 F3 d8 [: D: A2 m+ }- a( x( v
#define        DATA_LineMax                0x01                //LCD最大的行索引数" ]9 E! c0 W) Q$ H' v  o# N
#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置
- F( v, Z1 p( x4 ]#define        DATA_LineTow                0x01                //LCD第二行的索引值8 x" j+ i4 ~& {/ i5 p+ v7 l
//-------------------------------------------
9 A; J& I0 R4 E0 p2 u4 S( B#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时" A6 [( Q+ }! z- A% R2 I# P
//-------------------------------------------------
& |% w# w* q+ S// 定义指示灯端口
5 u( L7 x2 x  \% R1 l4 z2 Esbit        ioLed_Red = P1 ^ 3;$ m* B8 g8 i. l6 s6 Z  {/ y$ }
sbit        ioLed_Green = P1 ^ 2;
1 Q& L7 f9 r+ T, \2 _: Csbit        ioLed_Yellow = P1 ^ 1;
3 G1 Y2 N0 V4 k
* j# B+ r2 c; T$ h+ }1 U2 k#define        isLedOFF                1                        // 关闭LED5 l1 E; S1 O' Y" m% Z* c6 y( o
#define        isLedON                0                        // 点亮LED) |: X: g+ a: W/ j% l% w
//---------------------------------------------: j5 J% @* S* s& ?1 T' v* e& |5 k
//定义按键端口! Y  V6 u: A, p  W* W8 {
#define        IO_KEY                                P1        " P0 B! _0 q2 `
" h5 z5 M  b  @# a' {, e
#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据
1 h4 f! M3 F+ Z8 [* U% b, g#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据. j7 y  H4 ^6 t, q% R% i1 ^6 S
, \. L( y; i, V  b
#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据' t% i  ~8 w, z
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据" k2 r% Z- o, `" O8 N, B3 Q
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据. V: M/ M. Q. _) _8 n' f
//---------------------------------------------: R7 G: l. e  [% t, a. A. k6 g- a
//定义蜂鸣器端口
9 s1 x7 E5 `! `( [8 h* _" [sbit        io_Buzzer        =        P1 ^ 0;        ) r' T3 L3 t' E# P6 x
//---------------------------------------------) ], Z5 _' N5 ]
//定义检测探头到水库底部的设定距离范围 程序.jpg
7 K/ w5 D! v3 T' _% R#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
' U! K2 R5 f5 k: z#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm
' h3 z" [5 d* r% O5 o$ ?% l
7 O  f1 L1 o& P% j#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
9 _: j; \7 x* Y' F#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)( O7 q. h9 }  ~2 ]3 s7 t# E
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
; ^; u7 Q  ^- A1 F" J2 ~5 t0 Q4 J1 I, E
sbit        buzzerCallFlag = P3 ^ 4;/ d/ z. G* s5 Z
#define        isCall        0
% N9 a' O) @$ C' o* u#endif
# Y& O, ?$ ~  w$ F& k# K* J( P; n9 q
1 z8 G5 @( X+ t* w  X. \' W+ j3 K
8 k+ }1 w6 S$ q1 g3 Z1 g7 M5 G# T. c% A7 S( V
$ B5 H0 u) ]3 S0 C& {+ H

基于单片机超声波液位控制器设计.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 U5 U: b4 q* d% R. o/***************************************************************- }6 Y% s; A" S9 ~
        名称:基于51单片机的超声波水位 ...
$ H' J( v$ ?! F6 M& Z
又下载一次,打开跟你内容不一样?7 ?: G+ K" W# k' z% M6 s
QQ截图20201211202119.png
回复

使用道具 举报

 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05# Y0 O5 k5 B- ^
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

" t; ~# o0 w# d+ S& S- {' l是的、是物体都可以检测到!
: q! m/ l3 m! E" U0 w& W: f; \( a
回复

使用道具 举报

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

使用道具 举报

本版积分规则

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

GMT+8, 2025-8-20 08:58 , Processed in 0.043647 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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