一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3866|回复: 7

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑
& ^- K) w) O( Z. D1 v5 v0 \* k4 u! W) f
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

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

, L0 C! j& s  `0 ^. y" C
按键功能分别为:设置键 增加键 减小键 复位键

8 h6 ?8 r! ?& t7 p8 K
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)

) E2 u# n6 b- u: K# W7 m
发表于 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 编辑 2 y/ `6 _8 Q( L7 v1 Z% P, D# I2 `) L( r
tdc31224 发表于 2020-11-24 20:58
7 G+ z2 Z! `7 ?" e* b) P, i没程序?
7 Y* z# C$ N4 M' O! M& L$ m

0 {+ Z! a& \3 |- f, y* R/***************************************************************
" R% X/ O1 u7 G8 l* y9 K- z        名称:基于51单片机的超声波水位监测报警系统/ \2 I# C' i+ t) x, L6 W1 U
        单片机型号:AT89C51
; d& P3 Z2 f) G        单片机设置:时钟12T,晶体12MHZ
! M  |- J$ F+ }4 i        注:修改增加水泵控制和排水控制,即双继电器* N: j2 P* E% }
***************************************************************// K0 w, z2 C6 }
+ b# H" s- c1 }6 Q: N9 E
#include <reg51.h>: \+ V4 w, G* F& W# k% U' n7 B/ C
#include <intrins.h>                // 包含循环移位:_cror_
- u: M# e6 n0 B* {#include "main.h"     
# n; d# L& p. ~3 U//----------------------------------------------------------------------
! X; C9 t$ K1 ~" [) n
  Q5 d# B: l# zuchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};- p' r5 G. r& V& g4 J  |
1 A5 l" g/ X5 {7 U1 N, b
bool        g_flag = isNo;                //用于标记超时(65.536ms)           
# |6 n6 K8 s' e7 |) cbool        g_flag05s = isNo;        //用于标记0.52秒  7 S2 R) A8 `1 u" b5 R( J; [2 Q$ p
uchar         ucCount = 0;                        //用于计数0.52秒     
7 }" r( ]# Q) o6 C, i
0 Y+ G* c* p; j( g4 H0 H7 m: Buint        uiH =  86;                        //设定的最高报警水位 H# K  l* [8 J3 a1 b
uint        uiL =  73;                        //设定的最低报警水位 L5 p6 G- h7 r: x' G# `2 j" `
uint        uiD =156;                         //检测探头到水库底部的距离 D 0 Z+ Y# s8 a1 q& \. i( O
. {8 s* d6 ?6 @4 }
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志
( F8 y: [% Q. g' [6 B1 e: k' R8 ubool        g_flagBeepTimer = isNo;        //定时提醒标志
9 _2 q- o" s: N9 w* x               
  G9 u; v$ J2 O$ v. d' t5 y% o/ A7 ^! G$ J
//-----------------------------------------------------------------------' a6 Y. L* ]; m% H) h! ]: `: c
// 延时10us+ |' w3 I% g1 e  ~* g% e
void delay10us(void)                //@12MHz
1 L* K7 _% y" N+ \{* H7 [% {& G/ K! \6 G$ z
        unsigned char i;
; ^( L4 C% ]1 q2 C; C0 |  [  q5 w, Y7 ^
        _nop_();
: s( N; c) d" N5 W2 [$ R5 ~1 {+ J0 _        i = 2;
8 D$ ^0 a$ @9 e; j        while (--i);
. X8 \! S: O* t}
( q3 T6 A. g( L0 Y' p# W) k
) D0 U4 @1 \2 m- {# Q// 延时100us2 b& g  x# v1 E9 |  @* t
void delay100us(void)                //@12MHz2 d( J' L9 _/ Q8 a" W$ Z9 e
{
" t: H! y# d/ W; p        uchar i;
1 p. H% E5 M/ V+ q, C: J. r4 _$ W; U
        _nop_();
' ?4 o/ n' z6 T' Y% X$ n        i = 47;$ s- W. `* J& M# l, _2 B7 A$ A
        while (--i);5 g( o, b7 E/ h, L: Q; u* a/ [* d3 g
}
3 S) w* E1 Y+ E2 h5 i2 p
2 P) C- U$ p8 T% j8 q7 |// 延时125us: w- t* H! b4 X! e& w
void delay125us(void)                //@12MHz9 ~& \# a0 E7 W
{
7 u; [4 ~% o* G1 v: Y, @        unsigned char i;
. c- J* v. a% A) n  G/ {' G* u+ ^) Y        i = 60;
  ^+ J/ ]0 o! r6 L        while (--i);' N6 h1 q) p3 b! e) }7 R
}. t- Z7 m% K4 F6 R( D
' o  ^, M: v3 p, P8 w
// 延时5ms
3 v3 y/ m9 R  E9 [void delay5ms(void)                //@12.000MHz
- v9 o+ ]% B7 A. S' }6 l{. s$ z) W3 C6 B( y$ S
        unsigned char i, j;
+ x# K  t# H1 W( v' S" I, ^" d$ `( e" M4 e' o2 T* |' N4 t+ l
        i = 10;$ A' O# K# P, G4 L
        j = 183;
) C' a. v& C) k+ y, J        do4 s2 D7 s6 X0 U" n
        {
( C) V: c; Y! {9 A+ f4 p2 ~1 G                while (--j);
9 d& Q& G. c' n$ M8 a" }        } while (--i);6 \; |) S! G9 [7 e. I; Z2 J$ F5 a
}
  o- P" v. N$ F) K
: h. s, q( v% T2 C/ D# }1 I6 w" m// 延时500ms: K- t% j/ N. z- W. O) Y* }0 u1 m( h
void delay500ms(void)                //@12MHz: w2 F) A) v; s/ F) e. T& i
{
7 `. w, x; [( H% r4 ?+ W        unsigned char i, j, k;8 Z; @% p$ t+ v! b! d$ t
5 Q  I& f' F% k% D
        _nop_();
* R5 w) d( a4 X6 T        i = 4;5 t0 Z0 e' W, e  y# r7 x( m
        j = 205;7 R. t4 l( Z- F
        k = 187;
( ^1 u9 Z1 q% v2 W9 C        do
0 E& q. c7 w! N( {# C$ L        {6 ~9 n0 i7 s9 Z5 d( R' \
                do- w# u, N: w% Z! q+ j, Y
                {
, [5 ~  v, B4 j4 p3 J$ n( m$ ~                        while (--k);2 ?( w8 E/ g; o* H# G( H
                } while (--j);
$ D) c3 s6 Q2 v. c  T        } while (--i);# K* Y& F/ h; P1 L* _; B0 J
}
8 ?7 r& t& }5 n. e0 W! h3 `% g. L. X  r! w$ D: g, G
//-----------------------------------------------------------------------" c& f# N( x$ ~# v" {: B% \
//初始化IO端口                        7 ~( b( w5 y3 s$ |9 f2 R
void initIO(void)                                        - S2 h6 K6 J% r' F
{. z, O, M: u$ |- o
        P0 = 0xff;
# g) }& E% _$ {( ?        P1 = 0xff;
2 ]8 U" ]9 N4 |' D: R        P2 = 0xff;' Y: S' H& c, _6 b1 Q
        P3 = 0xff;6 W4 \/ y5 m# t1 H' P. R' a
}& J7 }* z0 }: f, k7 M, q
! i4 W& Z4 B3 }3 T# Q; n
// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz
1 w5 S$ B3 X2 G& H6 mvoid initTimer0(void)               
6 F9 u( q5 p2 t{
" V  J3 i9 V* t* F6 {2 M        TMOD &= 0xF0;                //设置定时器模式' G) K# m4 x9 h# Z1 w( j
        TMOD |= 0x01;                //设置定时器模式) K* i: g8 k; G, C# L
        TL0 = 0;                                //定时器初值清零
8 z( ~- `' {8 a        TH0 = 0;                                //定时器初值清零% }! {" ]9 d) @
        //TR0 = 1;                           //开定时器0# j$ c% A) k5 H
    ET0 = 1;                          //开定时器0中断
) E! I2 N- K0 D6 v! N, _4 U4 @$ ]    EA = 1;                             //开总中断            
8 K0 p5 x; h( A        ; _5 B: k/ j' G, N; K
}
  y0 @) x! l1 W8 [( A$ ~6 X! x/ b  Y3 }6 i3 N4 |
// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz1 d# X! z% J7 M. t1 e7 T
void initTimer1(void)                //50毫秒@12.000MHz
6 a; P( B/ L# h, c1 F' D/ h{        $ ^- [, ~# f* j: [4 `
        TMOD &= 0x0F;                //设置定时器模式& J: w/ @1 Z7 w6 x; U0 b9 ~) P
        TMOD |= 0x10;                //设置定时器模式. M' g! o$ _, j
        TL1 = 0xB0;                //设置定时初值
+ [! }: ]; E! h* i9 `8 @" Z, f        TH1 = 0x3C;                //设置定时初值        
+ M' _+ ~: s( z5 m3 R! \! x$ q; U        TR1 = 1;                //定时器1开始计时
  D6 E) F6 O# t" ?0 F% s( N. X        ET1 = 1;          //开定时器0中断
, o& r0 E: `+ a/ E8 L7 a}; o3 }* J" j. x, `. w' u# p
1 M+ b' J$ Q* A& T; ^+ Q
//-----------------------------------------------------------------------
' y, q4 p# j. S//定时器0中断
( s- B# p" T& z2 ~7 ]! ^3 S( svoid zd0(void) interrupt 1                  . v" Z- n  S/ h- t
{* l3 h1 K+ U. e' x9 M
        : Y; e7 q3 T+ s& @
        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
3 {1 @- T$ v( }7 u# }        if(++ucCount >= 8)
- d3 ]; k4 Q2 K! e0 U        {
+ @+ Q. w/ W- A1 I7 M' |                ucCount = 0;( @( L* D/ Y- z' z% l4 i9 j; g
                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时/ Z1 h) y0 @  k  r4 }" b1 ^
        }
# C4 d  b2 r9 t) d( u        TL0 = 0;                //设置定时初值
4 c# O8 n& \; O$ X- [        TH0 = 0;                //设置定时初值/ t# [4 Z& z+ s3 S1 x/ A& ]
        
4 v& L- X5 g' Q2 g6 |% Y}9 b# r4 A2 l4 W
. S  p9 r( I* D1 j8 t+ }  L5 y/ x

1 S8 f9 D  W& r//定时器1中断 定时50ms
3 A9 V- S+ A4 \2 h$ K2 Ivoid tm1_isr() interrupt 3 using 1! f+ t) Z3 L! b6 ]) E  B
{
( H; T% X; L: ]: w( W! x        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S
1 ?' q$ m  h# d5 m: x5 ]        static uchar uiCount = 1200;                                //                        = 1分钟                ( F- _4 [, T* n" V5 V; o* b
        static uint uiCount_BeepTimer = DATA_BeepTimer;0 h: Z8 L, T* f$ `7 n

1 Z3 k3 T/ ?/ n& D& ^3 K. n        TL1 = 0xB0;                //设置定时初值( e" L6 a( T9 L. M6 c
        TH1 = 0x3C;                //设置定时初值+ }" y* }+ X) K' h3 r
' ^9 @9 Y: u- f- y4 g
        if (g_flagSwitch == isNo)# E! O9 T& e+ H; Y. M+ ?2 P3 I) d
        {
! A+ W5 f+ q7 d8 j0 t$ p2 ?- a+ \7 d$ ?! U                if (count-- == 0)               //50ms * 200 -> 10s9 y+ e0 x# l. e% l
                {9 a0 A. J! w+ i$ ?
                        count = DATA_switchTime;8 l5 _4 M, m1 t
                        g_flagSwitch = isYes;
. S4 u4 d# V7 W& [5 ^                        // TR1 = 0;( |9 X7 X6 e9 a3 H; T: u' u- q
                }
; }! ?( m! u( B, {% W& x3 _        }        
# F; H, s, s* q# X        
1 y# X+ ]2 j& k        if(g_flagBeepTimer == isNo)8 o2 A) Q( j3 m
        {
! @9 S0 Z  p! ?/ k5 S4 \7 i4 H; {2 S2 }                if (uiCount-- == 0)               //= 1分钟; S) ^: `7 u- q. e, ]
                {: d: k& h5 J6 m4 K% Q3 \
                        uiCount = 1200;
, n' C: ?  Z3 k  ~& ^) i% K                        if(uiCount_BeepTimer-- == 0)
" Z( B2 d( W3 d                        {
+ E+ ~0 h6 ]& V4 w2 E0 b% i( ~                                uiCount_BeepTimer = DATA_BeepTimer;
. b. M. C. J/ i. M9 L8 {                                g_flagBeepTimer = isYes;; f( l9 C, J+ c& i9 {
                                // TR1 = 0;0 o" W/ [) p9 ?0 O0 j9 T
                        }                        
! ~* S1 S. f* W- i  o                        
' ]" w/ J7 m. q  U9 T                }
( t4 v8 P" m2 R2 c1 X0 [, J( T" o. h2 N$ T- O, w( G6 Q
        }
6 v; _# T0 n  w1 i6 g}
* g# m6 R1 O$ u+ j/ f  z
0 `1 ?9 O( D" j7 }5 k/ D//-----------------------------------------------! g3 e! a2 A" D2 j3 t
+ M7 q3 \! A5 Y. J+ R
" B  v8 j" r# N% p0 f5 Q. w

' \4 O: z1 {7 _7 I
! y5 o* m" U6 f3 n; Q5 Z
! ~4 w# U. B) M8 U/ a* V//外部中断1
" E# |# U2 J: O: N& Q" ~/ Qvoid exint1() interrupt 2 5 B+ ^9 L8 T6 P2 e1 k  m4 p
{7 Z  u1 E* G1 l; Q
    EX1 = 0;                         //关闭当前中断9 E& ~& @4 Y- b' K& L9 g) x' I
        TR0 = 0;                           //关闭时器0  d0 b. p4 j' o- U2 a
        
( K' Y* D. n3 t# V}
7 {# r  L" T0 T% b% k' w+ v//-----------------------------------------------------------------------8 ?3 }$ |; v7 Q2 V) R
6 ]. {% x% j, E  y
//读LCD忙状态并等待忙状态结束
! X) b8 h5 i: A6 f! avoid LCD_waitNotBusy(void)" G8 u# O) G* `  a, V% L  F
{4 O1 e; p; x  g" U- h
        IO_LCD_Data = 0xFF;
# [9 v0 ?! H5 l9 _        io_LCD_RS = 0;8 i/ u% z$ d5 G2 d! `
        io_LCD_RW = 1;
+ V6 ^6 d" o7 i4 d& A        io_LCD_E = 0;6 Z4 e+ Y9 E2 _' @" Q9 l) l
        _nop_();
9 h0 Y4 D+ L% n( J- ?5 s        _nop_();
2 o# Q. Z$ M3 R3 q+ j! m3 L        io_LCD_E = 1;+ y" L8 i) ^3 ~' n5 J6 w  r5 M, S
        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙
+ I+ s: K0 m$ {! `5 X; }}# u0 }  {( U" y& F" z5 \

* }9 H8 m. R8 w0 V  `//给LCD写指令# t( c" }% [% V6 K5 P
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
/ L: a0 U' W* A+ L# j1 v{
- e3 X8 h# y+ f        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙4 L$ r& ^: V/ U0 f9 q) e9 A3 g
        IO_LCD_Data = command;+ A* M- }; h1 W4 o
        io_LCD_RS = 0;1 |! s. I* \% \
        io_LCD_RW = 0;        
" \6 y0 O: l4 D* Y" v6 G( x9 D        io_LCD_E = 0;0 w3 ^: G" m3 y$ R2 e4 o! v
        _nop_();
, I6 v* j. D) c' [        _nop_();
; Z% E/ ~( r8 K1 L4 `        io_LCD_E = 1;        , g1 I, Z6 n, Q# m
}
) X2 j; X" u! G) B
# S; q/ G1 u% U5 e$ l//给LCD写数据
% Z6 f( l! T! g8 |/ qvoid LCDWriteData(uchar dat)
; q: Z9 m5 z, G# ?! F7 V{
4 l9 B3 H$ M' o$ W9 y, {        LCD_waitNotBusy(); //等到不忙
7 `/ E/ @6 S% [# K3 O        IO_LCD_Data = dat;9 o3 S% w. h- |
        io_LCD_RS = 1;
, }6 B6 A/ I* X5 `' E6 C+ F0 V* U        io_LCD_RW = 0;
+ M- O& ]6 K7 q5 p# L        io_LCD_E = 0; 5 T4 P. s' I! {& L6 t
        _nop_();
; |- G. Y3 b3 S/ W: @! q        _nop_();6 H  o9 {/ U* i$ t; f
        io_LCD_E = 1;4 ?- U2 S& |& s% i$ _6 Y
}% A1 ]- y" e8 E( y- h' S
: O1 C$ p2 A3 E! G3 A! l" E

3 h1 c1 Q0 N6 b, V9 }8 M- j: ?
: B# s( B$ g; D2 l* \
2 _0 E9 U5 h* p) c: P// 初始化LCD1602液晶显示屏
+ R9 ]) c! G7 @2 w6 K& q3 W3 s) V( Uvoid initLCD1602(void)
6 W% b2 O' [+ ~) C4 D( Y{5 P9 [% g" v; q6 L! X
        uchar        i;        
  p$ F# [6 t' m* z% i' f, O        IO_LCD_Data = 0;                                                                // 数据端口清零9 D& X$ T! K3 `3 v+ T7 g
        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
; V  a2 d! `: e" y7 C/ k        {, N7 J& P4 |1 E/ O+ o
                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号
$ h$ G3 _1 e' C: ^) h" H( e                delay5ms();+ o4 f) O3 e, l( Q' |6 k
        }
5 K9 W' ^" M+ y: \( J        6 F3 I, w/ @4 {% x* i9 e2 f9 p
        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号7 d: m' m- [, w: m( Q; O
        LCDWriteCommand(0x08,isReadBusy); // 关闭显示
/ Z) n, U, n9 X6 ?$ J* g/ f$ Q  U        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
; M/ d5 E3 W- R. M4 y& |9 |! P$ o        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置/ b. V3 B% |; n: L2 O
        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置
, O% E9 V. F& l" ]: p}
( U7 B7 X6 P- k) I# L! O6 T4 v5 Y* y7 Y2 F2 V  J& P. S) n
! t0 l: O9 y8 G! d1 p
1 K  f( A3 B4 ]8 w9 k" K7 |
//按指定位置显示一个字符! f+ J6 D- ~6 Y" i- N* e: X2 j
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
2 ]9 y; B  r1 l$ u& @+ h  x% `{2 S- r6 H) J. ^( S" q0 X- z4 D5 e

- e7 a2 P9 V5 o6 c& H6 x2 V) Q        line &= DATA_LineMax;
/ F& i, J5 v0 `1 r; X: K        position &= DATA_PositionMax;
3 C8 B& u8 E$ W8 E+ Y        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;, g6 f# |' L4 i
        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
# j0 E% W+ t( N* Z' t. v" m        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
* W, p$ E4 b% y! T& G% n/ y        LCDWriteData(ucData);                                                                  //写入字符的数据        $ F: R* i) V2 ^
}; @0 j3 e. e) t& \. K  c
$ j% S! J8 Y) [6 D8 V1 w
//按指定位置显示一串字符
9 \- l2 }) E0 P0 W+ T. `; Xvoid putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
& G7 \. ?/ ^5 v1 Y& x{* D- Q9 o  M; d* j
        uchar i;
* W6 V2 G# g' K2 m; @/ A- g        for(i = 0; i < count; i++)                                                        //连续显示单个字符
  P* s. [4 Q7 `9 [$ [) a        {" p% X3 ~% t2 n, n9 U5 A6 P
                putOneCharToLCD1602(line, position + i, ucData);        
! i6 H, ?2 z# q; D! f        }; v$ e/ p; m8 v: v+ E& M: i
}; G' Y4 q. K$ |4 ~5 m6 m3 J
! g& O  }2 u1 _( k: ^+ V
9 h+ Z5 d, o, b; ]5 E1 x8 s
//按指定位置连续显示三个字符(三位数字)  j9 S6 I! g7 j- l6 L
void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)+ N! x2 m$ ]1 L1 R6 h, q) a( c
{. i' G: `; o% k6 C0 G# j# P6 T
        uiNumber %= 1000;4 x# L, s0 ~! F6 ?! \! u% _
        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
$ i( t0 L2 P0 Q* M0 I9 x        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);8 e' f/ S7 F5 X- F7 {' d0 w& g
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        ) Q: |  I+ V- O$ m8 }: z
        % n! O7 P7 R9 P& y+ u+ h, y
}# D* w, h5 M5 z- p# ^
        
' \3 r% t2 d+ {0 E4 }2 ?4 ]4 f' l( g

8 P! X) i9 F+ R! X// 按键检测子程序,有键按下返回键端口数据,无键返回03 e1 h# S# E7 p( g9 P$ X, y
uchar GetKey(void)
8 a8 \" D+ ?! g  `  }{        " d- A, ^+ {: f4 d, A1 ~
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        
; M. g9 P* O7 h/ [. S; h- t        6 x0 b+ K3 Z/ d2 k4 ]% p
        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空6 X& L; s0 P. ]8 v+ E
        {2 J% a1 ?% K2 l7 ?
                uchar CountTemp = 0;
) k, }. |. i. W                do
# p6 j7 W% l9 `  A: |+ S                {& B4 |# C+ d. y1 K  a$ m% o1 a4 t/ A
                        delay125us();' [2 Q/ v. Q: t# n: G3 w
                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
* O4 x6 m3 @4 E  ]" x8 h                        
; U3 T# n3 @$ {& D% I9 P) X                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动 & l6 L8 A. q) ?) a* [/ k/ l4 h
               
( ^; O' o, E' B$ N' g. O& S7 U                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放                1 c4 M) I* I* [+ _, `# e0 J
               
" J+ o  W( F/ o& G* _3 d+ R                return KeyTemp;        // 有键按下返回键端口数据
; w% y; W9 r% i# b- Q: R2 X" [' M        }
+ @0 ?' C' r) Q3 s        
. L5 A4 C- v1 m$ e9 v. w1 j7 j        return 0;        // 无有效键返回0
; Q% K# {$ M' b. X4 D+ u( A" ^2 }' k}3 a5 H, z1 V: s7 U( s( J
; n8 c* p7 N( r1 {/ @& T. L

, W0 x2 Q* j0 h8 i5 ^0 U3 N8 N. s* C5 y0 A
% }) |$ o  {1 S6 M, v; I1 g//加一: t5 n& W+ Z( `
uchar  INC_Number(uchar Number, uchar Min, uchar Max)
& C; H- b6 x  }' r{3 u2 m' g! B/ @4 B' k2 i, e
        if(Number >= Max) return Min; else return (++ Number);# K0 T8 u! D. ~9 Y
               
; c4 o1 v: U" e3 l9 V: i}
+ ~" `' ]8 y" H/ n) K
+ K3 a9 L% b1 i2 G: s7 [8 j( U//减一: q7 O( g5 p2 ~: }+ ]7 e: G
uchar  DEC_Number(uchar Number, uchar Min, uchar Max): _- i% N. r$ W5 c: M
{
5 _* ?3 g7 z0 r        if(Number <= Min) return Max; else return (-- Number);  d; Y& e. r% v8 p+ n9 q  [, _
               
7 F0 D' e3 _" @  K}" n% G  k" e  @& S' S# i* t0 X
3 B0 u) C5 U) j, |" g8 T6 ^& W8 p) s
// 检测到有按键后 这里执行按键任务                        
$ Y" ]% }; B7 }7 q. c+ ^void execute_key_task(uchar ucKeyValue)        
8 b6 e2 Y; V4 @3 u0 ?( H! v{& X4 z* I. [: H/ ~/ m- {. j) J4 a1 F
        uchar state = 0;                                                //定义调整数据的状态变量% O6 k2 n3 K4 D
        uchar keyValue = 0;                                        //定义键值的临时变量
! G9 Z( A  Q1 P) [/ M4 e2 i/ Q        7 }+ U  @( n% X4 e  J! i/ {
        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出" q, n& @9 B- H- g
        * i( z( Q4 `) J; E: y/ _
        //是设置键继续-----------------------------------------------------
' q' V3 f' K# [6 m* r        
. ~, Y& \8 _4 c        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                - y9 J% |/ T$ {. e0 v, j
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        , q: B: r( P1 s
        . X' x% [2 v4 J3 I& h8 ~# Z
        while(1)1 W( {) ]3 K/ p5 J& D+ @
        {/ g3 |" E5 u5 z
                keyValue = GetKey();        
4 P! m1 l5 ?9 U; C4 J" Q8 P                if(keyValue == 0) continue;- @4 q* c3 G9 w
                5 e! s) Y6 D" V0 ~! ^4 y& w
                switch(keyValue)& [/ R$ S4 E5 G" n9 g5 F
                {
- v6 ~( ~( v5 q1 w                        case DATA_KEY_Set:
9 @/ |' c9 g9 u1 d; F                        {1 h/ m, w' \5 m: X& T, v
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
0 M. l5 P6 o& o7 _3 K& v                                switch(state)3 ?! Z/ J4 q% I- {8 B; ]
                                {
( C' n4 z5 k" f- p+ |                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面
+ |" j) D% U5 ~; N" d" `2 _                                        {* j0 h+ S0 @3 q( V& ]1 v4 |
                                                state = 1;                                                
/ Z6 Q1 e; _/ N4 k0 J                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
4 T9 h# u! p# j8 i7 ^                                        }
( K% T1 s0 N! v, _7 u" l                                        break;
) W5 G0 Z" M# \  A- O                                        case 1:! W1 C7 r8 i- n5 A
                                        {8 m1 k. _; H1 a4 R. U' [4 T; S
                                                uchar tempMax = uiD - DATA_uiD_Min;/ T' @/ ?( k; |* g% I1 ?
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
% K4 ?; f" g- f8 Z8 X7 k% o                                                if(uiH > tempMax) 0 P; O. x& ]1 U0 P) I& I
                                                {
( l( P+ Q6 Y- [. |* \4 J* {+ P                                                        uiH = tempMax;( Y6 x4 v* m% z8 q( }. z6 F
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
- h) b6 G, q( h7 ~                                                }0 R, C7 \, o# P$ ~. T( b% G: O) i
                                                else if(uiH < 2 + 2)8 U" J" j. \  O2 ]
                                                {6 ^& P8 p& F- g6 U9 I' D! h% C
                                                        uiH = 2 + 2;        
! u4 I0 R" J* w. W. z3 p* N, X( K                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);; P! G  A9 R* ?$ \1 c# p) ^
                                                }                                                        
6 a6 n3 q9 {; N                                                state = 2;
2 h; Y9 T& G. K; e8 `  A$ j8 }, D                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);; x4 ~  |: t9 p2 O( y: V
                                        }
3 E* [0 k: w) o5 }* C                                        break;
7 T% a6 H1 s' Z3 V6 ?" |                                        case 2:
4 s$ A+ ?0 T# N, N                                        {
. s% M, e2 |* A& W$ q& i5 ^                                                if(uiL > uiH - 2) 2 z1 h0 h$ A$ s$ f7 O7 x5 Q5 l- ^* R
                                                {
: |9 P- O8 N! }& }3 R$ B                                                        uiL = uiH - 2;
$ H. c/ B" e7 o& H, D% Z* \9 Z                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
! D, c, x2 @7 `' M) u4 d                                                }  d1 z  b% q6 n9 o# j0 h
                                                return;        5 N$ F2 X! q9 ]
                                                6 ]: q7 s- V3 S! ?
                                        }2 J0 t# x" i6 L
                                        break;
' r  c: u* p& u3 q& p( M: ?( ?                                }& O1 N7 v3 A) I- X* l
                                + G8 Q3 ^2 d. L: x6 z8 u
                        }/ K% @; y/ O7 V) ^, [; y
                        break;
( j  o* L& D5 b# C0 _5 O                        // 如果按的是增加键,改变相应数据并显示
$ X; F0 N* V9 i4 p; O" v                        case DATA_KEY_INC:
' N8 b) d8 [: [+ o- Z$ I3 W                        {. Z) B9 Y* n/ ]( z! O4 b) j5 Y# A! b
                                switch(state)  a( k0 f9 @+ t; ^- I
                                {
- j9 z# S& P( h" R% o$ W                                        case 0:
( P$ ], P+ T& f' Q" ^                                        {
" {: l, v3 l& k4 ]& X* v# r                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);# A* b9 \. j3 Z9 n# C- V$ S
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        + x' f" ]% a6 `6 D
                                        }
, B  A, {) o& D5 w' ^; z; F: ^3 L                                        break;  p" \9 @0 Q& J; V
                                        case 1:
' i0 D' I/ ~6 r% Y8 j                                        {; Z  F* m. |, q5 h5 I1 R
                                                uchar tempMax = uiD - DATA_uiD_Min;
7 }0 L8 L4 K# {" v& d                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
$ P0 i. F6 h" ~, h0 l3 @  d                                                uiH = INC_Number(uiH, 2, tempMax);                                                8 _! `& j/ m; }& j  [8 r' y3 g. z
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
( P, {$ x: w% R. w9 d" N* l$ G8 j                                        }/ }$ A& F) `7 {
                                        break;- z: p* ^' N$ C6 `: [+ h9 o
                                        case 2:+ o" `. x4 @; w6 o$ r; A4 P4 l3 c1 r
                                        {& A2 N  A7 e, T, E; i. t$ a3 u
                                                uiL = INC_Number(uiL, 0, uiH - 2);        , g: i7 P3 r! v+ p7 w. F- Q7 N. O
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
9 B' @2 b) X$ D& ~                                        }
6 S: Q$ o6 f6 X9 S. O" E% ~                                        break;6 y# u( y1 C. z; h+ }& k
                                }
' X8 i9 S2 M! Y, E# u1 [, y! b                                % X, v- h  k4 w9 W9 f* Q' f5 O) [- d
                        }
" O" Y& s' A9 z& r% L                        break;) o. a+ p% |  W7 J- ~: L4 ?8 V
                        // 如果按的是减少键,改变相应数据并显示
7 U% a0 }) o; N+ O3 d7 w" B: f                        case DATA_KEY_DEC:
$ |7 Y: n0 e3 Y                        {3 R( C- e1 m2 v7 c4 r" ^$ z
                                switch(state)
6 c6 R$ {, u3 G                                {6 m0 I* B6 h* R) a+ \1 n1 S$ \
                                        case 0:/ F' L, W6 j1 q1 k0 `
                                        {
* G# m4 A6 y9 N; @2 p                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        9 `3 N* G. q, y7 S, H
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
% W9 t. _% k4 S3 O  Z                                        }4 p9 v: f& Q/ e% ~9 p; t; g
                                        break;: D, t- D8 f: K- b6 o4 _. R
                                        case 1:
8 Q" E. U. ~" _6 v$ P& H                                        {
8 k9 @  @3 H, R: G                                                uchar tempMax = uiD - DATA_uiD_Min;
3 E3 v8 ]' S, K+ _; f2 q5 P                                                if(tempMax < 2 + 2) tempMax = 2 + 2;/ [0 o! B2 U2 a
                                                uiH = DEC_Number(uiH, 2, tempMax);                                                
9 e* o' |- a; w$ f' k; |                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
0 ?9 h* u: W! P$ @- g- ]) }+ Y" B6 D! |2 g
                                        }- Z  ]- l1 Q) T0 R: J' q
                                        break;
, [9 N2 q  a8 s4 u. s; }9 |                                        case 2:
: M( |" M- }! X% Y5 ~2 Y0 X- b8 e3 ?                                        {: |5 _2 D8 {+ t8 k/ K! h
                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
+ v* P- q! K5 h; W$ S2 J                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        5 m9 ~! L! }2 @5 X

) p: J, G. M4 J! M8 X5 }                                        }7 T2 Z9 F; E! p7 s* I. `. T2 m% E
                                        break;
( c; n" u1 D& T  m# a; `6 V8 r                                }6 }' f0 |  i6 Q2 G3 D  ~3 t
                                  @  ^( t0 s; P! h. W# d$ e
                        }$ }2 e$ |# a" J- Z. D
                        break;9 d: _  E' j" _" X
                        
1 \6 F& N" z6 I! {! G% y- u                }
/ D. ~( K/ _6 o# i, h               
9 ?2 q& p1 }& R3 S        }7 P& s( N- Z, `+ E9 D2 A; n
        
: w; O1 v! z( `4 U6 }}
& P% [! R( s" c
' k4 ]8 |6 \" d) A7 }9 l9 C1 `+ i4 e0 _/ Y; R
6 z6 A( Y: F4 S3 H/ ]3 \
// 蜂鸣器        
& h% I! p8 e, r# w1 ~/ D& n  G, |void        buzzerCall(void)
7 B6 `, q. r# |- P0 B2 ^% |$ q7 Y- x{
$ d5 I3 M* }* Y% s& w! k- C        uchar        i;; t+ z2 P: Y, A, e7 e
        ; x4 t& ]! E- R$ f' W* x# c
                for(i = 0; i < 90; i++)
- U2 W3 z1 O+ a/ P6 d1 C* u                {
& H" e! [, {& c, I( v                        io_Buzzer = 0;
' d" p# i$ e7 O7 [) d                        delay100us();+ P& T# f$ P- A! h  M8 k
                        io_Buzzer = 1;
9 [3 l7 r. v3 _                        delay100us();; n" ~6 @; n# ~% N* G0 G
                        delay100us();               
# s  G) H. {3 L4 x5 P% Q                }3 a0 f0 y- F* b6 c
                delay100us();        
6 P2 l# Z7 x3 K- t8 c4 u" C                delay100us();        * n7 n$ i# d: m, u; f0 u8 b" T
}
& L, @$ R3 K- `$ f% s! B+ }- t; v8 v( H4 b% Y# Y
//计算水位! G! A$ l4 e; N& m5 J2 v
bool CalculatedWaterLevel(void)- Q' O6 _* a+ x' s4 E7 \& |- I
{3 B' }% T% M) O2 p6 C" z" g
        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置3 y6 Y! v/ U) i7 }
        uint          uiTime;                                                //声波传播时间
- ^! c3 x1 h6 E7 J, R        ulong         ulDis;                                                //实时测量到距离        * a0 s+ s0 J+ e# D2 B$ m' H2 w
        
& I$ R) B2 C$ l) g; F8 g$ N; i' K        uiTime = TH0 << 8 | TL0;        
4 ?3 P* D* U$ x* ^# S9 h        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
" w2 c6 k# I3 G' C  z( O        " P$ E/ `$ c) {8 ^, Z, N- }
        TH0 = 0;& D/ a$ {+ [, n/ a
        TL0 = 0;        
, I3 N, E$ F# k$ j# h! |" b/ t        
( y2 j0 r/ Q, ^  S        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;! }- T0 U1 u$ Q% y
        {         
/ s) Y% K" g$ s' O4 F$ j: N                g_flag = isNo;                # q3 Z" q% [. q0 t
                TR0 = 0;
5 @) H4 ^" f) F; [3 R                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
, _' s% m. H0 e3 z# n& b, v               
9 E/ @: H& D9 C; U7 O                //阀门动作:               
5 T0 L; R& _! T& O                // if(g_flagSwitch == isYes)
+ B, X* H# V- l2 B                // {               
* M0 M! {) d" R( V4 p" T% ]  Q                        // io_Control_Inlet = isio_Control_Inlet_OFF;                . g' S2 ?- P5 a4 A  ~
                        // io_Control_Outlet = isio_Control_Outlet_ON;
8 B7 j4 @7 t: X: e% J2 A& @& N6 r                        // g_flagSwitch = isNo;) v* H+ T! B5 b# E
                // }                - o  T0 l) {; T0 n/ c
               
6 o7 q! }' Q: W& b                //指示灯:" g! g& Y/ i0 A- p' A
                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
& B3 P  Q1 v" o5 \" ^/ y! u+ O- n                ioLed_Green = ! ioLed_Green;
  N5 Y# o; H9 _8 \" {                ioLed_Yellow = ! ioLed_Yellow;) B0 C) E0 ]8 r1 f
               
' D! ]; f6 U8 {2 e# [                // 蜂鸣器叫:        2 I' |0 C* |$ c, i, S! o
                if(buzzerCallFlag == isCall)1 T7 L# D( A$ M1 ]! n4 U4 j
                {
3 l- K- E2 P& e                        buzzerCall();                                        // 蜂鸣器叫        
0 X5 T& s; c6 V& W8 O* g# Z) d                }! O3 i2 f5 V% [  v
                ( g7 F6 L& O. r
                return isNo;                                                                        // 返回错误信息8 {* S9 v6 ^0 Z& _. t1 D
        }- B3 n/ V4 O9 p2 h
        else5 Q: |1 }) w0 e
        {6 J2 G0 ?0 r0 E6 c& `3 H3 l
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离
2 j) }/ X' [  U; O                * W" \* d$ a  O* v- Z3 d9 u
                if(ulDis > uiH)                                                // 如果水位超高& Q9 s# [- ~3 u8 g
                {  X) v$ ^9 j3 t. J
                        
. `! Q$ {# P; D1 L4 k1 ^                        //阀门动作:1 Z3 O3 Y7 U" P% C0 m+ t$ i
                        io_Control_Inlet = isio_Control_Inlet_OFF;0 a8 u' K5 y3 m1 i2 x. W
                        io_Control_Outlet = isio_Control_Outlet_ON;        
9 ]$ a: {5 A6 o. h: p                        g_flagSwitch = isNo;
5 H; L) A6 Q. g; e, p0 q' w3 O! J                        
# n  L; [+ c! h  k- y5 y9 k                        //指示灯:7 j5 n) r& w5 @3 N  ?2 E5 x+ [2 ?
                        ioLed_Red = ! ioLed_Red;                        // 红灯闪) G7 k% O$ x- j) f2 T+ e8 j
                        ioLed_Green = isLedOFF;               
0 B5 u; d" j8 X3 U                        ioLed_Yellow = isLedOFF;                                + h  |3 ~* F, d4 N
                        // 蜂鸣器叫:
& b% L3 U+ e0 p& J" v" w                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警% @- t* P/ G8 Y# `
                        {9 Q0 t' x+ n: q  a
                                buzzerCall();                                        // 蜂鸣器叫
: U. X% x7 U2 p( w" z- W% l5 _$ w                        }9 Y. x# o  C: t& O- v; N& g/ O
                        
$ q% S! ?& E+ j                }
; f7 Z* K! `  x- w) H& B                else if(ulDis < uiL)                                        // 如果水位超低
' e4 U1 ^9 b9 M$ R; F/ Z                {6 D! q- O# l& s% r& K  k& x" ^
                        //阀门动作:        
6 o. W3 Y. ]' p7 v' b5 C7 R7 @$ z                        if(g_flagSwitch == isYes)
$ r6 r3 C% Y. ^& n3 X                        {                6 v! e" T; Y: M& F
                                io_Control_Outlet = isio_Control_Outlet_OFF;        
+ v; l$ f( b7 ?, p                                io_Control_Inlet = isio_Control_Inlet_ON;        * [' k7 t4 \5 }* I& d
                                g_flagSwitch = isNo;
& o3 G, A% C& }6 k' F5 S                        }        ) `# F" K# n4 [3 ~) Q4 S* R
                        
3 X% Y  n7 S$ b0 e+ f- P0 O                        //指示灯:
9 ~& {  n  {% `: L* v- A                        ioLed_Red = isLedOFF;
+ H$ N) z8 l3 {2 C                        ioLed_Green = isLedOFF;( g1 y  e& ]. M+ t1 v
                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪
5 ]6 o+ b% [; Y4 e6 x; e                        // 蜂鸣器叫:                                                
- h! b  |: J4 i# u& D  h" l. `                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警
' c7 d( g1 N% G/ q                        {
* h( ^5 C% m# d                                buzzerCall();                                        // 蜂鸣器叫% z& @2 |$ x! A3 W1 q4 x
                        }
* R4 y$ ]0 N$ c: ^# y! F; P                        
; L! }; s/ k$ X# n, @" p6 T7 l( \& h                        
4 V4 Z2 U/ C9 @                }
. A* q% p. _- F1 y" \6 z6 f1 A8 D                else                                                                // 水位在正常范围 * Y& c, H* V2 k7 S9 e: Q
                {        / Y9 o' E  X3 ^- ~- D" `# ?2 I9 b
                        ioLed_Red = isLedOFF;; t, R- r  e$ h0 c1 p
                        ioLed_Green = ! ioLed_Green;$ i4 o4 d9 j) V: u9 y% a
                        ioLed_Yellow = isLedOFF;        
" ]2 I6 d$ f. M/ w1 y+ T  g                        
& V$ K% L; S( p# O$ x  h                }! E% z( T; y" C" g/ P
                putThreeCharToLCD1602(lineTow, i, ulDis);
! C* P: e8 o1 O  H. Y6 A. d                return isYes;        - m& x7 a' x# r/ D4 m, T1 D9 Q6 p  V
                " q1 a1 s/ l+ U
        }" V- m) }) M& _  ?7 A
        return isYes;
# h1 K) u: V/ v$ R: e}
0 H+ y2 k0 Q) O4 F- _
4 C0 p2 [3 {9 x% A5 ]: d/*********************************************************/3 b" `' e1 x, [- N3 h0 v
void main(void)$ `4 L  A8 A( N3 r; J- K
{0 R/ t$ H3 k" i. X0 q/ J
        initIO();                        //初始化IO端口        8 e3 d1 g2 y& q6 ~% C8 a
        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        : T3 W" m8 h6 Z$ D5 W9 d* u
        initLCD1602();         //LCD初始化        4 n( N& a2 v; ?9 h
        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D3 P9 x7 f5 t& P# `  b4 E
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值7 x+ Z$ u% P8 J+ S2 x! ]
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H* j( m) {% J6 O3 _# V
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值+ Z4 ~. y( A& }* h& J" j: s
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L
8 F5 n% E6 |( C) K        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值. k/ B" ?0 ~( n& Q
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C" p/ x( d) e$ q( Y' w. {
        
9 E5 ?- S0 `4 g6 C, J8 z  `        initTimer0();                //初始化定时器0
0 U" s0 _+ }+ D+ Q        initTimer1();
; |1 `  @, x% d! d* ^7 z6 V2 n        5 n" O) `5 b/ d4 G9 v
        //阀门动作:初始先排水5 a5 v4 P( C* C3 I4 M7 W
        io_Control_Inlet = isio_Control_Inlet_OFF;        
7 w" ]1 j! ^4 F, s) N) q7 f        io_Control_Outlet = isio_Control_Outlet_ON;
5 y. |. L, j* b8 [& Q" U2 b        g_flagSwitch = isNo;        
/ _! g/ }9 \2 y6 I0 |  m8 v" l        " s$ b% u# F9 P6 Z( b, f$ a# d
        while(1)8 ?+ a7 S" f4 E! E' V9 C9 f
        {
0 c2 T# m# W% s6 e+ a                io_US_TX = 1;                                //启动超声波模块信号
* n, e* R4 d- L4 x. ?8 I                delay10us();
+ p& T5 y+ o; U8 z$ ]0 h' H                io_US_TX = 0;
+ o' c4 z7 T! B5 t1 q3 i3 S               
( M) s& j/ \. f  F( I                while(io_US_RX == 0);                        //等待计时开始$ H) K' V4 l+ Q; N
                TR0 = 1;                                                    //开启定时器0,计时开始        ) i- X* l- p; l6 W- b' e# X5 L
                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)7 M& v& G( Q$ J- D! u$ O" T
                EX1 = 1;                        //使能外中断INT1                $ u9 v) i) f; B, F
               
: i: L* d* ^$ O                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        
. A" g6 K1 \; H4 M+ j- j  d! T0 B                {# N% j9 U6 [0 p5 f
                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
) k- t3 M  J6 F2 g  M& i                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
% }0 R. K$ k4 U; D. C( S4 ^1 p                }
; z" O) I7 ]1 Q. O- g               
# O$ t1 `4 [. g) w7 X; `                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环               
- W! p/ [8 t) N/ k" k2 F5 T                0 \: F/ a2 i) v- W- ~
                TR0 = 0;                //暂时关闭定时器0/ c3 Z7 \/ h7 L: |; O3 |
                //清零定时器和计数变量以及标志8 `) a3 [9 `- P& u5 q
                TL0 = 0;                5 @" G$ D" ]* Y: a, U6 E
                TH0 = 0;                # i  [4 j8 |6 N/ D) ?! ?* M, a
                g_flag = isNo;
  m$ w+ o1 Q% }, f  H                ucCount = 0;
; N* ?1 q: C, Z% B$ Q! G  a                g_flag05s = isNo;7 W) Z! O' q$ p/ t
                + C2 u; U# i8 v( `; m. A
                TR0 = 1;                //打开定时器0                                        , j  O& ?' P  G1 `0 _
                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果* E: k$ V6 J1 s  w
                {                        0 H- u3 Z6 W/ B1 h' S" m# b2 S, H
                        uchar ucKeyValue = GetKey();
* S, Z; V5 M* E                        if(ucKeyValue) % T, U  F, r2 [" u- b
                        {
8 ^. p3 c+ ]& |4 l                                if(ucKeyValue == DATA_KEY_DEC)
$ |- s8 x9 p4 G  A                                {, c! P4 Y' X6 V! M# v7 O5 o( j$ k
                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志
" U* i) T, g  r# u" {* m) o# K7 C3 U# p                                }! F5 E3 G3 M8 l1 N
( H) Z1 i. A8 [7 p" k
                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
, k% D/ M/ Y) t' X3 O  K2 V7 U                        }                                % c" D2 q9 O1 Z' e3 d

8 g) V: A* q; s2 p                }        
4 ^& e2 N2 {# N1 e5 @                TR0 = 0;                //暂时关闭定时器05 }0 W& a3 u# U& [! r. G
                //清零定时器和复位标志9 n' y0 p7 p$ I- K' Z
                TL0 = 0;        
1 [, x1 k( @1 y" {                TH0 = 0;        
. \- P6 S" o( Z6 X                g_flag = isNo;                ) {8 X3 f; r. k! v
                * w9 ?" z% g% e# p) \
                //-----------------------------------# O) W' K3 T6 i& f& R& M, @; n
                //水箱清洗提示:
9 n/ ~( Y2 X. p/ b# E& N4 M0 H6 `               
2 v+ u$ s# x5 m: X, H" [. d                if(g_flagBeepTimer == isYes)9 {7 E+ C$ V! R$ R
                {  ?8 I2 r" ^5 V  z* s$ l
                        buzzerCall();               
8 P% ]& \, b7 ?- X. n                        //用减小按键取消报警标志  p; Z* G- [3 N+ {, J) R! Q, b
                        
! A3 m+ m. U$ h                }7 }+ r+ e/ \2 w! J3 F6 \
                //-----------------------------------* C) f7 W  o  d
               
8 Z6 D. Q! q/ O2 U( ]6 r        }
) m: g0 `  w+ a- X}
9 v+ c9 y7 a9 b, h5 \
: N' o" W+ J9 q" P
% F% J, N' m7 F) x9 x, Z- Q#ifndef __MAIN_H__! C" Y7 z9 l9 S( k' l
#define __MAIN_H__
( y' F! x9 i* [" Q" L4 z  c4 L' W6 q: V+ R! G$ n
//-----------------------------------------------
, `: N6 W! e. t) X/ Rtypedef unsigned char         uchar;        //为了方便书写定义别名
! t; l& p* a7 o( Gtypedef unsigned int         uint;
% B2 Y  m0 G4 ~+ r+ t. J- R$ ztypedef unsigned long         ulong;
, _( I  Y  V( xtypedef        bit                                bool;0 A: T4 f* p) i* q- \9 t

* m7 z1 c+ t9 t" u4 @sbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口/ }  O1 u) p" P2 g& y
#define        isio_Control_Inlet_ON         0
& |  w, k9 M, H& }0 o#define        isio_Control_Inlet_OFF         1
5 v2 K& c3 t! h' a  E: {# G5 q% p+ n9 M% d
sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
5 X* @3 f' N: g$ t. K#define        isio_Control_Outlet_ON         0
* E' m4 l0 n. d; v* M#define        isio_Control_Outlet_OFF         11 w7 X; Y+ t& F0 ?' A
$ I4 U. A5 Q6 i- O) Z( Q
#define         isYes                1
: Q6 b1 L$ ?4 o6 v# `; t#define        isNo                0# b. W, D  M) J5 [7 |( `
//----------------------------------------------------
" L* \  ~7 f; D//定义超声波模块引脚: |4 g0 ?9 t+ w
sbit         io_US_RX          =        P3 ^ 3;        ! z/ G. p4 U6 C# A  t! j+ Q$ V* J9 |
sbit         io_US_TX          =        P3 ^ 2;
! `  D8 x) K# H//----------------------------------------------------0 {. w6 f7 h6 t5 A
//定义LCD引脚8 X& e5 m* g& V0 l. \9 s
sbit         io_LCD_RW          =        P3 ^ 6; 0 K" q$ r' P" h! Z+ N  O; v$ e
sbit         io_LCD_RS          =        P3 ^ 7;
4 O! D( E- Z- l  i) }4 psbit         io_LCD_E           =        P3 ^ 5;            
" m" w; a6 n! T. u8 j#define          IO_LCD_Data                  P2
+ j  E' z4 g( q! S% I8 `#define         lineOne                        0" e0 |+ p/ Y7 K' v+ I4 w
#define         lineTow                        1
  L- h  q* S0 Q3 J$ {; q5 w6 @8 r0 o9 P
#define        isReadBusy        1
! Z& }4 t4 P6 |#define        isNotReadBusy        09 b1 U& H9 G( I" S5 @3 e
, [2 U/ ~: G; v0 W3 W1 c
#define        DATA_LineMax                0x01                //LCD最大的行索引数
  T- C5 k: ?; i1 O#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置- p. a% C+ o/ z" B6 i* I" ~; ^" s' ~( ~
#define        DATA_LineTow                0x01                //LCD第二行的索引值: I$ B. s5 l# F$ n2 s1 y
//-------------------------------------------1 y8 ?2 e( s7 }' k6 p
#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时0 D5 B2 n$ a/ i/ u& e" ?0 P
//-------------------------------------------------% x! A- g* Z- D# ?! g; B9 O/ ~
// 定义指示灯端口
1 l5 `# S% P2 J) a& W( \sbit        ioLed_Red = P1 ^ 3;
: d* F/ b8 ^7 z) k. m1 `sbit        ioLed_Green = P1 ^ 2;* E/ ?; {6 A% B5 j4 k
sbit        ioLed_Yellow = P1 ^ 1;; P# _# F/ h+ p0 I$ o, B1 F/ O
. ]0 K( t$ W( U; v1 D, F; ?5 j
#define        isLedOFF                1                        // 关闭LED
+ K; ~5 X0 B( v3 J4 f; U#define        isLedON                0                        // 点亮LED( n; e% E& ~2 D% G: S$ F& Y% K; T
//---------------------------------------------
8 K; d4 i9 F$ I) a- A1 D+ Y//定义按键端口! d; n) C, C. Q* C. K
#define        IO_KEY                                P1        
! I; q* x# B# u# \* e+ |: e0 F
: q. ~* @( _- v8 e8 K$ h1 }#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据
: k: ^% D+ D0 M, ^4 b1 Y: V$ b#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据$ V2 B( a7 t% i% ^* U7 M

/ S$ l9 j: W# O' U6 d( k% ]* Y#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据
" p0 `$ ^! |5 x! b% P5 p9 ^  Q1 _2 Z#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据+ b  \. _; X- h; {  ?( E6 ]0 n4 Q
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据7 O) k: c) E" R/ A. X
//---------------------------------------------
1 ?" J$ W  l8 D  Y//定义蜂鸣器端口2 k$ Q3 f5 i6 m* x
sbit        io_Buzzer        =        P1 ^ 0;        
+ s; J# ~( F  a//---------------------------------------------
! K3 C2 u1 U4 z5 H- m' l* }. [# U) h//定义检测探头到水库底部的设定距离范围 程序.jpg
" A2 s2 w2 J6 u$ l) v( z. b#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm3 x; B, @: S- N+ |
#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm: ~# y! G8 R& r8 f

: ]& D" Q3 b3 c3 a2 C2 L4 _  @' ?- |#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
) a1 {0 g# M+ x#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)
3 z+ T" f* Q8 u2 d#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
" g1 d8 ]4 J& j6 |6 F
& l! y' k8 E$ k6 G1 p8 G5 e! tsbit        buzzerCallFlag = P3 ^ 4;- ^) p8 o9 _9 Z7 `6 G3 f
#define        isCall        0
$ z" R+ e2 Y( C5 Z#endif, X% g( S8 `- V5 R. T+ Z
. Y! e. ?$ X: ~( t& d9 K

' i. d: e( j3 [
5 j; o  e1 R; c; W2 E0 O# b, i$ D" J# s0 i$ G( u  D

基于单片机超声波液位控制器设计.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- Z- X% ~1 F/ o! D
/***************************************************************: T, Q9 ^$ \& g
        名称:基于51单片机的超声波水位 ...

5 F6 v& [5 y2 v3 a9 a: ^又下载一次,打开跟你内容不一样?3 k. Y, z! Z, k+ P$ A. u, m, U
QQ截图20201211202119.png
回复

使用道具 举报

 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:052 b* ?* G6 [! k% u  W
大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?
$ d9 d2 P& k( Q; J1 r" m; B) k$ `% L3 U0 R
是的、是物体都可以检测到!. r5 }: ^6 R) [. E+ b- g) I
回复

使用道具 举报

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

使用道具 举报

本版积分规则

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

GMT+8, 2026-1-12 14:08 , Processed in 0.040676 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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