一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3862|回复: 7

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑 + l% N6 q2 Q( @

1 `; l# c5 c. k& c$ R
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

+ l- |, X: E7 c: E. `
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.
* x  S4 l: n4 o
按键功能分别为:设置键 增加键 减小键 复位键
* T+ l; s+ j" i/ P- i& ^& c, |
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)
" I4 r9 f1 u/ n/ D! K
发表于 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 编辑 ' y% h; B2 l1 y  C
tdc31224 发表于 2020-11-24 20:58- i: s' c" j' `1 A6 M) \0 U
没程序?
$ Q, F& w( k- X9 W+ g, D" Q3 }! Y

* H/ w4 t. @& k' E/***************************************************************% e3 i2 g" T4 h3 |. ~- e/ v
        名称:基于51单片机的超声波水位监测报警系统
/ ~4 Y9 K( h6 {% N' Q        单片机型号:AT89C51# E# W, [0 p9 s
        单片机设置:时钟12T,晶体12MHZ' C4 s9 y6 V# o; }
        注:修改增加水泵控制和排水控制,即双继电器
- R& w; e% S! z2 s; R***************************************************************/- `4 k: e8 {9 P7 u6 f

. Z) |, b; O8 i  B0 T# T% W2 B+ t' S#include <reg51.h>
: l8 x. m4 c9 Z. N0 a. a/ \#include <intrins.h>                // 包含循环移位:_cror_
5 Y/ b$ y) L5 H) a/ X#include "main.h"     . J1 O+ [7 J2 K
//----------------------------------------------------------------------! `7 m. j7 ]3 }2 T/ D! s  b

! T. ]! H) f* u- ]uchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};2 f% o6 Y! R" \+ }
% I& @7 W9 l- x& G1 W+ O7 N
bool        g_flag = isNo;                //用于标记超时(65.536ms)           
: n* x( e2 A3 |0 Ubool        g_flag05s = isNo;        //用于标记0.52秒  
  S4 J: @2 U- g2 |: \uchar         ucCount = 0;                        //用于计数0.52秒     - W" a. ?3 B. {7 l; |
. x; e0 o, s( |2 n
uint        uiH =  86;                        //设定的最高报警水位 H
" C) p0 J5 I- Q' }& puint        uiL =  73;                        //设定的最低报警水位 L
0 X9 ]9 o( e: \( auint        uiD =156;                         //检测探头到水库底部的距离 D , r8 |/ h9 r5 o" ]$ G8 L$ y
% r& E0 D' @* a3 N6 T! e- [( {3 R
bool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志) E5 z( j9 K6 R6 O2 ~: m7 f
bool        g_flagBeepTimer = isNo;        //定时提醒标志. |# U6 |  t4 e8 {% s6 g8 ^9 l
                  u5 F/ c* C- e( C) v( c
( Q8 z- B" E% q
//-----------------------------------------------------------------------7 u) Y  y+ L3 `7 J$ y
// 延时10us: o$ y1 p1 X1 z) @/ d
void delay10us(void)                //@12MHz
; b. G* ?6 p. G, B/ A{  w. y  n) F6 q6 M1 {5 M$ }
        unsigned char i;
0 ?; ^- {: h, h, {' v
) v* ^; X# c0 G% [        _nop_();
3 M4 j# g3 D  ?9 U' G7 X" ^% w        i = 2;
- Y& ~/ q+ [5 f1 R; }9 c        while (--i);) z, H( o5 o" r9 q  }9 p
}
( z4 h/ x9 e; U9 I1 H7 W
! x7 v* r# {; R" X// 延时100us
$ i- f3 r" `  \9 Gvoid delay100us(void)                //@12MHz
' i* u- r" U# u% R/ w{& V9 C6 r9 r# S. y5 E% N
        uchar i;
1 M2 j2 \$ J- `  i5 P. ?* w2 s, \) [6 z0 g7 d6 F6 a8 g0 F
        _nop_();! P  P# t  M) {3 }: U( L9 T
        i = 47;
+ t+ M  u& t& H- w2 {        while (--i);# J# K4 d3 A/ I' V+ \
}
# e  `; X" |$ T4 e- r# C3 a7 |3 E
3 h+ G3 @3 W8 |" c, f// 延时125us
+ S8 L. x2 S2 J. K- X1 n6 i- ^void delay125us(void)                //@12MHz' g) b+ X) h* s4 r4 w) ]
{( K* {! e% `0 I5 y
        unsigned char i;
# ^& b1 K) C* y9 A$ k, S        i = 60;
$ p: B6 j: o, b8 E1 Q        while (--i);9 \! W) Q7 P9 O
}) y8 W6 {0 R0 d3 S4 ]
2 v/ }, m& U! K9 i
// 延时5ms; \% v, y8 H4 K% J) L6 x
void delay5ms(void)                //@12.000MHz% x, _1 {$ z( T, ^" `$ C& q
{
) h. R, y; X% ]& A8 q+ e$ J7 f6 g        unsigned char i, j;
  B4 t0 x+ q) x7 O+ Q( v2 z
& @4 h0 Q/ g* ?1 s, K# k& s        i = 10;
- m7 q( r5 {/ B8 U9 ^3 X$ v& A+ O        j = 183;
( G/ h2 @+ X. g+ k% O2 P4 m0 g        do5 `- b3 K$ P* K9 Z" [1 d# {/ {* H) o
        {
2 W, h/ E$ h$ W- q                while (--j);& @; o7 Q- y- H. @8 f+ ~3 ^2 B* x9 Q
        } while (--i);( {+ P0 V8 ]% x+ e9 r0 q2 n
}* k7 {0 g* Y0 {2 Y

9 z4 o  d( R: ^4 T( l// 延时500ms; ]! l0 X4 i& q4 L
void delay500ms(void)                //@12MHz+ e: w: F' k* M# u
{  ^0 j: A. Z* A! J3 G1 c+ d: m
        unsigned char i, j, k;# T/ _$ P* e/ w1 ]
6 L; [" _9 C5 d
        _nop_();
+ M- Q. P! G* j5 L3 ?1 N8 P! V' a        i = 4;9 W; r, w) D4 x
        j = 205;
8 y1 C' M( `: h! [4 i9 [        k = 187;4 B4 |) Y" G5 `2 n+ ?8 ^
        do
) U) b0 q9 w+ j" ~$ ^7 O7 `        {
+ X% S" }8 w$ J5 _7 c% M7 @                do- l: L0 B2 E7 l6 L0 m4 r  f
                {: Z0 a2 k6 B/ `1 O5 J
                        while (--k);
1 Q: D" D& B8 f, y                } while (--j);
2 f8 c1 |7 e" m1 E        } while (--i);. G3 s, M2 X1 b% Y( R
}
/ p  M9 `9 A) D' d3 q1 [
( j! E0 h: A" e# p7 L- ], p0 m//-----------------------------------------------------------------------% L# y- M* W9 m0 a# s! c
//初始化IO端口                        ; \- k6 d# U9 I( v
void initIO(void)                                        # t+ f' n# B7 X1 U7 s5 k
{, v8 x1 v7 r4 C: f2 q, s
        P0 = 0xff;( H4 b9 `* S# j0 D+ |
        P1 = 0xff;
: b2 J6 ^) ]  f6 y$ A        P2 = 0xff;) g8 W* M) u) U9 U* r5 e/ B
        P3 = 0xff;
4 L2 Q! p% ~* E}# K+ f* s5 Q' {
! s9 `* {6 N/ E5 Q, p6 e. ]. S. T
// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz  Q  a9 a8 T* X3 X/ c
void initTimer0(void)                # b; p* U3 q" t: v1 n
{
) ~/ z( O$ j$ a        TMOD &= 0xF0;                //设置定时器模式- S& `6 n/ Z; ]4 `" L
        TMOD |= 0x01;                //设置定时器模式* R) S: R- J8 b2 Y# J3 O& _) ]
        TL0 = 0;                                //定时器初值清零* b3 n4 }0 t' L& o
        TH0 = 0;                                //定时器初值清零3 k/ S/ u' F% _: X0 L7 w# H
        //TR0 = 1;                           //开定时器0& u, M3 a" Z" v6 F& ~, M. {: h" N
    ET0 = 1;                          //开定时器0中断3 M; E! ^) D( H# c# \! `/ j
    EA = 1;                             //开总中断            * Z$ l7 d, w2 H8 Y9 Q9 w
        0 [/ b$ ~2 E. Z& }
}
3 H. X' V# u' q7 `  c7 l
' [" G5 l- ?$ S/ ?// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz
; V* L/ I9 g8 M% K6 ~* R& b$ Cvoid initTimer1(void)                //50毫秒@12.000MHz
8 ], n; z; R8 j6 x# k9 J{        
9 M* M4 D6 ~4 F0 }* d        TMOD &= 0x0F;                //设置定时器模式7 i( Q  W5 ?/ e2 V- h1 M4 J
        TMOD |= 0x10;                //设置定时器模式
& Q5 B( A( `9 y2 `. h; B: J( V        TL1 = 0xB0;                //设置定时初值
3 K. F1 Y2 d1 l$ s7 ^9 d4 G        TH1 = 0x3C;                //设置定时初值        
  U/ M1 ?7 ]9 D( F: O        TR1 = 1;                //定时器1开始计时0 K5 S, |6 J3 E) H
        ET1 = 1;          //开定时器0中断
4 A8 \2 l5 \: [$ n2 P2 N9 ^}1 `, Y" G, v& n) U

+ L1 u0 E5 ]% {' M$ o//-----------------------------------------------------------------------# M  @1 j& p( y) Z% H- S
//定时器0中断, x1 `7 Y' P& b1 C
void zd0(void) interrupt 1                  ( T4 ?  l4 V+ c! G
{
! A/ a0 B& G5 z: O6 j( h4 y8 o        2 Q/ z. T2 Y7 s7 Z' E3 _* f* l
        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
% n0 O0 ^& ~) e* O! \( J  ]8 }: [        if(++ucCount >= 8)
" k7 M. S5 f. v- E        {
- c$ d, \: `  n1 |+ X                ucCount = 0;
3 l) V! o% E9 P9 C9 l5 Z* t+ D; `                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时: }! b# {$ c% K( U
        }! |5 t* x# e/ @% `6 Z# T4 Y
        TL0 = 0;                //设置定时初值
3 E  T' N* }6 B, t" }        TH0 = 0;                //设置定时初值1 X/ I' a/ [& I' m
        
1 w- k& q% [( y8 @7 ?  \}
/ A8 C$ D; V+ Z# |+ A" i  J! X8 ?) P" p' E% C  ~3 K3 v; D
* N$ ^2 Q) l3 J# k/ F
//定时器1中断 定时50ms7 d$ M4 n" E" A1 F- V
void tm1_isr() interrupt 3 using 1
, ~+ ~' ?, r# \, P/ j5 S{
% g0 F+ l, T- \; z+ t" Z        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S
) L# ?  H# k- l& k        static uchar uiCount = 1200;                                //                        = 1分钟                $ @! B2 X' H9 C
        static uint uiCount_BeepTimer = DATA_BeepTimer;
4 r5 T# z' v( p. m& s" F, f2 F8 w$ p0 v( k% ^" z
        TL1 = 0xB0;                //设置定时初值1 C7 z! R# a8 z6 D
        TH1 = 0x3C;                //设置定时初值9 z2 C) u& i: j6 n1 W& J

& j0 _/ _8 Z7 F& w        if (g_flagSwitch == isNo)9 f8 z4 l4 h; G6 K$ o0 o
        {; G$ L5 }- ~6 e" T+ G: c
                if (count-- == 0)               //50ms * 200 -> 10s- L+ W6 }  b1 j$ ?& p
                {
2 N" J# ~  t' z# v4 k3 e$ ~/ [! j                        count = DATA_switchTime;
7 D% ^- |( I9 y& ?- z; v+ @                        g_flagSwitch = isYes;
$ _/ x, i+ A" x: E, u& i9 v                        // TR1 = 0;
9 @: b* q+ \3 W5 \                }
4 A8 p: |% Y1 h0 V        }        
! V/ \1 R7 i: W' F        
' w; Q  t' I& ?4 A# M; h0 c        if(g_flagBeepTimer == isNo)- X8 t8 D* B9 s/ o+ d& H+ L. h
        {9 k. M  U; J7 U  @1 ]9 c
                if (uiCount-- == 0)               //= 1分钟
" U; z7 y% B1 V0 ]+ A2 b/ b                {. p2 i& \& n/ |- f: Z
                        uiCount = 1200;
$ [; e% @: @9 R7 G                        if(uiCount_BeepTimer-- == 0)
3 B7 _* D# N8 h& ?. ^                        {' a* A& C/ R4 ^+ J& i5 q+ z
                                uiCount_BeepTimer = DATA_BeepTimer;
. O9 e; _. }) L. r                                g_flagBeepTimer = isYes;
. K) j2 f& m% v5 m9 D  o                                // TR1 = 0;
+ Z* L' o7 {6 p$ W: z: B, U                        }                        ( l$ p: W* b, }
                        
7 y  }. v- l7 I- ~) A: @                }
2 }2 o5 h2 V7 i7 Q; p7 Z) W; ?/ ^
' s" z1 M; F7 \& [+ R. y        }. [( L% X; ^2 k: r$ x) j
}/ b2 n% K; R- f6 A1 g
, x  y8 S/ O! i5 a8 g
//-----------------------------------------------
8 @, u9 Z( v) k9 m; H- j" s9 \4 B( g% k
9 U$ f, W1 N8 g% y
0 s- X1 G9 a# a3 K; P5 K  V3 ~
- v/ t( M$ `0 m" Y( U3 _; z- l4 Q$ ]

! i1 q- l! \# M! h) C" m% ~" X//外部中断1
+ U  w( ?7 N3 a9 S' C. Dvoid exint1() interrupt 2 9 |( t# x* M) `5 ^; [' l5 F- k
{
+ a$ i) ~% D+ d7 X: F0 f1 Y6 c3 G    EX1 = 0;                         //关闭当前中断
1 }+ l3 x4 D1 j; P        TR0 = 0;                           //关闭时器01 ^  S# T. _8 u! r0 j; ?5 W
        % L, n3 y3 U9 L6 @$ U
}$ u! a+ S* q. U7 e" y
//-----------------------------------------------------------------------
9 M9 a+ B  V, o% M
5 Z/ }- U6 z* M) C4 X//读LCD忙状态并等待忙状态结束, C( Z$ N5 M6 y+ r5 {  N, `
void LCD_waitNotBusy(void): r* s1 b' [- G! W' Z
{
" d! h6 g+ m  G: N; l: D        IO_LCD_Data = 0xFF; ! ?5 P6 p+ |# M+ {3 w. a4 s; `
        io_LCD_RS = 0;$ A( U8 I' O- Z+ c0 e' I+ ]
        io_LCD_RW = 1;( }. e5 {4 @$ @2 ?! ~/ h
        io_LCD_E = 0;, m! w! j; J: ?1 @$ d
        _nop_();( N; e2 R+ ~" x5 o9 d' [# B. O/ K
        _nop_();
) [+ G; _+ c, k. ?: |% O        io_LCD_E = 1;
, u( l" g  T6 S4 T6 E# @        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙/ D: o& V; ^- s( r" b# U
}$ m  A' ~/ F9 s. A

5 G, D8 y4 A( {//给LCD写指令
! _% b( D& @8 F  L7 lvoid LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
% A9 M8 `6 \3 y{" C5 p! {9 z; x* w+ F! p
        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙$ T- x2 U) A1 H+ w  Q' f
        IO_LCD_Data = command;8 `8 J5 N. k7 H5 F
        io_LCD_RS = 0;6 x! Q+ P3 I  t  K
        io_LCD_RW = 0;        % V* k# [8 y. X! G
        io_LCD_E = 0;8 p: H- G+ Q3 t2 ^8 P2 j% s
        _nop_();
! I9 j, z0 j0 b- N5 @+ `        _nop_();
4 ?. O  n5 [9 Y% l% i' V        io_LCD_E = 1;        
) ~+ n2 f/ z7 L4 J; l}' a$ z2 g1 |- E

. M5 ]* i3 j# |' h//给LCD写数据$ R' A( M) d4 E. Z7 {; r" O7 g
void LCDWriteData(uchar dat) . F0 w0 V* P  w; O3 J" I, \# ^
{
# Y9 I& D. Q% J: ?' G; r! Q        LCD_waitNotBusy(); //等到不忙
. P' c2 ?4 b& T        IO_LCD_Data = dat;% x0 Q/ l% Z# |6 F. Z$ D: w- d
        io_LCD_RS = 1;
2 L. P! ]& N9 C4 M( C$ \/ f        io_LCD_RW = 0;
+ _. J! x& s. I# i! Y$ e" Q! l. \: c        io_LCD_E = 0; , ~* }0 ^$ z: A% j: j3 t1 o
        _nop_();
6 c6 D) Z8 M# T- g+ X        _nop_();) M! c" l$ W2 W7 p% B7 d
        io_LCD_E = 1;
3 U6 L. V/ c4 L! N( q% B# I}
8 P3 d; k* w6 _/ Q
) K8 L6 t5 ]) Y) e! F6 m/ O8 j4 W6 r/ S; U5 z/ Z8 @$ E

5 D# |0 ?& C% z  j* N# a8 m% V$ ^5 f- j. D6 N! w" l
// 初始化LCD1602液晶显示屏
$ Z) o9 }7 f; w# {8 M, q% F/ Y% }  T1 e9 evoid initLCD1602(void)
  R) a5 z5 S2 W9 s9 R{
" a# o! z# `% v( u" a) ^        uchar        i;        
* D' r+ y, H$ t: [        IO_LCD_Data = 0;                                                                // 数据端口清零
9 E* b' h% I& r5 K( P- y" ^        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
. E) u5 D. d4 D$ X. s- A% m. K        {
; B, T1 E) ]6 F9 ~+ C                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号. ~( z! A7 h# m7 E' M5 |+ z$ K7 E; Y
                delay5ms();9 t' N% ]; k# {. o/ g; A$ a; \/ X% C9 _
        }3 j1 I& Y% P+ v  A7 \3 {% s
        
0 f; _; k9 l" r3 Y% u% _; i        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号
; G6 `# [* M' x3 m4 h8 C/ H        LCDWriteCommand(0x08,isReadBusy); // 关闭显示* E+ u( Y5 a1 l# k9 h
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏; k, Y. I/ A! b# X3 i. e6 W
        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
3 _* i* X1 G; A1 E        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置' L+ s6 a6 E: b1 h+ S, t8 s1 m
}
4 x* L, C! j& e+ t
4 e$ U# e  `! ^. W% w* G5 Q4 C6 t
9 ]$ t3 h' c- M: p, q  Y. E9 }5 r2 |+ Z
//按指定位置显示一个字符8 e9 W# G$ @% j7 e0 d3 C5 g$ t
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)& C$ Z8 k  G0 |
{2 U: n0 O: L6 o6 J" Q( C
. M! }+ H# ^8 Y+ s7 x8 }8 l
        line &= DATA_LineMax;+ k6 p  G4 Z6 r* `
        position &= DATA_PositionMax;
* @9 V! E) u- B; }7 H  j) u        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
! E, o# R/ K& l5 s        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
$ v) |- z. ?6 O- ]/ f        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址% f8 C0 `, g3 ~' T
        LCDWriteData(ucData);                                                                  //写入字符的数据        # L) _3 Z( L5 m; D; M0 E6 r, [
}
; I6 y$ p  `2 m2 ]: T- [
, U# r* D$ Q6 b( w9 {$ l0 k//按指定位置显示一串字符
+ Q( Z5 _) d, Y* S* {8 cvoid putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
) G5 ~2 F9 M9 h8 B/ _{. O6 V. Z# E# q1 G
        uchar i;& i; N' ~7 G5 F2 v; o6 g7 G
        for(i = 0; i < count; i++)                                                        //连续显示单个字符
' t8 ?( w2 K- r' C        {% H0 ^( w6 O" ^1 F* {4 U, T
                putOneCharToLCD1602(line, position + i, ucData);        
) Q2 [( _+ s( O  s" p7 \# K        }: q0 ~) O) m7 `( N; H: u
}
# d" K' U$ {- ], \! S6 W- Z7 _: v( U8 T! a6 M$ D) Q( k/ ]

; a( Z: _* R6 L$ ^+ t7 f//按指定位置连续显示三个字符(三位数字)
+ z( c% f( S2 w& [# _# C5 Zvoid        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)
5 k% V) h2 w6 k0 W1 S$ T1 y6 I{" _. [: S$ p$ r- A
        uiNumber %= 1000;5 \8 ~1 D( [5 @1 e
        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);% g! |6 ]; ?) }( S" T) i
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);1 G9 h1 i1 P: k7 q  F3 w6 r
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
9 s  }  Q' l5 u6 W: W/ ]        $ F, h6 p2 r5 s1 h  |  k
}( i8 u: z$ E7 m6 n+ b1 i
        
. Q- U' v4 ?3 f
: ^1 a) s/ v" m
& o1 _3 D1 h& ?# a. \9 O% H// 按键检测子程序,有键按下返回键端口数据,无键返回0
/ J# |9 b; h: Kuchar GetKey(void)
: ]7 {  g0 G7 J/ V7 f- Y{        & \0 k: ?8 |* [7 G
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        
/ {* s# F7 r6 L5 A  v9 q# `        
# }, Y2 v- u( F* |/ ~( x        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空& m  f% S8 U$ P2 M& L& v$ }+ n* g" W
        {
! [  U; `8 A' j& J! Z& Q                uchar CountTemp = 0;
1 ?: v4 i: T% h  T' Q- I                do
7 Q0 m4 R% T$ X5 J: v                {
! S$ c5 O' v8 x7 o+ }+ q                        delay125us();
# g  m  x) V; U# J" ?- j7 ?- m                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
+ A* P( D. V7 Y, c, }& E5 E& s                        / G0 ?8 f1 _5 B. ?
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动 1 [" P% E. g" }% h' K6 Z
                . N4 U$ \8 m: d
                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
- z! ]4 o) t7 g" }; Z, n# b                8 S; y. E3 _. S3 h/ |. B
                return KeyTemp;        // 有键按下返回键端口数据
2 J; L: D; R# k- t. ]/ l( b! h        }
+ L9 L& x$ K/ _4 ~! ^, L3 @7 F        , l2 I1 e0 E# Y7 F: P
        return 0;        // 无有效键返回0
" v5 @  [& F6 X& A2 i* z3 v8 W}3 s6 X- h: @, O% n$ h# Z. o3 ?
, E* q2 Y8 p* a+ h5 T( N# f& K

# a, k! A: O0 D$ x+ k& J
/ A/ f0 d+ j& G6 }//加一- c8 @! ]. W3 l% w
uchar  INC_Number(uchar Number, uchar Min, uchar Max)
2 L& j* O2 a; l4 e2 T* s{
! d& L3 ~. L5 Q, c7 r        if(Number >= Max) return Min; else return (++ Number);
2 E9 G/ I) y7 h$ s+ ]2 e               
  `# \* H* p) O9 Z! X, g}6 o, Y! N8 p8 w- u, \6 `! O

6 T+ X" u6 w, D1 Q//减一
; E  d# u* r3 F+ z, f6 a  Nuchar  DEC_Number(uchar Number, uchar Min, uchar Max)
1 H  d$ L  g( z* C' N' S* @{
" k! V5 ?- T9 b% N        if(Number <= Min) return Max; else return (-- Number);
% H' p! k# b8 v" M) V                9 r. O2 L8 x' q" j% `( ?% q/ G
}8 u$ R/ r5 l% @: @& |

" S& B9 C% D6 F. G9 t( `7 G( a4 W// 检测到有按键后 这里执行按键任务                        % [# }1 R! P% K* [/ o
void execute_key_task(uchar ucKeyValue)        # v& c7 X, T% ^$ N1 i" ^$ u
{
% E  D1 j3 D% \* @6 }        uchar state = 0;                                                //定义调整数据的状态变量) h! _! Q0 d6 X/ b% z) R; ]
        uchar keyValue = 0;                                        //定义键值的临时变量- }" r& Q% Y( \) ^' z# k
        * @& Q' F4 s4 B0 S' S3 k4 }
        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出/ A/ t' [# Y1 }- Z
        $ k% H. v) S) F3 t( l9 O
        //是设置键继续-----------------------------------------------------/ U' S, b9 y, }4 B  b
        
; x7 t( I5 j) w& i: S. Y        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                ; E1 Z% X' q! l9 J% A% V' s) b
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        + J/ h& J2 Q5 K' P$ H
        2 l3 B3 V6 a2 a, Z
        while(1): k) N9 t' t: ~: Z* U
        {
4 v7 U' v) J( g, F; g                keyValue = GetKey();        7 T; l. `* p# K
                if(keyValue == 0) continue;
, P) j# x1 _3 ~% g. c3 }$ s5 Y               
1 f5 |) z: D1 ]. Q8 N' D- q, w0 r! G$ Z                switch(keyValue)
8 `) q8 r8 {. b6 z# `& r4 D                {9 g# a- `9 n; O+ o6 f% `. r
                        case DATA_KEY_Set:
" p- k6 _7 Q5 @6 g8 o                        {
4 d" \8 L1 ], ~7 N, N                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出, `% I! v* M% Y, w- E8 P3 F4 p5 W# ]
                                switch(state)
& [9 c9 q9 X' S! m                                {
! d4 s6 P* }8 }. E. C                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面, m5 X' S* b: x9 E
                                        {
2 M% B+ M( N/ b& l. f' S                                                state = 1;                                                
: `  r7 n& V' r. c2 Q                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
, u; K& v% V9 b" G8 K                                        }
* H  a' @' Y2 v5 i                                        break;% K: A" v! R, K" R0 q/ D
                                        case 1:
1 e  L4 l0 A; h% B/ q                                        {
# c+ H) y( k) q* |6 m0 ?& M0 O: ]                                                uchar tempMax = uiD - DATA_uiD_Min;
: H4 d/ P1 X: v                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
. _5 c, T  `9 p5 W8 q) K8 M' x                                                if(uiH > tempMax) % K6 B1 s. S' j+ T9 Y- k8 Y
                                                {; o0 w+ z6 M/ n, t
                                                        uiH = tempMax;
, {# c& i$ {# W2 `                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
# `2 M; K% M% X: `& U7 U                                                }$ _( M0 D# _, X8 x
                                                else if(uiH < 2 + 2)' W8 Z/ P+ s' o% T' g" t+ Z$ ?
                                                {! \& [( |* H7 G  z# L4 H
                                                        uiH = 2 + 2;        5 D1 v% x) I9 d/ F* `* X3 z
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
5 I& [% L6 S3 o4 w  @. Y* w                                                }                                                        
( G( w/ F, H$ E! W8 |5 }+ x% d7 Z+ @                                                state = 2;( b: w) V  Y! X1 f3 D( N0 D5 V8 y
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
; O8 r. q: T* i  X                                        }, o) m; [6 c; d( O$ E0 u8 X
                                        break;' ~* ~; \8 d, ]6 v- f
                                        case 2:& \' ]3 s  l8 M. u5 `
                                        {
* D  ~( j  H7 o                                                if(uiL > uiH - 2)
% r6 C( O( F8 b% _' x" O                                                {% Z+ [# K7 Q3 a) Z3 |
                                                        uiL = uiH - 2;
' B7 D7 v/ i$ `! h+ T                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);6 V& F+ E5 x* X+ R- j3 i! A& z
                                                }9 t. L- o0 v- x+ X
                                                return;        
. v# f' J$ O3 _+ q                                                9 [6 P$ C0 ^7 `. N5 @; h1 e, @0 T
                                        }! T8 U" r7 T5 O9 v% G7 D
                                        break;8 ]2 G- {  @% U- o
                                }
# i, M8 o9 g! U, o, ]% f; u                                
0 Z4 o' g/ i) q# ~: Y. w0 j                        }
8 G/ K/ V* A. g: E7 B                        break;
" y6 {- L) X" `/ A* h/ w# v8 F                        // 如果按的是增加键,改变相应数据并显示2 H# U! S7 }# w3 K0 L; `$ ^
                        case DATA_KEY_INC:
0 `0 S7 w9 b, i' Y. r. f! t0 \# M                        {
$ ?, J8 M  l1 d' w+ [/ \& V" Y                                switch(state)
2 S6 c& k. |# }* ]+ a9 Q# E6 B                                {1 L: F4 u+ j; i. _) m: q4 A
                                        case 0:2 _$ N7 a9 _1 S) C4 p. r( R
                                        {& s7 ^$ j/ F, b
                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);0 a- B. E. o+ P& A3 E$ B
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        ; T- \3 C$ _" s. o# S8 \8 [" x
                                        }/ D1 x% e7 P. O( I
                                        break;
4 R/ I6 e4 G% ^' A: o5 N1 E                                        case 1:
, Z) e! F4 [/ r% X0 O0 P0 o                                        {% x1 x# E2 ^* v5 Z+ y% }8 {. M: i
                                                uchar tempMax = uiD - DATA_uiD_Min;2 ^6 j/ a0 I0 W1 m0 K
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;  a+ j( Y: p( x8 p1 V3 t
                                                uiH = INC_Number(uiH, 2, tempMax);                                                  @# I, L% N. G
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
+ h" \5 f+ R+ Y                                        }$ B& [+ U# D5 z  r
                                        break;
  f3 E( w  q3 u2 m7 C                                        case 2:
: k+ @; }* j6 `% ~' K; \                                        {) f! n( B6 \9 m2 _1 {" O) `3 X* O
                                                uiL = INC_Number(uiL, 0, uiH - 2);        & o% h9 Q1 S( b, k/ F
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
# L/ q* [+ U$ g9 z                                        }
: H8 x0 j) p; M' u! L3 R                                        break;: }9 q/ w, O! i7 G/ v8 J
                                }
  E. C! _- p- R# Y( I# V  M! t+ J9 s                                
2 ^% u3 R6 z+ |) e' f$ G  ~                        }
" I. e; ?' X& l5 e8 J                        break;" q, v" y! g: A  J8 {# K5 ?
                        // 如果按的是减少键,改变相应数据并显示: c& F9 w5 D& e6 @2 e2 z6 s
                        case DATA_KEY_DEC:
: @( k* q2 ^& t4 `  T                        {
5 E/ F! ^; ~6 _/ T& ~3 F0 j  S6 ]                                switch(state)& h# y9 f. X  t. t4 i
                                {
! t6 |8 p( P8 ^- A' e  y6 s/ E                                        case 0:
6 T2 w" G0 R# E: ~7 N: T1 i                                        {
# c; u4 w+ l  _5 |$ P# w7 F8 B* N                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        , D" d, ^$ h0 Y" Y1 E
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
  A' K) e% O& R) R* m5 n                                        }8 \0 E9 y  N2 J: v
                                        break;
% V7 N( g+ g& S' \5 G                                        case 1:0 M( }7 s( c& w# \% c0 O
                                        {; l, N: l) N& n
                                                uchar tempMax = uiD - DATA_uiD_Min;! I( ]" h0 }7 s; l, }
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;( p7 p6 U4 m9 |$ j4 H" V+ C, a$ j
                                                uiH = DEC_Number(uiH, 2, tempMax);                                                
, d, B+ `- ?" A5 ~% {                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
. W3 U. n; x8 D$ Q  x; ^
0 G' j: ?3 M* _' |$ C1 Q3 U                                        }
+ u9 u8 t9 M+ _6 e" y! K* O; T                                        break;
! K5 z- ]% `! E6 D. w                                        case 2:1 R+ k! ^: j6 L" I% R( S% ~
                                        {
/ ~9 Z" Q9 |% j5 V3 X                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
  C% {  J  [- t8 j' p9 J, L6 ?( y0 `                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
, |7 o* j' D2 o
( w- s) p, M5 B9 k                                        }
' T9 ?4 V9 ^6 v$ ^7 u$ t                                        break;1 r4 H  a4 i' X  r) b( O
                                }, s0 M" \+ r$ S4 F! K6 @+ s
                                5 T8 I1 s) T- h$ D1 z' Y5 S
                        }
* D8 a7 M; S8 X& O$ E5 N                        break;
% K& ^  C$ _1 R) Y0 l                        
% b1 |$ G  t, b8 m# |                }: l! ]  S& i) x
                3 t$ n; r5 |& i5 |# |5 [
        }
" G# m9 T% B  `! C        
' _  Z# H7 J, O+ B& A* U}
, n3 _( f1 [7 w. v: B' G# C' x  k3 T6 f' Z' H/ Z2 p
) l) K7 d9 X* g
& E, f; r4 ~( ^& L/ n7 s
// 蜂鸣器        
( u- x7 b; [& Q8 `8 M0 p/ g, vvoid        buzzerCall(void): x( m, {6 S8 c% |
{
6 A& h4 f) i1 \/ g) o0 x        uchar        i;
- G! f1 l  [7 P        
4 f' F5 w* |/ g. T! }                for(i = 0; i < 90; i++)
7 D+ h, ]& h: {+ x; ^3 \* N                {
3 f. A9 e7 ], F% C  f/ P# ?0 M                        io_Buzzer = 0;
3 z$ ?' s- Z- {/ S: D4 k* ?$ o3 W                        delay100us();. [% C1 N9 l1 i# z' M. h2 r
                        io_Buzzer = 1;. Q! L5 ~+ D8 {/ {3 c6 x
                        delay100us();
+ _; x* W# Z( o# U: b& t( U                        delay100us();               
# r: C- e- z7 m$ H/ ?/ M                }9 Z$ ]! _( d, _0 v/ Q3 U+ i" o
                delay100us();        + x! f6 ?0 U9 W0 w" |  G7 W
                delay100us();        
/ L7 |  W% T3 s, k$ Y0 [( r  L! l}, T0 u' |4 t; H  N' l

; E* c  n; m  s7 j7 B//计算水位
$ ]( m! S$ m  s. S( zbool CalculatedWaterLevel(void)$ \) K" T) _7 D- Z; _# s( G
{1 f* J2 @9 \, G$ G5 l, E
        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置$ X+ j" }! ]4 `  N7 M
        uint          uiTime;                                                //声波传播时间& K9 N$ i7 h3 r" S9 q
        ulong         ulDis;                                                //实时测量到距离        
, Q8 X# U3 S* r) E/ ?        
4 R4 `) ~- ?/ W2 \        uiTime = TH0 << 8 | TL0;        
+ F9 S  I; _1 m. f. g# f, C7 f3 f; w        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
" |1 ?( z* Y) _7 s3 [        % c! U$ u# ]4 C2 o: M
        TH0 = 0;7 Q3 ^3 A% k9 k4 Q; b  ]( k
        TL0 = 0;        6 r- v2 W1 h/ B( Q
        
! `6 A0 q  G1 m        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;1 P6 _& Z- G$ P7 P
        {         2 }3 h% Q/ L! E$ P
                g_flag = isNo;               
# A$ F5 I1 M3 J- F# c/ U                TR0 = 0;% a* d# Z$ V! |) C  i
                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
% s- y* K0 U* t4 n$ d               
; G+ S# K  _, r+ X                //阀门动作:               
1 [! c2 _, ~; c# D  s% a                // if(g_flagSwitch == isYes)7 K2 v$ |/ {. x8 |  P, A4 e% i) p
                // {               
9 m9 z' |( ~' f4 z                        // io_Control_Inlet = isio_Control_Inlet_OFF;               
$ N; z5 e1 S% ]                        // io_Control_Outlet = isio_Control_Outlet_ON;' C; j5 [! V9 ^$ a+ C
                        // g_flagSwitch = isNo;
/ _! _8 y1 D* `# H, t( ]9 |5 ~                // }                ; a4 k: N1 \: {# t8 |
               
! F# b& b: k. H; a  \                //指示灯:
) c8 d8 ~$ A9 y" d& [  H8 a                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
( M8 ~5 M0 j% q! @! i5 e1 o# Y                ioLed_Green = ! ioLed_Green;/ p4 Z# G1 s& B' G+ X& ~+ t% ~
                ioLed_Yellow = ! ioLed_Yellow;2 X8 g5 P: ~/ m/ E: M
               
: K+ K  l: H& V$ Y                // 蜂鸣器叫:        
( N# r5 f8 Z) Z  z! }                if(buzzerCallFlag == isCall)" z/ F9 h3 b3 c) A' @. B: q/ v
                {8 B& n, K: b& n1 W: c5 _4 T
                        buzzerCall();                                        // 蜂鸣器叫        
( D8 c& n& E/ T9 E! G6 g4 V. q                }, Z4 m. _* V9 C8 X2 k
               
7 K8 D/ o: ]. ^+ C! l' O; P) W& `& @                return isNo;                                                                        // 返回错误信息, `+ F3 L: j$ x/ ]  _+ k; m0 w4 R
        }
/ d; s9 O1 E* u. G$ J# ^& R        else
& l& }! w1 y/ t( Q- \        {; K1 s6 G0 s, p% r
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离  w% h/ h7 a/ @( p" s
               
6 k! G7 ^6 l0 k" w& i0 w" i9 t7 J9 v                if(ulDis > uiH)                                                // 如果水位超高" m: m3 F% f7 k( m* J0 J
                {6 h: o! Z8 E3 w9 |! K0 h+ Z
                        
: u& i3 r: N2 ]! T                        //阀门动作:
( A/ Z/ F( ^# C+ F2 L* o                        io_Control_Inlet = isio_Control_Inlet_OFF;: e- P  t" G4 b' l3 p
                        io_Control_Outlet = isio_Control_Outlet_ON;        , w4 h: j1 m5 {, N. y* T
                        g_flagSwitch = isNo;1 P8 A2 y+ B, e7 j* E9 Y
                        * L: U/ i5 I8 H) ]. `- z( ~
                        //指示灯:
' w" U! I) s8 ?% U                        ioLed_Red = ! ioLed_Red;                        // 红灯闪; j8 Z* b6 U* F8 L
                        ioLed_Green = isLedOFF;               
, a  N8 g6 }! @# u  i" _                        ioLed_Yellow = isLedOFF;                                
3 G/ V( \, v+ R$ q5 x7 U' x" E                        // 蜂鸣器叫:5 {9 x% J; o8 `$ k) o& y
                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
, U) K( f( A; x                        {3 v9 T7 G; h8 h+ g- I  @
                                buzzerCall();                                        // 蜂鸣器叫
( ]: \0 h  W& [$ V7 q0 [                        }/ e  ?1 [/ x3 @$ j4 }4 N& l% S
                        ! N  Z! M# `' X9 j! K# u
                }( T+ q, G( u9 Q9 T1 K
                else if(ulDis < uiL)                                        // 如果水位超低3 y2 ~& R" e- h# }9 I( c
                {
  E  x% D; G8 ?3 r- Z, p                        //阀门动作:        
: T: e- P" U6 L  D& h                        if(g_flagSwitch == isYes)
6 y! t" B& L8 z( u                        {               
( _! d  R, \, A' a                                io_Control_Outlet = isio_Control_Outlet_OFF;        
2 c4 P2 y- V. Y# V: W9 J% i                                io_Control_Inlet = isio_Control_Inlet_ON;        
, I0 h: x9 z% X. Q  s                                g_flagSwitch = isNo;6 _2 u; v: N1 J) D" [$ u3 m
                        }        $ m: k7 A& i8 r) W) ?  F
                        
2 K$ {7 @4 N" F$ X6 V                        //指示灯:
  p3 y1 c9 f, ^2 x& W; K                        ioLed_Red = isLedOFF;; w+ I( y" F/ \# R% @8 A- j/ q
                        ioLed_Green = isLedOFF;
+ X4 Q: ~7 B7 E1 E* o                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪0 B4 |( a. q4 Y: p9 S/ o5 c# \
                        // 蜂鸣器叫:                                                
; H0 p0 |$ q' i& D9 E                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警& m* V6 @6 Q7 Y( e+ S; o( t
                        {
$ y2 p; q; t" Y, h* x  r7 \; n                                buzzerCall();                                        // 蜂鸣器叫* j2 E0 H! k( O' t! @1 H' b
                        }/ D9 B. O; u2 x2 a
                        
& B6 w1 ?0 S' T# K/ u- o1 N" N                        
3 n6 v9 @9 v) D) u4 n( y                }3 E4 ?  b: v2 J! ^& z
                else                                                                // 水位在正常范围
" y0 d: Y/ f( M, R                {        - t) c3 g% k& f9 Y2 K+ i/ H
                        ioLed_Red = isLedOFF;
& E- M3 R0 F! f  I                        ioLed_Green = ! ioLed_Green;
& R' H* T9 Y- |9 x. G0 e2 k/ P+ ]                        ioLed_Yellow = isLedOFF;        ; Z8 _; H6 Q' ~- V4 \/ z
                        . [: q3 D, n% N
                }2 c4 [) O# S# g  l; x+ e
                putThreeCharToLCD1602(lineTow, i, ulDis);( Y1 L7 n0 n: r2 _' ]
                return isYes;        ( F) P( e: B, m" a
                % P* p1 }) ~9 B) R7 Y0 m4 v+ E* W
        }/ m1 Y5 A6 B: S) {$ n# A
        return isYes;
5 [9 Z# @: j( @4 ^. [- t}) R# C* G8 d* l" S1 x' @) X

$ b0 O& @2 D1 F% J7 X, Z2 `8 ^/*********************************************************/  T$ Z3 p0 g5 y: {1 D
void main(void)5 f2 U/ i6 j) z) b9 N. ~
{5 u' C9 [: q. ~% m1 r* j6 `
        initIO();                        //初始化IO端口        
5 j* M( z6 G; O3 t  d* B) _        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        
( G/ X; m9 L7 c/ T9 o        initLCD1602();         //LCD初始化        
5 p, {+ f! R5 V4 y8 n        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
, e; T/ M8 ^  T, u1 w7 N        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值  C1 X/ _) P* T% }4 B" t
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H% i8 N/ t4 v0 u
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值( J$ i8 D6 Z* _& @
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L
5 x  u6 \) x- B8 @        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值
  |$ |) S8 p) T# }        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C
; Z1 P( p* V2 B; k: v7 \8 Q/ |. j' M        
& \/ {3 g  t2 D9 l& y% N  T4 y        initTimer0();                //初始化定时器03 c; Z: L" _8 e% u6 |4 g4 c
        initTimer1();# [( I3 M: T- J3 ?+ j
        
# v' @0 [6 W6 l3 Q7 ^( S' V        //阀门动作:初始先排水3 N' E+ u2 p8 g7 v& f0 z
        io_Control_Inlet = isio_Control_Inlet_OFF;        2 H0 P* g# u  w' X- ~2 n, Y
        io_Control_Outlet = isio_Control_Outlet_ON;
; f+ F1 r. G' r% W4 }" P& a  D        g_flagSwitch = isNo;        
( W& O+ \' B0 V( b' t        * `6 J8 X4 a, m1 l6 L4 ?' i
        while(1)
- g* p! u' x3 u- ~! q5 W        {
7 d+ b7 _: C8 k1 w: b& _8 v                io_US_TX = 1;                                //启动超声波模块信号2 G! G: X6 U6 s9 T8 V1 k) K1 n
                delay10us();& D: i$ R7 z4 |8 c! |6 T
                io_US_TX = 0;/ _9 Z! z9 w' A3 _
               
7 c5 S" G$ i) Z  W3 J                while(io_US_RX == 0);                        //等待计时开始3 p7 `1 z0 A, I1 Q. l! u0 G
                TR0 = 1;                                                    //开启定时器0,计时开始        
  q2 |  l( ^4 {3 T# \6 I3 A                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
7 P; b1 x. k. F6 [                EX1 = 1;                        //使能外中断INT1                % [4 ], ~2 |, I( n# t
                7 D. Q$ k/ ]  M% Q, N6 E' X
                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        
) C/ ~0 x& i6 _# r9 B7 i1 e                {
: b7 m4 Z' m6 R! O! r8 H                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键$ V; R/ b" J- y: R* j
                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        ' @. F  l6 P! Z  @) Z! g( ~- u
                }% T. Q' q- E& e# D/ X
                3 l% Z: ]+ p7 U' p# m
                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环               
. T6 i* t* I1 `+ X5 f  g# Y                ' t7 f7 a$ Y; E/ q& k
                TR0 = 0;                //暂时关闭定时器0
# ^. Z- f- H/ u, Z                //清零定时器和计数变量以及标志
0 K7 Z, @* U% r+ d( {+ t, R                TL0 = 0;               
; B  M, j5 P+ l! C1 s1 ~/ U                TH0 = 0;               
3 k" f% U& S7 F                g_flag = isNo;; P- s  y  _' w' v4 L; W% g. h9 a
                ucCount = 0;9 B- n4 i. x; N4 X7 c! h, W7 y0 s
                g_flag05s = isNo;
7 `2 u. z8 _& a* I               
' O0 n4 C( S! J! u5 L' H                TR0 = 1;                //打开定时器0                                       
" p+ R. W8 [* [! ]  a! p' F: F8 |                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果
9 N/ a2 j. k4 W                {                        
4 S' u. ]# ^/ Q                        uchar ucKeyValue = GetKey();
  s4 D: j6 ?3 A8 a% D                        if(ucKeyValue) 5 S/ M3 \- F- V. i% p4 h9 W
                        {+ U- ?( u" o0 B# Y' O1 q7 d' P
                                if(ucKeyValue == DATA_KEY_DEC)
' _  a+ ~, H- m/ D% R                                {
' R7 m0 g' u! ^1 {2 Q                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志
( J3 w" \$ T6 x! V$ _/ }                                }
+ [/ D8 I. n: s: G8 Y  i/ a( U/ F( g
                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        : K6 ~/ c9 v7 ~: `$ O
                        }                                
' i1 x7 i) V) P0 W$ G5 s: V7 K. T1 I5 r! P0 W7 y
                }        
7 O& ?9 z- n- g                TR0 = 0;                //暂时关闭定时器01 w6 x3 S% r3 a1 d# W- z
                //清零定时器和复位标志- W# t+ S( x5 Q
                TL0 = 0;        
  V, {$ ^& Z$ {# m" W" ]8 v2 P                TH0 = 0;        1 f9 v% ~$ W# q) J5 D0 W% m
                g_flag = isNo;                ! B1 Y+ e$ Z9 t4 ~# ?  _
                8 n; q7 B3 ?: i3 N
                //-----------------------------------
8 `/ x2 W) l0 C) @% `                //水箱清洗提示:5 t1 N* P4 B5 a. y* v
               
9 v' r* w) M. J+ y                if(g_flagBeepTimer == isYes)
. D0 [6 T" ~7 O5 R0 @                {1 Q. {# y" k" x0 |, L& J, a0 w, l/ @
                        buzzerCall();                & ?0 U; j9 Y4 R; k
                        //用减小按键取消报警标志
: o$ n5 O5 H& y, T1 i2 R                        # v! b$ e5 m# E2 a
                }& N7 `' z7 C) d9 i& R
                //-----------------------------------
; a% P' X+ ?( R# V  w6 s                7 h: G0 s. d! [2 X! W
        }
! i. h1 @6 L1 Q$ W& k3 x! j3 j}7 O9 `& R! o/ y4 \  q0 T- e

+ p' T9 |2 L- ?, Y1 F& z$ E3 \
* B8 _% h* m* S0 D! [#ifndef __MAIN_H__
1 R' H* Q- _3 J/ R* t. T#define __MAIN_H__+ n$ ~  n/ V( b. a
1 z+ R  U2 r* Y6 K
//-----------------------------------------------! W8 O5 ?* m6 b4 u* v
typedef unsigned char         uchar;        //为了方便书写定义别名9 `, _/ q; P9 Q) [) q8 |0 U
typedef unsigned int         uint;8 K3 v' J# B, \' `4 y
typedef unsigned long         ulong;- `$ [3 `% b$ h0 ?6 e) }* h& O
typedef        bit                                bool;, m' Q4 i1 ~+ n- P2 _7 W4 l

+ ~" Y5 x: X# F; j6 Rsbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口) d0 E( S/ F. K% @/ b
#define        isio_Control_Inlet_ON         0
9 c9 C( F9 h. S( e2 R3 E, ?( e9 e#define        isio_Control_Inlet_OFF         1" E$ l  \" m1 D" p
  g3 A3 Y+ B& I" L3 ^8 [# C
sbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
: S& P/ F( S# \1 O$ v#define        isio_Control_Outlet_ON         00 l% B4 ~9 n; K2 f, _; L
#define        isio_Control_Outlet_OFF         1
0 N* U% V( o: {: x* v0 v! W0 @
3 t5 {' x* ?# `/ i' A. K#define         isYes                1
& i) s2 d5 d' S3 j7 I7 D# }#define        isNo                04 k* {$ _7 a5 h  r
//----------------------------------------------------
, f' f* u8 y# x; W9 _* ~7 L( \//定义超声波模块引脚+ b% @' ~8 ~6 N: y- E! i
sbit         io_US_RX          =        P3 ^ 3;        
5 U, J4 k* u+ E* w& Z9 V) y5 u* Osbit         io_US_TX          =        P3 ^ 2;
( ?& j. B5 E. r$ s" b//----------------------------------------------------$ s, m5 A& ?$ P, r4 F7 K
//定义LCD引脚
: b. c/ V8 }$ o* }" H$ {! `sbit         io_LCD_RW          =        P3 ^ 6;
+ X  c& Z' x  g# p9 Fsbit         io_LCD_RS          =        P3 ^ 7;
$ H6 W# }1 d2 F9 k3 ~- w' csbit         io_LCD_E           =        P3 ^ 5;            
  i1 w+ U2 `$ ^  e3 d#define          IO_LCD_Data                  P2# V6 z* L8 u3 K- @$ u- y4 Y; W2 m
#define         lineOne                        02 s7 ^8 w* J& \: k; D
#define         lineTow                        1
/ Y% K; h7 N; ~8 t# `
/ z2 C" T' E3 _#define        isReadBusy        1) o- e1 x9 w5 @2 r7 k
#define        isNotReadBusy        0" G8 [0 x2 a& }" D" ^2 G( r

4 n8 \, N1 H' G& u' n* j#define        DATA_LineMax                0x01                //LCD最大的行索引数+ [' ?. _7 C, Y/ M" I! `& T+ R
#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置! F! [4 ?' ~. f# X5 \: h
#define        DATA_LineTow                0x01                //LCD第二行的索引值6 @5 r' D  `, g8 `( j
//-------------------------------------------9 C% P! P1 E; r9 |
#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时3 v" E% T8 \. t2 E
//-------------------------------------------------
- p. B4 W$ H. c& O- W// 定义指示灯端口
! l8 |9 _( p: b8 }/ _& D  N+ Vsbit        ioLed_Red = P1 ^ 3;
9 t% j7 i2 h8 m+ P. p) C  Jsbit        ioLed_Green = P1 ^ 2;
; B- \' j! }3 O2 A4 O1 [sbit        ioLed_Yellow = P1 ^ 1;" I& k6 j1 s4 |) m- ]

9 R0 B2 ]/ m- p( {" o: G4 J% d#define        isLedOFF                1                        // 关闭LED
0 w" p2 c/ E6 M& p#define        isLedON                0                        // 点亮LED
" N% f( i3 R' w" Q; L. b4 d//---------------------------------------------
' ?9 F  D! T, w6 x3 @//定义按键端口4 |& ~7 ?* \: t! I5 b, n: X
#define        IO_KEY                                P1        
5 Q4 g' n1 ^$ O" ^7 V+ M8 ^/ t, F6 |) v0 m: N. S# a: j. w
#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据. `7 n+ r. W4 }7 ^  N
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据
* A: E6 \9 q; A+ B' N9 h3 K9 v% }7 P4 P' X8 O1 y& E
#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据' t0 a: g! _" f! k( D. o
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据
/ D7 G; _0 m$ |% t6 j#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据
5 r. J+ G& _( b. A//---------------------------------------------: l( m, S+ ]- U) F6 m+ U
//定义蜂鸣器端口- [( Y1 [+ P% L/ ?, \  `+ ]3 B3 E
sbit        io_Buzzer        =        P1 ^ 0;        
! A/ C$ p' j* N7 k) E//---------------------------------------------
% z+ i* l/ ~' q& X! W* o% l//定义检测探头到水库底部的设定距离范围 程序.jpg + ~& A3 B) b( i0 _4 o! h; o, N: b
#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
( A0 p. x" h$ j: ~& O( h: U' b3 R) p#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm
( Z$ B2 n, v  w; N2 I  X) ~  b8 }7 z: w& U( _
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数$ c7 A' n( O% p) K) O1 C$ `! H$ R5 H
#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)0 R* l& R' p6 d; k
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数
" J9 W* @( ~5 w9 u; }! \1 i
0 i0 M4 M4 ]1 U, ~sbit        buzzerCallFlag = P3 ^ 4;2 T# Z7 N9 E0 P- S
#define        isCall        0
$ [- J. U' u9 _' I/ q& j0 M#endif5 [4 `' E6 K$ f+ a; E
* t& Z+ S. X- _$ }

% f' c/ j& w& R/ l2 o! h3 q0 c
+ X4 A9 c2 r+ \) Y! \2 Y
/ K8 y0 T7 A- v

基于单片机超声波液位控制器设计.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/ J( C1 u* x5 o# o
/***************************************************************
$ ~% c: P) R3 h$ V        名称:基于51单片机的超声波水位 ...

+ q3 x( `' y5 F' h& |又下载一次,打开跟你内容不一样?
& x1 E  l- R* B% B" q( D
QQ截图20201211202119.png
回复

使用道具 举报

 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05
6 Y: T! y- M' O& C大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

/ {' s( o- h8 v5 Z, k3 A+ S是的、是物体都可以检测到!
! N1 Q$ f9 J1 G4 C! I- q3 |
回复

使用道具 举报

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

使用道具 举报

本版积分规则

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

GMT+8, 2026-1-11 17:26 , Processed in 0.057103 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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