一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

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

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑   |' o$ l6 L- Z# N% ^5 {5 }
- X- q9 \1 Q, ?$ K
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)
& L% }4 f" [. K! a$ M
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

, V" U$ j$ c2 B" l% n
按键功能分别为:设置键 增加键 减小键 复位键

+ U( ~4 x# j. c, D* H6 Y/ ~. w
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)

0 N  `+ I0 o  ~6 k4 B
发表于 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 编辑 ) u" N" Q! S3 u8 U& e, u
tdc31224 发表于 2020-11-24 20:58
5 R( p8 w+ ?! F没程序?

! A4 b0 `4 G6 B+ H' i5 A( g
' `  r* A; V4 o, t/***************************************************************2 p5 r* Q0 |% @1 I8 j( C2 D
        名称:基于51单片机的超声波水位监测报警系统
/ o! O/ D) G- {% j" L8 `        单片机型号:AT89C51
4 U8 T  s, p( U' q        单片机设置:时钟12T,晶体12MHZ- O& l1 }; G2 K8 p( J
        注:修改增加水泵控制和排水控制,即双继电器
+ d1 I8 T# U3 L( b***************************************************************/
% |2 ?) D! B, K7 P* y" _6 y
  j0 f! S2 M& d, D8 Y8 B#include <reg51.h>
$ S# q% d6 S/ n' V* K/ m#include <intrins.h>                // 包含循环移位:_cror_' [/ s$ W) j2 i4 x: J
#include "main.h"     
) y* N. x3 S- i' Z//----------------------------------------------------------------------
; e4 M2 Z" e/ i* P, g
1 I4 p# K7 o7 I; r4 e/ xuchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};
7 }5 I. A4 P! u7 N( w1 P9 {+ M5 H  Y
bool        g_flag = isNo;                //用于标记超时(65.536ms)           7 l; W9 i4 m, w0 ]9 }- y; n- k
bool        g_flag05s = isNo;        //用于标记0.52秒  % O+ X( G& H/ A1 }( |1 ^
uchar         ucCount = 0;                        //用于计数0.52秒     
; W1 v/ s$ ]* m( _; D2 d5 C1 W* ?9 e8 W+ B; R5 L4 W
uint        uiH =  86;                        //设定的最高报警水位 H* I  |* J; `8 Z( ]4 f7 F
uint        uiL =  73;                        //设定的最低报警水位 L
) V4 S( D+ n, p/ D- A9 m+ Suint        uiD =156;                         //检测探头到水库底部的距离 D
  ^# `( k5 ?: d" P6 _& K% Q+ s8 P) ~. J0 p) e- P8 e& m
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志  U8 t9 a. `# y+ k4 J2 ^  ~4 b% A
bool        g_flagBeepTimer = isNo;        //定时提醒标志
1 o  `. l( g; R                * ~$ w6 O/ m/ R2 W
0 {1 `4 H, C- R0 [0 u0 A7 F3 Y
//-----------------------------------------------------------------------
5 j& o+ a5 K! t* \// 延时10us
9 |; Q0 A) j3 R6 j! x' D- Fvoid delay10us(void)                //@12MHz, {: z5 \" D; M9 c% `
{3 o, T( v1 E- J
        unsigned char i;
2 c) Z0 y2 b5 R7 d% ?. A0 U
5 I1 i! G/ R. |$ Z: s& m& n: ]. j2 _        _nop_();  d  ]1 P) Q  A% `' m. y
        i = 2;2 M+ M% y" g- Q1 j, L2 S
        while (--i);
$ j3 L9 h- z4 |% T}8 J4 K3 v% N6 z! n( {) G
' l6 Q1 x2 b" P3 Z
// 延时100us" {" p+ L, e2 c- e2 f  p$ J: q$ m
void delay100us(void)                //@12MHz! y6 @0 u& L! g! f1 b' T
{5 r7 @5 z  {& b5 A
        uchar i;
6 ~3 ?& k7 B  p& z
" e8 S+ s0 X, T7 ]3 ]        _nop_();
8 U% B) A. e  V1 c, d        i = 47;2 f( j: z% n; L' l8 h4 q+ G
        while (--i);
. f9 k7 Y6 i5 E* j% v4 ]}
2 l1 F6 E% J8 L/ O8 @/ D7 E- d3 S  w2 c
// 延时125us
. t( p2 R4 z9 P. X* Ivoid delay125us(void)                //@12MHz$ p% s1 B5 K* V5 h) j& L) i
{
. U7 K( m7 T: f: g* _8 c# |        unsigned char i;# k  R: r9 r/ g# K  X/ H, L
        i = 60;$ l- F" u9 l1 g3 ^& ~
        while (--i);" O; o% W* O1 s- S- Z+ {
}- \7 T  L# I! E

4 a6 A7 |& O" d// 延时5ms+ Z$ {/ r! X! E' c% g& H
void delay5ms(void)                //@12.000MHz
- O8 h8 L# K+ o. S! ^{5 q2 I3 M8 G' J' x3 H# P
        unsigned char i, j;
. R7 x! N$ x* s4 d
& o: `( H0 x) R8 P- L  C! S" n7 H        i = 10;4 Q/ G8 r9 r: [; z9 j5 Z9 Z
        j = 183;
" j) \" Q. _# G5 ?        do# L2 Y, X/ Y) o! A! |$ ~: G" ]
        {
- D# z4 _: f8 Q& H! {' \; H# T8 c                while (--j);2 A& h3 F8 k4 h% x+ Z, \% b
        } while (--i);) {9 ^5 S8 J3 t) n9 q8 |
}
, E/ \8 @7 e5 r9 H% f, l. d7 `: b8 C# E$ ]" X: n
// 延时500ms
. l1 W) v8 ~1 I: A% A( M8 d: Kvoid delay500ms(void)                //@12MHz; O! A- A' f' M& H4 D
{
$ }  L& \: L2 B8 j3 A        unsigned char i, j, k;% P, B$ J: |. {9 m6 |+ q$ u$ X

, B- [) w! {' y, P- X! X9 v# w$ v! p        _nop_();; K! i$ G  W1 l% J5 ?! e) J# o# D3 [
        i = 4;
% v+ K4 i; K6 L: x4 [) B        j = 205;
9 x- F# V3 ~. r9 v( A$ W+ @$ Q5 b        k = 187;
$ w# W6 x$ K: F6 G6 O        do, m' S- u# r7 d( z9 T2 j- e
        {
  v" y2 F1 E' U+ U8 |                do
! k( q$ M9 v6 i                {
$ I) T7 c  a& O                        while (--k);
- C3 @1 l& _5 U, b                } while (--j);
0 d- r# j4 F4 k  p, ?        } while (--i);
' o( t; S. Q& C& |( H+ {* Z}
" C6 l: p" ^3 d  L+ `+ k# u, v. F1 A/ L2 k
//------------------------------------------------------------------------ a0 n) h, O2 K2 Z
//初始化IO端口                        # x4 O& Z1 s* x
void initIO(void)                                       
. w4 K: \9 e: |+ Z( D{
! z* K- }( Q( c4 k. Z( E        P0 = 0xff;
8 g. }0 N- t! ?4 [        P1 = 0xff;' \6 \% |( G3 n7 f) |+ v; x
        P2 = 0xff;
3 H: y8 d, f9 `" r- f        P3 = 0xff;
$ a5 h$ n! h( d: _6 B! }- G7 _}
0 n3 C5 f8 R5 @, P* U% u# _/ i; r- D" ]9 t+ V3 H7 q: B
// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz* Q& ]& E; ?# X& A; _5 u5 U
void initTimer0(void)                4 {% S* ~: |; A  t7 b( T
{, _7 D7 N) C% B5 i: K
        TMOD &= 0xF0;                //设置定时器模式
) Y3 o# g/ y; {2 B' y+ N9 k        TMOD |= 0x01;                //设置定时器模式
0 Q* h( a1 I; L( q# s: a        TL0 = 0;                                //定时器初值清零6 i. M4 |) O0 _
        TH0 = 0;                                //定时器初值清零
2 g# S. U: i  f7 X2 C1 Q        //TR0 = 1;                           //开定时器0
' f* A0 ?1 q) ~/ m" G    ET0 = 1;                          //开定时器0中断
2 t( C  X+ j! Z; e    EA = 1;                             //开总中断            
! |) x; i4 x' f        
2 G( R) h2 C, R; V9 Z}5 f' s+ x% @# q( G
7 M" h+ c9 g7 b$ T+ A
// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz
6 S9 ~, d  j3 Y# Z7 Uvoid initTimer1(void)                //50毫秒@12.000MHz
8 D! ?' X. e0 Z' u6 r8 G7 l{        
" u0 ?) K8 I! d2 B( a9 v% m        TMOD &= 0x0F;                //设置定时器模式
0 Q% [  g4 W% J- Y- ?; e. x/ b; `        TMOD |= 0x10;                //设置定时器模式4 {: m9 {& W) O
        TL1 = 0xB0;                //设置定时初值
! f$ D* O+ D) {        TH1 = 0x3C;                //设置定时初值        
" p/ q/ G# q' }6 u" z2 e7 r        TR1 = 1;                //定时器1开始计时% m: k0 M3 y, e6 B$ B2 h
        ET1 = 1;          //开定时器0中断3 `  P( I/ Y7 N/ L$ L6 h
}7 U+ x9 O$ K' k  R- b0 E
/ Y# o# c2 E* Z  Z* t0 V& P, m" c
//-----------------------------------------------------------------------
7 r* I$ z# G% m: c, Y//定时器0中断1 f7 J: Y: F4 V1 K' n) p- F
void zd0(void) interrupt 1                  0 S5 m& _5 j" ?# K$ `
{
& d  L  k  X4 \; t+ {& j+ J        
" F9 j& ^$ Y+ N; T  b8 N        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
1 S% D" r  x/ I8 A; u9 K/ E$ X: `        if(++ucCount >= 8)
: @4 f0 m& z0 O        {
1 ?1 G8 O' A+ r+ [' A- p: S                ucCount = 0;) x3 S& C8 J% h- y( C7 R+ w' [
                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时
7 m$ N8 U7 o& S# H" o        }
' n3 y: t- h0 U        TL0 = 0;                //设置定时初值1 [0 ~* E# s0 G+ L
        TH0 = 0;                //设置定时初值+ }+ c0 Z  g' W% O
        " |; f. l4 k: K% L8 K
}# G7 H6 ^) o% \! O) d% M& U
3 e* z' g6 b# V  F* ^% W
0 V. Y" O$ K: i
//定时器1中断 定时50ms$ Q. o2 B  @: ^: N1 r# O9 K
void tm1_isr() interrupt 3 using 1; s' A& y( C- B; R- {' x
{
: t& @7 L- Y2 t# ?        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S4 U* C$ z& }- M  \# E
        static uchar uiCount = 1200;                                //                        = 1分钟                4 d0 }, `2 ?4 V$ }# D
        static uint uiCount_BeepTimer = DATA_BeepTimer;
+ z" d% Q  [3 p9 q6 V$ B- u, ^- b, D, S* _! l
        TL1 = 0xB0;                //设置定时初值% j# E5 s* q( Q2 s; R0 v
        TH1 = 0x3C;                //设置定时初值
1 y" W5 ]0 g& B& D5 B. `, D% w8 m7 j3 _
        if (g_flagSwitch == isNo)
, k& ^% P' T8 i8 ]        {$ ^6 V' F' |) \8 N& X- z
                if (count-- == 0)               //50ms * 200 -> 10s- u, T  f; a% s
                {
6 g! c1 V7 U! Y! i3 T' K. M8 }: a5 M                        count = DATA_switchTime;2 [5 W0 P% T. |7 r9 C! ^! f
                        g_flagSwitch = isYes;4 B; R4 l7 l" ~
                        // TR1 = 0;0 ], {$ q& l- G: W
                }" L/ }% V/ E3 y% c: o% s$ y
        }        1 u4 C  Z7 O& g7 O
        ) ^: c, D) A) ?% G& n% W
        if(g_flagBeepTimer == isNo)
) D/ z: x" D8 A! A( R- b& e3 Y4 T) b        {  S! q, z# T& z1 v
                if (uiCount-- == 0)               //= 1分钟
$ }3 r# f( Y, m: s, H( d1 D% @; j                {
9 G/ O! `; m( S+ _" Y) K1 x                        uiCount = 1200;
* W; X: d9 U) o  [. }                        if(uiCount_BeepTimer-- == 0)
% g" W' `3 h: J                        {
) L1 p5 S2 c- O% H; X. Z) N                                uiCount_BeepTimer = DATA_BeepTimer;
/ g& |6 J# a0 p                                g_flagBeepTimer = isYes;
" g; K$ E; @& A7 p3 ?% M+ z                                // TR1 = 0;$ `4 d% p; _! q( }
                        }                        
4 n# {0 Q( C, X. G0 }                        ' B" p7 m- w7 O8 w0 [3 `
                }
3 |6 i# w" D3 G  o: |" c. S/ D& C! n
2 I3 _) h- n7 N) A1 L        }5 b; G) F7 U( ]  q+ V
}! q& H0 Y8 z6 x5 R7 |8 M

! c  r- l$ [/ H1 k//-----------------------------------------------3 M. `7 n) ]& G3 h. ?
) U( N: `- _- g8 r0 k2 I

( q1 c) S: t( U
& |5 \0 Y: S9 ~: n7 ~  L& U) _
' f2 c) Q& C9 ^& {
4 I' ]+ b7 A1 [1 i6 c//外部中断1" E  T3 t% M& [2 i! l, s, }
void exint1() interrupt 2 # u/ C( p2 |! l' {+ S
{2 T7 y/ k7 R. h% w5 G  U
    EX1 = 0;                         //关闭当前中断
0 g4 `, |2 _& @% ]" T        TR0 = 0;                           //关闭时器05 s8 ?. u8 l) I( b2 Y
        
* s6 y! i* Q4 u  A8 e, Y}! O0 e1 |4 a3 J) J* ^
//-----------------------------------------------------------------------
4 ?' N/ m2 P3 g1 n; Q, E
" E/ E) o4 I2 Q3 F- q6 I* j- r$ G//读LCD忙状态并等待忙状态结束
1 C9 f# }4 n# y4 e* T) Q: Dvoid LCD_waitNotBusy(void)+ d  v* ^: X* i- q/ M
{* v; m7 x: E. T2 V
        IO_LCD_Data = 0xFF; * k0 c. w- N; W
        io_LCD_RS = 0;2 L# i4 `/ _$ a. w( x( [, [
        io_LCD_RW = 1;
3 b+ m+ \% P7 y5 O7 K        io_LCD_E = 0;4 q& L1 Z( R+ a7 T
        _nop_();: f4 ]. z1 Q8 N( I% w) Y
        _nop_();( b' A0 d* M" {$ c+ P6 [6 ?
        io_LCD_E = 1;8 y9 O8 u: E* C) p6 c% C
        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙4 \+ e) j; m8 |4 f& H4 r
}6 L/ Y. z* @! h  Y3 F* v5 [

& a! _( c; o" s. P//给LCD写指令1 q; |1 _4 ^, ~- |" l+ w
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测7 i. T7 m$ W/ F3 n- a% K0 n
{
9 c. A: L+ i/ X" w' S- Y: [" a        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙6 K0 b4 c0 {  Y7 I4 z( Q
        IO_LCD_Data = command;4 {* g* S- u8 I0 ~$ m1 R
        io_LCD_RS = 0;
# z7 @7 e. D: b; D  [        io_LCD_RW = 0;        
0 s3 A9 B% m- g        io_LCD_E = 0;( z% P9 n" Y' h7 {# F
        _nop_();
' E# b  j9 u$ B0 _8 h        _nop_();
( ?6 J/ e; Z! }8 {1 }9 y4 Q        io_LCD_E = 1;        
' Y5 q' @/ F- f0 t}* d$ n9 L2 V3 t% ^
- g- ^3 w- k2 m$ s1 Y% A
//给LCD写数据2 F* g8 O, Z1 i
void LCDWriteData(uchar dat)
) C$ j5 J/ e+ l) L- n{
0 w1 l! N: Y4 B, W; Y! a. g! H        LCD_waitNotBusy(); //等到不忙% z8 @7 I+ n" H5 b+ Y. z! v
        IO_LCD_Data = dat;  L/ |! ?8 S. L5 ?0 i: ?% x9 z
        io_LCD_RS = 1;, W6 q3 v& m4 l/ o1 w- k- j; }
        io_LCD_RW = 0;
# X9 H" h% n" M        io_LCD_E = 0; , i) m( N, ^# L  Q, H
        _nop_();
+ ?7 I; X2 Q4 X2 j* P        _nop_();0 h2 \) A" V. p1 I3 I# _( k: g4 u
        io_LCD_E = 1;& s  \; U4 Y: z5 D! w- p% p
}( z. G3 c0 c7 q5 j# n7 M# t" `: I

! C$ ^5 [5 C& Q2 w
& W: t' K6 E& X. }  [; ]5 d
/ N  L# T* k+ p  Y% q
# ^! D$ H! w+ K/ l' K  |9 Q$ g/ M// 初始化LCD1602液晶显示屏3 C" v5 S2 P/ i2 x9 C
void initLCD1602(void)
4 r( N6 h  E4 i; a$ U6 `1 B% T# O{
$ N+ ^( Q% j* k0 p) N. K! X. \        uchar        i;        8 r, a2 x+ _5 i6 U! r0 n, r6 x
        IO_LCD_Data = 0;                                                                // 数据端口清零
1 J8 v+ ?$ H9 @% h& f; ]6 R        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
6 Y1 z" \4 M* s7 I        {7 z+ w  H; y/ }, O# ~
                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号$ {: k& J) Z7 e8 G
                delay5ms();6 W1 t! t: t( T, a# W7 f4 W/ `' G9 V8 l
        }$ ~+ S( O3 \# z$ @, y4 A) l+ f
        
) Z3 n3 J" b: _8 D/ d" z0 ^        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号
+ h" A# w- s/ d3 G' a& N& t+ d        LCDWriteCommand(0x08,isReadBusy); // 关闭显示- M2 |8 b' P' h* [/ w/ C0 S0 @
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏/ u4 h( K: M$ b; V0 ^' w/ ?
        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
# F1 q  [  D( q  ?% {+ m) G        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置
/ W6 b2 l2 z# U4 F) {# D}# j3 v( [$ Q7 [# }* k  B( o: ?

0 J/ X" o3 i) ]4 ~' v4 e; g: P1 P& s( S. d/ q9 O5 G
( S6 \# l9 f3 m+ ^  s
//按指定位置显示一个字符" \/ G5 q  L6 ~  V5 I9 ~
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
: E' a. J9 F) F  E. H- x" Y{
* t; b* U1 x3 r# ?
* n; E( Q1 `# S% S        line &= DATA_LineMax;5 _! C4 ]& L2 |- k$ m% d+ M$ `: D+ g
        position &= DATA_PositionMax;
6 E. I7 I) u1 d        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
- y2 b1 Z& @( o7 a! p7 B: |1 t, x% j        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
* d+ \' @0 P9 U7 p        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
, n( o6 k7 P( t1 F8 X        LCDWriteData(ucData);                                                                  //写入字符的数据        
3 a( m. t7 E- `; b% q, S. C}* {$ ~. g* O7 [2 A
/ p; R# e) W4 p. D" S
//按指定位置显示一串字符
& S/ s% ^9 D3 F/ [& u8 R. I( N2 rvoid putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)3 h- d1 N+ e' U9 G
{1 R* N. [2 N  d- v( g' v; ^
        uchar i;
8 B! b- b9 K7 }" Q) o9 e        for(i = 0; i < count; i++)                                                        //连续显示单个字符
1 F+ s% L1 x. d7 r, t        {
' X  C8 O, e: x+ d                putOneCharToLCD1602(line, position + i, ucData);        
( I) [2 [1 M% j2 p9 ^3 @. ?' q1 ?        }9 Y; r- c0 Y4 w5 y. \6 n2 s
}5 U0 n5 z  l; c5 W% T* n

+ }0 V- {8 P0 ^; @2 l3 L2 z
( n3 a  G; _. v* n. b//按指定位置连续显示三个字符(三位数字)
2 O6 x8 ?7 K; K" K$ g0 A) Y' zvoid        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)! |0 m% m+ D8 w
{% X6 Y( h+ |# |% m9 x: n7 ^( u+ y7 S
        uiNumber %= 1000;# m/ A3 J0 R, f! L! q( f/ d
        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
4 f5 \5 C- n1 r8 a1 t' i1 ~        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);1 }% g9 X6 V! w+ u3 ]# P: k% M# l
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        7 B/ A  }7 s! m. ^1 b3 P  d" P$ u
        
, Z7 N0 x! p. N/ f& T7 w( u$ a}
& T6 e" m( |3 W. o, c2 X/ _        8 E& t" p. f( s  L- {

9 y# A5 c4 T3 d) r. ]- @! g6 ?' `  l  z7 M9 P% O5 {  z# T+ ?$ ^
// 按键检测子程序,有键按下返回键端口数据,无键返回0
) z& @. G: {) \& W7 ^2 ^uchar GetKey(void)5 B2 x' n$ c0 e; D5 k) x
{        
; L- G0 Q1 C7 C, |4 o6 @! k    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        ' d! G# \" ]9 a9 m4 K9 K
        2 A6 r1 l: H4 K6 y  `
        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空/ g' N  z& A8 q  z
        {6 z5 L3 {" O, B6 G# X
                uchar CountTemp = 0;) T/ _- B8 q5 D, D
                do
8 ?/ |6 l& k; M* Y! U) X* L                {1 p1 o3 D) \8 \* f; I& e
                        delay125us();* @$ m) I; U5 x: U5 ~8 e' [6 D
                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
+ e! o* x8 o0 `7 g1 T: g                        : {2 M# t" s8 O
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动 * X' a% D2 @$ h" }" ?- Y! V
               
# o' I  z( \' _5 I$ s* k- A                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
! I- ^+ @2 r7 D- f# R" ^8 j                , ~4 z/ Y/ a: S' q- k
                return KeyTemp;        // 有键按下返回键端口数据3 J  @/ _+ I- i/ \! u
        }
7 j: ^! [" f7 E: {        & l  T3 o1 d9 g; t/ h2 G" A+ o
        return 0;        // 无有效键返回05 a, W0 e4 f+ ], [% _. B
}
, E! j, P' v& i* f
9 D2 E* |3 m/ L, G6 h+ r
, f+ Z; v4 O7 x
% ?; W* _0 ]9 K3 G! O8 J//加一
9 B: X/ Z0 F5 V$ f+ ?4 cuchar  INC_Number(uchar Number, uchar Min, uchar Max)
- x1 s  @) L& F* x: `- o4 }{
8 S, n6 }) G9 D, m        if(Number >= Max) return Min; else return (++ Number);  K" P0 F0 M1 _
                # U6 o2 Q( w* ~6 x9 _% r
}
% I2 d% U- `$ k% d! `
9 `$ `1 e* @' m; @5 T+ _8 i//减一' V9 ?' w# |3 f$ N; c0 r/ W
uchar  DEC_Number(uchar Number, uchar Min, uchar Max)
/ |3 b. z% b0 u{
; R+ i, m& Z2 E3 J9 l5 X5 h( n        if(Number <= Min) return Max; else return (-- Number);5 d9 R1 E* k/ I
               
2 Z: Q* R% X+ L+ }3 @$ O% j( F, A}
; A- B4 A" q& \  H: \
% G( ?; G! J! s9 F) Y// 检测到有按键后 这里执行按键任务                        * q7 P3 L/ f- e; v6 j$ ^* b$ n6 f# N6 @
void execute_key_task(uchar ucKeyValue)        * w4 L$ I9 A  N) f8 c
{, P" P% G8 M5 B% E+ p' D  h
        uchar state = 0;                                                //定义调整数据的状态变量
, O0 Q5 C' j3 u5 y        uchar keyValue = 0;                                        //定义键值的临时变量! X5 s/ D/ q9 z
        4 {! x8 X; g& ]( `
        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出
* O, F  z1 d+ K' V9 J, F# R        
7 a0 X; }' q/ }        //是设置键继续-----------------------------------------------------9 J2 L2 |2 N1 \0 W# E1 `& B2 H
        
( d9 d( T5 O" T        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                0 W' J4 Z+ U; C! C2 `
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        2 X5 R7 ?$ B! P( A! W' T
        
7 z3 e4 W! b6 H: u        while(1)
- \* A* g5 {/ k5 g; `        {5 C) b# h1 \* V7 z. E% j& D; }
                keyValue = GetKey();        9 p7 Z1 U- Y* a. X! e( y
                if(keyValue == 0) continue;2 J. y: h* N/ c0 t4 B
               
& _3 }8 F/ A8 `, }8 v                switch(keyValue)
. c' m# b3 F3 Y- y; A7 T                {4 h) M9 f2 v" R" \
                        case DATA_KEY_Set:# I& D6 T' s0 M0 `/ B
                        {/ U0 }" p1 P( \: g5 n0 r
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
! |. F) c; E' `                                switch(state)
* D, I* r" R+ E/ l/ ]1 n5 M                                {
" J' U! F9 ~8 x* ?6 {: b                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面4 d9 g: T* l2 v5 r2 H+ t1 d3 T
                                        {
: N" W; H. h/ x+ I                                                state = 1;                                                
7 ]- D- W3 [2 M& M  n1 B                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                . o$ x- @6 ]6 ]
                                        }7 z# q. B6 d, O2 f
                                        break;
0 J, Y/ A4 z+ L                                        case 1:! X7 ]7 _$ Y/ Z$ V4 B( P! w
                                        {6 Q1 L- D/ L* l% o7 v
                                                uchar tempMax = uiD - DATA_uiD_Min;9 y( ]* Z& X' N
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                          Q$ m- U' l3 P8 E( C
                                                if(uiH > tempMax)
& z/ ^9 _; R, V4 b( f8 x$ C) \                                                {) C0 @6 A# C  _/ a) `( S# k6 {
                                                        uiH = tempMax;+ O* t& y& l. |3 N0 I
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);5 Q4 n! I' t4 g+ Q. i2 j" h6 w
                                                }2 l, m9 t1 y  T! l
                                                else if(uiH < 2 + 2)
8 K) d# B6 s$ a# I5 W                                                {( H. @$ r, z! ?" a
                                                        uiH = 2 + 2;        
' S7 l3 y2 H0 Y' V; c. i) [                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);3 z' ]- n3 Z& Z: P+ {) G
                                                }                                                        4 L0 a4 {8 Q$ U
                                                state = 2;
% u. M1 q6 K3 J/ `7 o" K                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
) p! E; a& N) E4 Z9 V+ I                                        }8 S! V, U! ~7 P- X9 A
                                        break;+ L7 ~: Z, t& e! M( V
                                        case 2:
, e* l* n2 I3 _                                        {
8 w5 T( Z9 y8 U6 l, h6 x                                                if(uiL > uiH - 2) 6 D2 V, Z& J" M. }$ q, p5 c
                                                {7 u' T/ z; {' c3 |7 F
                                                        uiL = uiH - 2;
& j! ^0 _7 m6 Q1 L# V2 s) p                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
+ D; t  @" w/ P! e+ m- V: Q$ U                                                }/ v1 x2 C# b% E( d
                                                return;        
# G- f) R. h3 Y( W' R* @                                                  }  @' ]7 ~- J- t4 Y
                                        }
3 `% o+ k8 ]6 P                                        break;
! \+ P  z/ }! C                                }  c% U3 v7 G3 W7 u& I- Y6 i, S
                                  V# x0 f2 X4 v  R: S" D$ E" ^
                        }
) G' N$ t% r( r' x/ a                        break;7 q5 ^7 j/ g  u/ q- H- S5 \
                        // 如果按的是增加键,改变相应数据并显示: V2 O* W7 r2 I9 K; B5 e& W1 o5 j
                        case DATA_KEY_INC:
/ @3 {$ P3 n) O% K+ A  i$ r0 z9 @                        {+ R  E! Q% t5 d3 l, B
                                switch(state)
' D% {% U" g8 v8 B                                {
2 x" J; _( \$ Q3 t                                        case 0:0 X( R, x5 ~' r* V$ p
                                        {
* D- ^7 V9 |8 [$ l. C                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);1 Y, c3 k4 b5 v, m) L; Z; ^
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        ' e4 u% |; Y4 w& @
                                        }
  v, b5 ~% {  \3 e: Z1 {                                        break;' D# D9 y" y( u) v
                                        case 1:
( j' f# @9 v) v: M/ M5 K                                        {
3 v( s, P7 a5 P+ _7 m- ]( _                                                uchar tempMax = uiD - DATA_uiD_Min;
0 U% \& t- f  Q$ C* g                                                if(tempMax < 2 + 2) tempMax = 2 + 2;, I2 Y  r3 u6 F
                                                uiH = INC_Number(uiH, 2, tempMax);                                                1 Q! i, m, ]  O  ]. M4 j* Z
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        ) A* e9 C4 L) d* C' A+ Q# s
                                        }; U# S# ]! Q* d9 a7 R; p
                                        break;
0 ^3 q  {( S, R# @                                        case 2:
! u  r! ]1 v# g                                        {2 G" G4 v! A) W" l$ Y# K
                                                uiL = INC_Number(uiL, 0, uiH - 2);        $ o; W. O( ?! H% O9 n
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
% R. C/ h4 P" }  m& l. v                                        }8 K  Z! |" ?3 i
                                        break;
4 O/ B% l$ F$ G  f                                }
* O0 r6 z# W7 c% t$ C0 P  b0 Z                                9 t# `3 H" r9 U+ }& _5 Y+ j
                        }
. U: b3 y& Y* T6 [7 O; S                        break;
* \' T; @; R8 H! U8 \                        // 如果按的是减少键,改变相应数据并显示
* O$ ~' ]) S9 U" T( b4 i, Y                        case DATA_KEY_DEC:
8 ]; i# _0 b5 a' s9 P% {  \                        {
) K7 g. t+ @( a% K3 d                                switch(state)/ h- d2 P) S9 W7 N6 L  L+ V+ a
                                {& o' S1 C& e' G  P% c
                                        case 0:8 m3 ]+ J( y9 T; I; J
                                        {: u3 |  B" g6 P1 P
                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        3 L8 I- A' K; O& s& o9 [; c4 n1 Q
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
1 Y, a. l6 {3 T                                        }
; w% f9 B5 o+ l6 b5 F3 W. v% X                                        break;5 K( k: A0 N* I. K8 j0 e. B
                                        case 1:& y8 i5 [+ F$ n/ `& k
                                        {+ J& I. G4 p' t  O- Z" K
                                                uchar tempMax = uiD - DATA_uiD_Min;+ L* U# F, Q  O: ?* [' M
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
: Q. F' f% T+ b# h0 d                                                uiH = DEC_Number(uiH, 2, tempMax);                                                % W$ \9 y  R- Q! _
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
2 H+ [0 n2 z+ V7 K- f$ X% S( Q0 ?1 m/ N& K: |4 F
                                        }
6 d: R5 K0 v/ [/ I8 x$ h3 D                                        break;% [; K. @0 a6 H# f; D
                                        case 2:
% C- Z( Y1 h! g5 l  C                                        {
# a! s, t7 a) U                                                uiL = DEC_Number(uiL, 0, uiH - 2);        - q8 a# q- a* e8 j, H/ K& O, L9 d
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        ; A/ ?, B* w4 }4 |- g" M8 {1 n
: m8 @; |) Q/ n; ?) ]% E
                                        }
, i, ]$ @# b$ b/ w. q$ s9 P+ S/ q                                        break;/ w0 E# [# [) H5 Y* t
                                }6 K) E/ F& z4 X9 H1 q2 k$ w
                                
5 w5 j7 z- ]: F+ d2 n, z. O                        }
+ r& {$ Y# L- |% g3 y: K                        break;& I9 s5 s& s4 s) b: I
                        + ?0 _8 n) z. h
                }
$ w% J, e6 e) e; s  }                ! M4 }( l! q0 N  ~
        }+ j4 y# w1 p9 ~, a7 o
        
4 C' p+ L  U5 |}: ^0 ?, S/ R: T; A( g5 {' X
% k/ V# o4 }8 C$ P: @& M
. u& O! E+ h+ H1 q" g- i

4 b$ q8 \6 ^% {// 蜂鸣器        5 S: |9 b; d5 }; P" e: t
void        buzzerCall(void)
$ N, U; q- l1 m0 S) C{3 T) I) i" o! |( R: R( a
        uchar        i;
! y, W  i7 i2 H# |0 }3 x0 x        " R& m$ q  x9 q5 R
                for(i = 0; i < 90; i++)
/ o( z0 y9 ~  H; Y                {- z% ^# v: w- G2 j) F8 |
                        io_Buzzer = 0;. z) E) O) m9 V5 `/ m5 n$ M
                        delay100us();
: Z, V1 z  u2 S- [+ t                        io_Buzzer = 1;
5 J, W8 A0 j" \3 R5 e& ?  P7 H                        delay100us();
* C2 K' F) S0 {2 X                        delay100us();               
9 y8 h4 }( X5 J+ H                }& d! N5 P0 _. s
                delay100us();        
# q: z/ Z6 G3 s3 @0 P( X                delay100us();        
! k$ C. ]( ?4 E! _2 y! f6 I# Y" P: V, |}0 r* r8 O8 Y3 H1 }, X2 T

  G" F1 j5 p* Z: F) r+ D4 i& |//计算水位
# R* w1 u' J8 ]1 H. o  l" t# l. \bool CalculatedWaterLevel(void)4 A& @( a6 j4 g1 }  Y( g7 d
{
6 Z1 L5 S8 K4 Z8 p! G        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置
0 Z: K6 z1 Z$ }0 p( S- z8 Z/ ^% k        uint          uiTime;                                                //声波传播时间
5 U9 h- I+ a; S5 e& h        ulong         ulDis;                                                //实时测量到距离        
+ i6 g4 f# m  {$ ^/ Y        5 d4 H0 J  G1 T
        uiTime = TH0 << 8 | TL0;        
5 r! i/ j$ s1 x- t, c2 m        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
# R, y" @/ u/ D+ \! z        
* @2 p1 f" U9 x6 G        TH0 = 0;6 t0 Q5 J" b! n7 Y. [$ m
        TL0 = 0;        
- H' _1 e. ]8 h" U        
0 {/ |0 w' x9 k, G, \- v6 @2 c        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;" N+ o% e; M7 k0 S2 M& J& Z+ s
        {         
. Q, s( A/ z0 `4 I                g_flag = isNo;               
1 C. g1 N7 Y. s; Y9 b: l! Y$ {                TR0 = 0;
7 t7 Q9 r% l: D9 i% H$ S                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
: E  P: l5 y  S% P' b) V               
" P; n$ q) I- N& H7 e                //阀门动作:               
- y$ r/ U/ v+ D2 O4 u2 M& @" B+ N                // if(g_flagSwitch == isYes)
$ ~8 A7 c8 }; ?3 Y2 T, g+ N8 S                // {               
( {2 p0 T  Z: B6 a) U4 @$ Z                        // io_Control_Inlet = isio_Control_Inlet_OFF;                2 k7 X) E9 K8 i% J# b( b6 i
                        // io_Control_Outlet = isio_Control_Outlet_ON;6 M& p  |4 r* Y$ A* }6 s6 U) J
                        // g_flagSwitch = isNo;0 {4 R% d/ @2 h# I2 g( q
                // }                4 r* a7 P/ L' P, j' j) F
                - l# N  v: b# m
                //指示灯:
! I& S0 I& Q; R/ a7 b, l0 N                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
# S8 p' |( {3 n5 ?$ ]                ioLed_Green = ! ioLed_Green;
) [" C8 g% t& m3 W3 J: d                ioLed_Yellow = ! ioLed_Yellow;
. A$ P1 h; b1 r/ k                / O! M& P% T' L/ l1 N2 U
                // 蜂鸣器叫:        
$ q1 K" f- Y- z9 N7 X' ^                if(buzzerCallFlag == isCall)
3 m# M6 d- W! n& X, E, s* o9 T" c# a                {
$ U* l5 M! o+ ^4 P# k7 |                        buzzerCall();                                        // 蜂鸣器叫        6 E4 K1 V7 w& n& L  U  L
                }0 P* Q0 N1 V& ^0 }. P9 q! N7 g
                , k  t1 p3 K+ f( w0 \7 s# q4 c
                return isNo;                                                                        // 返回错误信息, d0 R) V0 ~9 [( L' w2 |
        }
6 T; W5 L% M+ R; S        else
& o' y1 N3 l0 J7 s+ q1 O+ P        {, K# l8 [* b/ v+ ?
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离$ r$ g* E; `' p$ B
                2 b3 O  M; A+ {
                if(ulDis > uiH)                                                // 如果水位超高9 @' G5 r: `7 ]! P
                {
4 c% C6 `( J  F" s' o" Z                        ' X! \, d' h% c" M9 B
                        //阀门动作:' R4 ^' ~% g9 b, M) `, s' j
                        io_Control_Inlet = isio_Control_Inlet_OFF;
, v8 S) {7 Q2 ~0 h! a# R                        io_Control_Outlet = isio_Control_Outlet_ON;        $ G- t# b* _$ T% x+ i
                        g_flagSwitch = isNo;( G& Q& X" w# S0 S2 H3 l$ |- O
                        
, v: g4 @, p. d) m( l                        //指示灯:
2 v# D) w1 l/ F  ~7 T2 {  u                        ioLed_Red = ! ioLed_Red;                        // 红灯闪& k0 j- N' c" l& B! N1 q
                        ioLed_Green = isLedOFF;                : H) n; L" T0 B; V" }
                        ioLed_Yellow = isLedOFF;                                
9 g: S2 }/ A$ U( Z% B* i                        // 蜂鸣器叫:
% n" ~1 z; x8 @/ q! d8 }                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警$ }; B% m. c9 l& \0 M4 K
                        {( Y9 r' Y) C( t- L; M
                                buzzerCall();                                        // 蜂鸣器叫
: H) \9 @2 ?! b/ f% }1 \8 u" B                        }1 ?4 |- E6 c2 f' ]* g
                        
; k, Q; @6 ]* V6 r  |6 B4 y, X                }
) I/ L- p1 S; D1 E                else if(ulDis < uiL)                                        // 如果水位超低  y+ g; k* x4 u& [1 T
                {& z. z+ b. A0 h4 Z7 `3 q
                        //阀门动作:        8 d$ o& x# S9 s8 Y& a
                        if(g_flagSwitch == isYes)
0 l) s" D+ ?2 M2 N( l9 h- K                        {               
$ c% Q4 V% m9 K* r. c0 i2 o                                io_Control_Outlet = isio_Control_Outlet_OFF;        . E# H( H/ B( N( v
                                io_Control_Inlet = isio_Control_Inlet_ON;        
; j$ m* i) a* v6 @                                g_flagSwitch = isNo;
) U; c, n; r) X+ s9 I0 n                        }        
8 x0 J$ L! u# f" {9 w' ~  ]0 b' F                        ! z9 D  R0 m: V$ ^5 \$ M0 m6 }# h- R
                        //指示灯:5 [( Z7 X0 T8 V
                        ioLed_Red = isLedOFF;8 v' d$ i) J  r! Y
                        ioLed_Green = isLedOFF;3 y- Y. V# X; I" Y& x- B
                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪
% w( s+ b, ^% f* X                        // 蜂鸣器叫:                                                
. s3 B( N' f( s7 M$ B                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警
' B+ ?3 G" ^+ R$ F. N2 U3 U; u                        {9 g; @4 w( E" z! m5 W( d
                                buzzerCall();                                        // 蜂鸣器叫8 E' Y3 \! V7 t* F6 E8 V
                        }! N" I1 a, ]* r8 A$ f( M
                        
/ I5 R$ K1 I* Z  w! W& k7 E                        ' T( ~8 g' n2 V+ B5 p
                }
( q$ W2 v0 C( V4 t                else                                                                // 水位在正常范围 / E9 x, l) L' X+ f- C7 m
                {        
. ]( V% k4 r% a; }4 p5 K                        ioLed_Red = isLedOFF;4 \$ m: F" Q' `" n' R% \1 a  V2 ^
                        ioLed_Green = ! ioLed_Green;8 ?1 L% }$ d0 D* T% _4 \
                        ioLed_Yellow = isLedOFF;        ) t4 x, d7 f. J% U1 G
                        - G# I. F4 U! D' N, Q4 G! i7 ~/ k
                }
8 ?+ f& ^9 B; H3 h' O                putThreeCharToLCD1602(lineTow, i, ulDis);
/ X" h$ Z' k* ^! N0 J9 j                return isYes;        . b& u( N# S* o# ^; Z  @: P: w
                $ Q) F" e3 ^2 s+ }% C8 V) _( K( z" g
        }
7 a# F0 Y. Q5 c6 ?* h        return isYes;- d4 n5 O" I% @6 l3 i' I9 ]  `
}/ g# [' J/ w* g
, x" z$ J1 D5 t5 t' X( Z
/*********************************************************/" R) f, l- y. Z
void main(void)7 {8 Y6 R0 ?# Y: ^2 G4 D4 J: u# A
{
5 V+ n4 i' D5 t$ G; ]. a        initIO();                        //初始化IO端口        
4 f9 b+ ?2 V0 q6 S" \& l        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        
. |% c$ U3 P6 d' Y: O& H: ?        initLCD1602();         //LCD初始化        ) A9 I4 D% A# Z: n; N" K5 I8 p
        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
2 ]' Y1 Q$ R# e        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值7 u9 C* f+ I7 v: S
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H. S! I. }0 @- v/ j. N+ ~2 C
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值
5 c% E# k- ^0 Z9 J# Y        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L
% _3 s- d; a/ G* P7 y" L        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值
. {  x$ ?* f) i% u        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C
) j* s2 Y$ u3 u, l& F( Z        
1 S1 F! Y( g4 M% `' ]3 S' s& ?        initTimer0();                //初始化定时器05 X+ N1 o  f2 y' H
        initTimer1();
( H" K" q7 _: e* D% {        
4 f8 L7 Y9 _. H$ r        //阀门动作:初始先排水
) I& m5 S9 y. [: C# E. O+ [$ \$ Y        io_Control_Inlet = isio_Control_Inlet_OFF;        
; B2 M2 k+ O# E  D& e        io_Control_Outlet = isio_Control_Outlet_ON;1 Y  o) n; z" V  o
        g_flagSwitch = isNo;        
- h& q$ U) w& t' Q        
, t" X$ y/ G2 a        while(1)7 M0 X0 R; T3 t$ h) Q+ k
        {
5 F+ v( a# }3 |3 R                io_US_TX = 1;                                //启动超声波模块信号2 P: P6 T. g# K. V
                delay10us();  r9 m) S! f+ l
                io_US_TX = 0;/ u# H3 Z  j/ [: c
               
# V4 r3 f7 ~" M% J+ x7 u. k; Z3 t                while(io_US_RX == 0);                        //等待计时开始
7 C0 [' L; F; m6 q- ~                TR0 = 1;                                                    //开启定时器0,计时开始        
7 ^  B! f) _' B! f/ s) y                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
$ `; Z. F) k. N4 f, y                EX1 = 1;                        //使能外中断INT1               
! o/ M! n/ x5 V, Y4 u0 h8 S               
% a3 O+ R2 v% i; h% ]9 r) j                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        # v0 ?. ~- g1 |- r2 ^
                {) }2 W9 W7 w# J, f7 u* c2 s
                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
+ q3 C1 \4 g6 U- t                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
4 \; ?0 L1 k1 t% V8 P$ x2 b                }
9 S6 y* A; C/ O5 y                4 i  E. o7 E( n1 c. K
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环                ( j$ s7 G( I( F+ y* W, e: R
                7 _& R' }5 ^" F2 `) O2 f: p9 o% {2 u
                TR0 = 0;                //暂时关闭定时器0
, m% v+ R' J7 y: R( g/ I7 n' T  d                //清零定时器和计数变量以及标志
9 M1 @0 Z8 R" a# R6 v! L/ ]0 n                TL0 = 0;               
$ v' R& H! ~, z/ n, J                TH0 = 0;               
/ _4 Q9 J/ p& T4 t6 e                g_flag = isNo;
/ q8 @5 E# `5 Y$ G& b2 c                ucCount = 0;5 J7 I, r+ Y$ k/ p: {# Q
                g_flag05s = isNo;$ t9 ~* f$ ?8 z: e/ d
               
. T8 I% P" b' p, A5 S/ s                TR0 = 1;                //打开定时器0                                        5 C3 M1 E% f& k6 T, E7 O
                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果
. \1 i* \% s5 x; _9 @: N1 ?                {                        
- d1 \. _7 d5 Y* v/ J                        uchar ucKeyValue = GetKey();  {# f  [% c0 P# z+ Y' a% E
                        if(ucKeyValue) 6 J+ R# f+ E: a1 J% d
                        {
) ^' L9 ]& S" [' i( e# p                                if(ucKeyValue == DATA_KEY_DEC)
) J, }" G2 f9 N# M                                {% h8 q& C' b3 e4 _3 {
                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志7 c+ c  _1 [% |8 y* _2 G: s* ?
                                }
& ^3 }& H- x% t4 P$ O/ q9 I) k& x
" ~8 s) Q; a5 U$ L# A# `6 H2 c# q                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
( t7 s/ d, y$ ]+ }) V# K                        }                                
( b, K2 ^; P( T: |' j2 J4 f  c+ k: B( ^. t! E' z1 p
                }        3 j5 o# h, {% b" X
                TR0 = 0;                //暂时关闭定时器0
( w4 t. `! I+ t* J                //清零定时器和复位标志
5 B' [% v  A4 h                TL0 = 0;        8 k) z1 o$ {) A) D: i. p; l
                TH0 = 0;        : z5 R/ G8 V& d  H0 y  T; t& |
                g_flag = isNo;               
; \: G6 w3 v3 Q" _* F               
) ~: p! Z' K2 n, ~                //-----------------------------------
: T1 Y. E. w' A' M% A                //水箱清洗提示:
& z. G% q: f: i5 j% U  ~               
0 Z( [; T. x( ^                if(g_flagBeepTimer == isYes)
6 e% E* B+ C) M0 c* B# l3 C% s                {  V6 y+ E+ [: P  x8 B8 R
                        buzzerCall();                4 A0 v/ V) Q3 r7 r. H# N$ }
                        //用减小按键取消报警标志
! c! Y- M, E+ t. i* x                        ) h( W6 }: Z6 u6 a  |
                }2 V: q+ c: V: {$ O  d7 p( Q% q
                //-----------------------------------% y- Z% z+ ~9 b* h
               
2 @# b: ]1 I3 N        }
& F1 D1 d" ^/ Y8 g0 z9 C3 D}
/ t  }5 _6 ?9 _, m5 b: n; E
  l+ c9 ]+ P0 d$ f( D; I, ~: A$ u# M5 T  I4 t3 q$ `6 ?& J  B: n
#ifndef __MAIN_H__' Y9 K, P0 {- w# B2 }, n
#define __MAIN_H__
* Q9 J$ a. D) a* Z( Z5 I
# J4 l. [' @+ X7 J1 x//-----------------------------------------------4 D' R2 X( g$ m2 v- \8 i
typedef unsigned char         uchar;        //为了方便书写定义别名7 f" E" L  Y7 i- ~+ ?/ G- n' A
typedef unsigned int         uint;
8 T$ q( ^" O" ]  }typedef unsigned long         ulong;3 ?! `3 E/ h% t# f& y9 b
typedef        bit                                bool;
+ E% x- n, h) d2 t8 D9 z5 x
4 l1 Z/ q8 F  t) t' n' Qsbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口
# S$ d" r( ]2 w/ x' r. W5 p9 v#define        isio_Control_Inlet_ON         0
" r9 n8 |( Y0 |& S. i! t- Z& c. Y- o#define        isio_Control_Inlet_OFF         1( m8 v, `7 ?8 K

' g/ o! ~. W) ^5 ^sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
# d! [, t4 q) ~& t- f7 ?' c: I; I#define        isio_Control_Outlet_ON         0
! R( ?+ c$ \/ c  P. Y' d# l#define        isio_Control_Outlet_OFF         1
' w/ K! M- x0 M. h
4 y: V0 N1 j9 U1 O#define         isYes                13 @" }: m3 k) T+ E
#define        isNo                0) N* M+ x2 [7 s6 g/ }) e
//----------------------------------------------------
# f, t" C. j0 d5 G3 P2 ]//定义超声波模块引脚
! J2 D* t: {7 ^' l0 u/ Q* isbit         io_US_RX          =        P3 ^ 3;        ' k. a" n1 v3 R4 V
sbit         io_US_TX          =        P3 ^ 2;
$ r3 B: C6 ^0 Y: J; b//----------------------------------------------------$ H4 v7 M& A" J* Z% V$ K$ L' Q( {* |
//定义LCD引脚
  n# Y! S1 \9 {$ vsbit         io_LCD_RW          =        P3 ^ 6;
- G! a7 `4 l* x$ M+ X* l2 lsbit         io_LCD_RS          =        P3 ^ 7;
# @" g6 L% I; Usbit         io_LCD_E           =        P3 ^ 5;            
9 k$ e+ q) A: ?6 Y#define          IO_LCD_Data                  P2
5 c0 i6 n6 J4 ?9 ~' F#define         lineOne                        0
' e  V6 K/ }# {1 T, l7 O#define         lineTow                        19 ]0 t3 S$ R; J2 q
$ U* w: `8 C1 Z) `2 W! S
#define        isReadBusy        15 k/ u  E& B2 U
#define        isNotReadBusy        0
  |9 a6 `: f+ b- k- t6 z+ x% O" ]
4 w% c5 T, R. e  V#define        DATA_LineMax                0x01                //LCD最大的行索引数
4 P0 ~% ?% {( u9 {+ i0 Q#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置7 v! m0 C! h) T3 _% b! p% p- ?
#define        DATA_LineTow                0x01                //LCD第二行的索引值
: @$ O6 K. Y* U: |; x5 g, h3 D//-------------------------------------------
# {( F5 H$ b) q) v$ u# _) i) r#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时
3 B2 _3 |/ x# A5 K3 U" z//-------------------------------------------------
1 W* {  m: G+ E( M! h// 定义指示灯端口
% @# j7 l4 K+ ~. Msbit        ioLed_Red = P1 ^ 3;0 ^; X! K4 C0 V* P" N
sbit        ioLed_Green = P1 ^ 2;
4 S0 o' R. C' T$ W) asbit        ioLed_Yellow = P1 ^ 1;2 k5 W$ a! f& H/ A5 i7 W$ r
& Q3 {/ H- V" s7 F
#define        isLedOFF                1                        // 关闭LED3 a( y7 E  S! ?
#define        isLedON                0                        // 点亮LED
9 v+ j+ ]6 a" T2 a2 G' ]# Q//---------------------------------------------4 k# _+ }3 s0 E  W
//定义按键端口
/ ?  K6 f: \$ u3 z#define        IO_KEY                                P1        
6 J  ]2 t4 q! x+ N  p' D4 W7 L$ h  V" c$ K& y5 h" o% V
#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据. v: B( m' K9 \* ~
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据4 L/ U$ |, v5 @7 R9 ]( l& `2 A& G
: z+ m" a* T! B) h
#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据6 y8 }6 D+ ^3 ]( f+ d
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据5 s+ _  S2 t- Z2 p, |* [
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据2 q" H* Y9 R* I9 ]/ [$ o7 o/ ?
//---------------------------------------------
2 L% S: _: v4 t/ I: V/ P//定义蜂鸣器端口
* t" F) L; C3 M( `) [! {sbit        io_Buzzer        =        P1 ^ 0;        * g5 z& E4 w4 X. P! @! G+ a( @
//---------------------------------------------/ v0 s# F/ V0 \( c
//定义检测探头到水库底部的设定距离范围 程序.jpg
+ B; y' Z4 {- F/ H#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm& \9 X+ y" o6 ~/ `6 Z5 U5 B$ H
#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm* h. y: W4 v' T8 F, d& M  g
! V* n( c" U$ O
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
0 m- T$ V# T) F$ f% t5 w. w$ Y9 b0 ?; m#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护): V3 H! b# w7 D. \2 d6 ^
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
0 r- [* l# F+ P3 `, N6 T1 i( l5 `! E* b4 K; @" \( i" w; b
sbit        buzzerCallFlag = P3 ^ 4;* b% a! Z# ^; W3 i+ a
#define        isCall        01 x& y$ U& f( L  ^' E9 G
#endif
$ u' X8 R, z$ c( ^/ N( l3 O; n* g; u, G0 R

0 r6 A; v5 D" P7 r4 w3 l) W6 U
/ X) k7 n: U* E0 u! \% \1 z. c. M8 t: 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
/ o- E( M1 F5 q& p) F' R/***************************************************************, n. n/ l: N8 t. E4 v
        名称:基于51单片机的超声波水位 ...
# j! L' C6 _7 m/ w+ ]% _! A- n
又下载一次,打开跟你内容不一样?; J' x% f+ N; r
QQ截图20201211202119.png
 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05
6 {4 J! N* K8 C* B+ A: x大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?
: h, {" U, @/ t# P/ z
是的、是物体都可以检测到!/ Q! Z: _: [2 n2 w' G3 s
发表于 2020-12-18 14:55 | 显示全部楼层
程序Keil、Protel99下载不了怎么办呢

本版积分规则

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

GMT+8, 2024-4-19 20:06 , Processed in 0.104807 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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