一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

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

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑 ! I; t! A( D$ x0 A  i

7 P# p+ C" r6 {* m* z3 a
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)
& Q% ^  H' R" s  F, W
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

# O& Q6 A" V6 w# V
按键功能分别为:设置键 增加键 减小键 复位键

$ g1 |: M4 Y+ w& u
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)

: S5 P/ I, u7 j7 J
发表于 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 编辑
( Z& j% }! H& Q* I% r" ^
tdc31224 发表于 2020-11-24 20:589 {  Z) b# i) {* q, l4 R
没程序?
( p8 f7 Z' x# V

. @" n1 D* V( X' x. s. G$ q* g- B/***************************************************************
  ?4 i$ k! P7 b& a+ J$ N        名称:基于51单片机的超声波水位监测报警系统; f8 k' {7 H# O1 _$ [* h5 E5 T3 A
        单片机型号:AT89C51; n; d; ]4 {6 `+ W9 r% [7 i
        单片机设置:时钟12T,晶体12MHZ
2 g6 X2 ]7 M' I3 A! E! {0 L; q0 r        注:修改增加水泵控制和排水控制,即双继电器
/ ?7 k" b; I4 f( H5 y1 x- s: d5 p***************************************************************/
, k2 G  ^2 @1 h: \" E' n6 W, L% Y8 I8 k" {* I/ r7 k
#include <reg51.h>
) V+ g; m: G9 V9 `' _8 A( E5 G#include <intrins.h>                // 包含循环移位:_cror_: L5 z! T- [! m2 D4 G% h
#include "main.h"     # u( B9 E: x2 i4 p5 t# j
//----------------------------------------------------------------------. ]( u! ]6 e5 q

4 S, S4 D1 S8 e+ c# w4 Wuchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};6 X5 L6 b+ o% N! ]6 |6 P
0 p7 B  f. [; [  I; j
bool        g_flag = isNo;                //用于标记超时(65.536ms)           
# m7 w2 ]" p, ]* h" _1 V) Ubool        g_flag05s = isNo;        //用于标记0.52秒  
& x) a0 d/ X5 W/ n, ruchar         ucCount = 0;                        //用于计数0.52秒     
! w/ ?1 l0 G- B' I
$ F( w7 a; M' J) C) W9 H  c; a* `; Luint        uiH =  86;                        //设定的最高报警水位 H- C. ]. l8 M) s) H* X
uint        uiL =  73;                        //设定的最低报警水位 L
0 z4 U/ S3 b6 q! e7 i3 |6 wuint        uiD =156;                         //检测探头到水库底部的距离 D 6 k& g, x0 h. Q' G" s1 Q8 ~

  r2 H/ F, y; Ubool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志2 R# a) N; m, N
bool        g_flagBeepTimer = isNo;        //定时提醒标志7 \; j3 O, A$ E" c, t9 e! [6 _& W
               
& s3 l( b' U5 [$ g9 @3 A) r( _
# _0 G& e/ p1 }8 v0 V" L. _3 o//-----------------------------------------------------------------------  T0 S3 D) Y$ n% H9 M( b" c
// 延时10us* W$ r5 I, \# ]) d" ]
void delay10us(void)                //@12MHz
! C4 y- `2 X" I* _7 c{
* k4 d0 r. e3 b: D: u% x& N( a        unsigned char i;
/ j6 _0 g. i* i+ c8 N' h
" W8 Y- D; D1 h/ V0 H* _        _nop_();
. s: X0 w  x2 F( N! [* S: u" ~% N        i = 2;
2 B& R) M: l2 y5 f        while (--i);4 S4 l3 @7 C  x/ l
}
% |' w, R- \& l7 `' U# {
* V0 x0 V5 j% f# U, Y// 延时100us
7 b+ U/ H* P* @3 }2 Jvoid delay100us(void)                //@12MHz7 a' f/ w- Z9 D2 m- B5 T, i3 m1 `, c
{. ~% ?4 J* }( s& J& O$ h$ l
        uchar i;3 H* @* ^: n7 u7 v8 G0 ?( w

* c' ]" P% R/ N5 D4 a        _nop_();2 u5 S- u" c* b
        i = 47;
( h% c- S/ R9 c/ k$ b: a        while (--i);0 ]! h7 F  [  Z
}
/ f, h  F" b0 w5 G' j& E" Q- U) P* V  f- Z+ G
// 延时125us8 \4 H& k# I5 N- P
void delay125us(void)                //@12MHz$ _$ N. O) D5 t: c4 L( w6 W! ]
{+ z' @. |8 p$ c, G! ~* X2 F3 M
        unsigned char i;
3 J* w. S3 M3 B2 Y        i = 60;
2 t2 W0 h7 g% G4 |        while (--i);7 M' K; l! c- }" ]1 X' l
}
- r8 P, |6 F0 j, h# g% ^  U2 W. {) m8 k) A
// 延时5ms
! D; _% n- p4 t6 Ovoid delay5ms(void)                //@12.000MHz
$ t% j" h6 r7 q3 E{
- b9 E% O9 ]& d( i8 `1 y        unsigned char i, j;
- C+ f. h2 K5 H1 ~1 K% l& v3 c
0 t" M( y- N2 }+ Q) f        i = 10;
9 N$ ?" j& _* R4 A$ q4 T6 K        j = 183;  f4 o0 Y* ^' l
        do
# r& \6 N. m; l/ L- @        {
8 r/ z) S, ]0 c' ?! K                while (--j);6 D; n! y; ^  z( l( m) O
        } while (--i);
1 C: Z0 _; I! V2 f5 Y+ D, }& w}
( S) J5 D  S* T' c/ a
2 {- f8 J* X4 p# ]  _( f6 D2 b7 h// 延时500ms
* M- a1 R# \% o, ]7 k2 i6 \void delay500ms(void)                //@12MHz
& p2 `+ P5 L2 l  E* P% y) d( J- c{6 c8 L$ B6 w! Z& a$ D7 U7 F
        unsigned char i, j, k;
2 ]' E7 _) C, C5 u  n+ U4 t. i* d/ z$ K2 x2 ^) [/ m* c$ {3 Z
        _nop_();8 i! Z- E0 t4 _4 z. Z, r3 C& y# i
        i = 4;
' I$ H4 }0 x* H# r: L# W        j = 205;1 y/ C" Q% l0 j6 X0 K
        k = 187;' n* D" B. }- c8 z- r
        do
% I3 T) J7 P- H9 k- w        {3 V: |5 D7 w9 C4 {5 C
                do
; n& ~. }  |2 P" K                {
! f  I+ }" R% K( m* q7 W                        while (--k);- c5 @8 n2 [3 @( `5 \5 I, ~
                } while (--j);1 k* t8 A3 R7 z5 |/ j! V
        } while (--i);6 Q) d- k: X8 P; i9 r$ s8 B# i% W% g. x
}
( C) f7 M; h2 O
2 n. a( }2 K  J//-----------------------------------------------------------------------/ e& W3 S9 p. P6 O
//初始化IO端口                        
) ^% q( \0 |4 Y7 n: r' hvoid initIO(void)                                       
+ \/ o# X; F' D! k% I{
* S- T( w3 Y1 V# `! m6 M        P0 = 0xff;
3 J' {' ?$ d/ F/ O' x        P1 = 0xff;1 y4 ]3 x. f4 a! J2 @7 D5 S0 K
        P2 = 0xff;
3 {7 [" F5 W& o) a$ p- c1 V1 a        P3 = 0xff;
: r8 h; |% \5 }- f# V: }# ~$ F1 M}. o5 e# T( a; r/ p/ h2 Q6 |

9 a5 i, B# [+ v// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz: J7 i% O' s) l7 z, C
void initTimer0(void)               
4 @" o/ ]% X# \# e# O0 H- w{
; P- T* }; V2 Z5 R        TMOD &= 0xF0;                //设置定时器模式1 O8 B. J$ `1 d' n% k
        TMOD |= 0x01;                //设置定时器模式
  ]/ b- U0 N/ `4 z' g        TL0 = 0;                                //定时器初值清零$ D8 Z2 c, X* m
        TH0 = 0;                                //定时器初值清零4 ]6 b. B& k9 j
        //TR0 = 1;                           //开定时器0% k: r- E9 C  ]) c1 x
    ET0 = 1;                          //开定时器0中断
8 i4 D" M" d8 s& H8 s+ x) g9 G    EA = 1;                             //开总中断            6 w$ N8 W& r; c( Z8 P
        
2 b  n" w, U: S. n- e' [! ?}
# o* Z, K! R4 Y
! f% _! g) n( h6 g: {- c# y: f// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz5 M! B  J5 Y# Y! v0 z4 i
void initTimer1(void)                //50毫秒@12.000MHz& y2 E. D- X6 T; o
{        
* ?4 x; A" O7 k' E/ j  ]        TMOD &= 0x0F;                //设置定时器模式
# M. L+ G! W6 P6 h( `" Y& `, Z        TMOD |= 0x10;                //设置定时器模式
1 K0 O0 G9 `* T* J) x3 {! e) P0 C        TL1 = 0xB0;                //设置定时初值& f3 e) m) N) Z0 h
        TH1 = 0x3C;                //设置定时初值        
! G7 L, o% R0 k! X        TR1 = 1;                //定时器1开始计时& `5 K) ~! m* L$ S7 O  ?
        ET1 = 1;          //开定时器0中断
! C" h1 v7 a$ D! ]) O+ R. s- a}
( _7 w: a4 ]$ h& k0 p2 s4 G$ q4 e  J& p! o
//-----------------------------------------------------------------------0 j+ c' j  I9 Y, U( S- N6 b
//定时器0中断9 @( H" o2 r  S& X. G; J
void zd0(void) interrupt 1                  
1 u' g4 x+ D. E' w1 j# E# P{
' T/ ~) r& c* \' m& u4 E        
- B6 Y5 f0 {" R        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
& X- j; l, @, P) O' u        if(++ucCount >= 8)
. Z9 J  d& o- [  `1 j        {7 l7 Z6 [0 l2 F  d6 B
                ucCount = 0;
$ K; W( m- {1 \0 P                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时
" y2 Y7 ~- y. k1 Z: S" H& e        }, d0 g9 C& S( d/ T, O
        TL0 = 0;                //设置定时初值" t: {/ n. I: f2 x
        TH0 = 0;                //设置定时初值1 d) o4 k6 P5 y# D$ T6 y) r1 X
        
" ^' t7 v$ P# Z; a}
3 ^& C' z8 b/ @9 @1 A1 U2 r9 {3 @5 ^% f* f' b

5 P6 u# R. v; c) Q//定时器1中断 定时50ms
1 B4 L3 [! M0 k* Zvoid tm1_isr() interrupt 3 using 1
8 I: X7 n8 c! x6 H( {{8 ]2 c! Y: X$ b( a) t% W
        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S8 d* \9 H; y% s! v
        static uchar uiCount = 1200;                                //                        = 1分钟                - U- u% i! ~6 h. C  b
        static uint uiCount_BeepTimer = DATA_BeepTimer;
  M  c3 i6 Q  r  e5 t
  y! \8 A  r' ~7 a1 n" D/ x+ {        TL1 = 0xB0;                //设置定时初值
0 [# r1 y' O4 w! y( _        TH1 = 0x3C;                //设置定时初值
& `+ U0 C- a% n, `4 a3 C& w& X
* p7 O+ B$ v# l8 D9 J) L! U        if (g_flagSwitch == isNo)
2 p4 W8 Y* p! p$ X- P" s        {
: v% a# M& v5 ?/ o& k4 h                if (count-- == 0)               //50ms * 200 -> 10s: {# x# [, y5 A4 Y$ H7 ~
                {
$ u- `/ z  }) Z; @! W/ E0 U* K                        count = DATA_switchTime;
; m. m# C3 J: j; O6 X! z8 J                        g_flagSwitch = isYes;
9 j/ T5 R# C& w) N                        // TR1 = 0;
% |$ J/ J1 x$ e4 E                }' N4 V; C" e) Z! g9 P3 F
        }        . {  k5 b! c, g" x' l0 u
        / L# h, ?+ t/ h. Z1 U
        if(g_flagBeepTimer == isNo), p5 s, \. Y, c. B
        {: g8 ^" v2 B3 U* b9 H+ b
                if (uiCount-- == 0)               //= 1分钟
4 q7 |. v, v+ B; L5 w                {2 h' K8 M: V2 J. [0 A
                        uiCount = 1200;" a0 X6 s9 t. G' Q- H2 O
                        if(uiCount_BeepTimer-- == 0)5 o( B9 ?$ `: R! a/ _6 O/ c
                        {
5 p2 D9 A+ P4 l5 D% a                                uiCount_BeepTimer = DATA_BeepTimer;
* z' U1 T$ i" ?8 U! a                                g_flagBeepTimer = isYes;
! v' f) w/ k$ H& N$ }4 D5 J                                // TR1 = 0;$ Y) a( V: L! l' ?
                        }                        
8 Y* L) D, Z1 A, ]& E8 k                        
4 t( }% D+ u5 K( V                }5 }( m& f" }. b
1 p; A& C6 |( F. y1 G8 W1 r
        }
/ G" C* w( f9 ~+ f6 r/ ?}6 C  d& L& D0 W3 K

5 P' q! ~* B; X9 k+ k  a//-----------------------------------------------
8 t. l; J# X. `; q, X" q
# r" S$ A# Q$ I- U! @2 z
7 j6 o/ k, c; V3 }0 X, k! e6 G  z2 V; ?, [

! z" T" n+ X- f( x
: c" R; \) z) c//外部中断1& O. ?+ o# ?3 d
void exint1() interrupt 2
0 C3 Z' J% ^" {/ S9 S$ @& p$ s{) Z4 P! b: J* d8 f* Z# W
    EX1 = 0;                         //关闭当前中断
- n7 g9 v5 k$ ]( ]        TR0 = 0;                           //关闭时器02 k+ x6 E6 Z! b$ e6 N& n
        - j$ h1 ~, R6 Z% E* M5 t# [+ m
}
& m! ^- t$ u; B. F% i. q//-----------------------------------------------------------------------) x( ]: P- @0 Z. R
3 q2 |* v% {% n: E9 p' H7 q/ t0 M
//读LCD忙状态并等待忙状态结束
8 G# C5 }' O" h. x1 \, a' Pvoid LCD_waitNotBusy(void)$ E2 ^; P0 H/ L5 F1 I$ r: j
{
9 I  _, v- l8 F$ N4 I0 \        IO_LCD_Data = 0xFF;
/ {# S/ [, r% e. H3 g6 \        io_LCD_RS = 0;/ H- D# l' X( l
        io_LCD_RW = 1;. ~: F6 A% `2 `6 H" R$ ~* ^! ?  O
        io_LCD_E = 0;1 b9 W6 b0 [7 |8 _1 S
        _nop_();
8 T% e' i5 |% k5 @! J6 z8 C9 K& R3 \        _nop_();2 ^/ b% f6 _/ i
        io_LCD_E = 1;
7 `+ s/ r- U# ^4 ^/ J1 D* G, }4 M        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙" G7 ^7 `1 n% Y$ p% n' C  U
}4 f  L2 U7 R% N- T% ]

# z1 i# E; r4 ~6 }' S+ D& h//给LCD写指令
6 t% c8 ^9 X  N, `' ^/ Y% m$ K: pvoid LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测+ z9 `+ X+ ^3 B: G& z. Z" D
{
2 H( G5 Z' f% Z8 N! I$ s        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙
) f5 l& V" m9 |/ K4 j/ W; @8 Y        IO_LCD_Data = command;
$ w* s( o( `) t! G        io_LCD_RS = 0;: Q% G: e- i1 c7 _0 u: v
        io_LCD_RW = 0;        " V& Y& _" y1 ]3 h" O* V
        io_LCD_E = 0;
% E( `- W+ `! ]. Q. z        _nop_();, n4 M4 J, [8 |9 N4 H% G! H
        _nop_();
8 w; Y, ^. O5 j        io_LCD_E = 1;        
8 q& g: ]: `# \. }}
+ m. P# \9 X+ L7 U! A2 S  F5 ?9 m2 m1 L* t% G" j
//给LCD写数据
6 R+ Y: V  x- {0 Ivoid LCDWriteData(uchar dat)
, m6 s0 w' @) L& ~{' w; N4 s# ~7 n8 k, r4 D& v; x
        LCD_waitNotBusy(); //等到不忙
. `2 i- t8 ^5 o# E( d* a4 o' \        IO_LCD_Data = dat;
# d( @! M0 X+ b. ?* Y        io_LCD_RS = 1;
% V2 }0 v1 D- c7 p        io_LCD_RW = 0;* n# {& S# s+ I! R/ B3 P
        io_LCD_E = 0; / N9 i+ [/ |) E% o% u
        _nop_();
! F/ F* K/ l* ?9 U7 U        _nop_();
' ~( ^7 Q$ R3 w        io_LCD_E = 1;
: O  E2 o% }/ E' }' a! |) B}
9 C6 H5 q& n0 r1 {; @0 K6 ~/ g1 c4 E% B
3 q* p4 o: \3 o& ?. x

! x. F: c+ ?4 @  D1 n% u( z# t; {" ?0 x8 Q. ^: d1 h9 O' J. V
// 初始化LCD1602液晶显示屏
" i. U/ \- m4 _7 tvoid initLCD1602(void) ' h# J" n) i+ s; S
{9 I7 z4 k( O5 k+ Y
        uchar        i;        
( ?: l2 ^3 U) S3 f8 J/ z8 A9 S        IO_LCD_Data = 0;                                                                // 数据端口清零, [; d4 @* g# Z1 S* y2 i
        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
0 v4 V" C. O* H6 i- v7 s        {
4 y- g' l" q) y                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号; u$ j. ^4 D3 ~7 x& D- E# S" a
                delay5ms();
, l& M! y5 }+ F8 f" r        }
! \. `# C8 f" ~/ [        
3 n3 z9 ~* Y% ?9 I        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号! I) `* @. R3 I2 I- ^; E
        LCDWriteCommand(0x08,isReadBusy); // 关闭显示
, A" f5 @' J) W9 `, `1 H1 K        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
& H# c: k( Z% u+ E9 Y0 W+ t        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
& @; o/ c  K0 W' v, k% B        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置
& i! f) h' V( C# g% T) X9 {0 a5 Y}
: t- y$ j3 J1 J8 b* l& k" |
* x( i7 n( b4 J8 {4 U7 N9 E! Q! K. ?! j2 g. v- r* W* L% w6 S

8 \$ e4 o  h- x! v//按指定位置显示一个字符- _1 k# O( K/ ~  n' P
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
. Y8 H" W7 m( T* [& K$ t{! U0 z* X% i6 U5 e) C) O

$ R' J; B5 A3 M' ~' Y& b  ?3 O* U/ {        line &= DATA_LineMax;  f/ f% n% O1 Y/ I4 d
        position &= DATA_PositionMax;* o9 [- J! T5 ?5 \0 e9 K; ]
        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
# u; Y5 q1 c) n) I        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;; ~) l, }$ z% l. z2 h
        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址; G2 G1 \- {/ t- m
        LCDWriteData(ucData);                                                                  //写入字符的数据        
% ?  c* p% J9 l7 y1 c! }9 G0 T}3 P. Z. Q: k9 {3 C

) J8 Z( g0 U- m% Y) [5 o. {//按指定位置显示一串字符
: [7 w, J" l# A0 L$ t0 Svoid putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
! _( s# F! c! j5 h9 h* F{7 H, ^6 w+ E$ a
        uchar i;
* C0 c) j# a* K* [+ a        for(i = 0; i < count; i++)                                                        //连续显示单个字符
1 L4 }( i" B$ x5 {. w2 V        {
, [. Z  [% p) A! l                putOneCharToLCD1602(line, position + i, ucData);        
5 p, B0 I& r  w5 u' y* O2 c        }
: z. \( [6 q+ ^! h( I}
6 k, j( T2 V3 p6 O& v" Z8 m) R% X
$ s* O, v0 p$ V7 e. S; e
% Y# J3 I6 D- M% o//按指定位置连续显示三个字符(三位数字)" \$ Y/ _" l& B
void        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)6 r7 o( [. `6 ?2 Z- ~6 [  E/ {
{+ N/ A8 K7 d+ f8 W. z  z
        uiNumber %= 1000;- a) [6 @  @2 P+ R$ j/ K
        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);. F9 ^+ v% W' X* |# u* |- v+ }. z
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
+ n9 O  p, J" k( e+ ]        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
' `; Y. I7 S' [        
& W- v) y6 k0 W}
7 {9 @. B" N# |2 N        
9 H9 r" {+ C+ ?. o  \3 k: |  Q% e5 h
5 W4 }- r; Y1 p1 x
// 按键检测子程序,有键按下返回键端口数据,无键返回0
& T* I% V' x; N# r' buchar GetKey(void)
" S* |- _5 ~7 X5 R{        
* o# ^* h# o* M5 N    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        
: z* p+ v% o$ I# j        
8 x2 s+ X. p" M. G1 s; n8 A        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空; \; i0 H2 n# o; l" \9 e
        {+ f2 }5 j8 g1 b; q' ]9 o" M8 o- I
                uchar CountTemp = 0;2 a+ o* s% k1 q, _0 T1 c! \& [
                do
4 @) Q3 R( A( A                {# d+ z% `& ^9 s0 }1 |) ]4 u
                        delay125us();( f; {, u4 ~8 Q
                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出          p) X+ {8 s8 n. G, a- x, u! n- V
                        * m! T( @4 {0 ]6 a1 G+ `0 v& u
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动
* N7 v& F$ M3 M1 w* |+ o5 G               
6 `; a& P7 t; H- }+ m                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放               
5 C" v, i* B' i1 M. x7 I               
* b% a& h4 {, w) d                return KeyTemp;        // 有键按下返回键端口数据3 U, E3 z! m- O4 v& s8 d3 K
        }
9 s2 K) Q5 ^; A/ `" G9 _" ]2 u        ! ^# i# Y$ _7 Q: }" Y
        return 0;        // 无有效键返回03 \! N( n7 V$ h
}/ F" j2 p8 B% N$ d7 c' F7 q

0 p7 `+ n. j' Q
2 ~+ i9 }  u0 y  c. j" k0 }8 W- a2 s. R+ e8 @  _4 w
//加一7 J& T; K; C; |7 k( v  V: I. |3 |
uchar  INC_Number(uchar Number, uchar Min, uchar Max)
  v/ R" M0 x" T4 g3 F{
; L4 k+ w9 p9 B8 p( @6 S8 a5 h        if(Number >= Max) return Min; else return (++ Number);' n8 K! X8 \8 S$ }' Q0 D
               
% V: P$ H5 V1 v! F3 i5 a) @( I' R}, E) g% }# l* |4 P1 E: |' d8 V  k

, \. y  ~7 _; @: o; J! p2 i0 t, c//减一/ |& ^% {: x7 K
uchar  DEC_Number(uchar Number, uchar Min, uchar Max)
9 ^" C$ u" b; ]7 V7 {( @/ y  E{: r! ~. {0 K( y( ^$ p9 p/ G
        if(Number <= Min) return Max; else return (-- Number);
0 Y5 Z5 W0 U3 w& F# A                % E) v% D7 a7 ]
}; x2 `. ?- G4 Z/ H' J1 |9 m
. V" z0 z7 [& z. e5 K4 Z' O) [
// 检测到有按键后 这里执行按键任务                        
2 A* Z4 L, b5 E) @7 v+ ~; N/ P2 `void execute_key_task(uchar ucKeyValue)        
! x3 G& `7 U2 [$ n- @& A- ]{$ L" }* K, C& {% C& P
        uchar state = 0;                                                //定义调整数据的状态变量
6 X) b) k' |- G8 _! V2 n        uchar keyValue = 0;                                        //定义键值的临时变量, U3 l4 Z2 V8 v" H
        
! z! c# M7 i- B: p        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出1 S1 Z4 F" H2 t! q( F4 u4 e1 t) W& \3 y
        2 N# P3 A$ A, o! N7 D2 v0 T5 ~' j
        //是设置键继续-----------------------------------------------------
5 }' h6 E3 D) ~$ q) N        2 b' T9 i) h& {: F. B
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT                , T: V) F0 O/ t: Z4 h- L4 Z
        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        
' ]) B: F" |: I9 @: s        : S* n8 o' E6 t
        while(1)
2 W+ D- g% ]& Z4 z) W8 M5 }* Z        {8 N/ b. f; X! m' w& t' F1 M, @- F  l
                keyValue = GetKey();        
/ r: }( O8 J& R6 ?                if(keyValue == 0) continue;
" D  H& E0 _- J6 s5 B                $ h: K" m- Q( c- R( ]
                switch(keyValue)2 [6 [6 j% l) `
                {
: f2 o! O+ D2 j8 [' S0 A  Q                        case DATA_KEY_Set:+ c' V9 k. ^4 p7 `# @$ u
                        {( J+ f1 {& ^( }+ l, K! ]
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
- p' l$ ~2 D) ^& I! y; y                                switch(state): e" D/ G9 ]3 J5 Z, ~6 ~! |: D" ?
                                {
3 D9 Q% v# T! |5 V; Q( H                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面3 P/ S6 y- v$ l$ v1 Y  w- b
                                        {
& h; P2 R& B& t1 d) H4 Z+ f                                                state = 1;                                                
; ]7 c  u1 A; ~, N                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
! x6 D& F- {7 x) r9 i( |! R                                        }7 w. U) J$ U2 g1 s* `$ l
                                        break;, s& W) k1 `+ q- x5 J
                                        case 1:
* x- `0 G6 S3 Z) O                                        {
5 X4 O6 M+ y  O  j  Y5 ?& Z. Y                                                uchar tempMax = uiD - DATA_uiD_Min;
' q( \$ Y: b4 F+ N4 [8 d                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
8 u$ f. r; I% R/ P                                                if(uiH > tempMax) 1 X3 j" A5 z/ \# ]  ?, y
                                                {
+ k* X( w6 S7 v( Y2 S                                                        uiH = tempMax;
4 O2 A2 B9 h9 f( L! h                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);4 s5 N4 U3 C& `5 W
                                                }+ Y; E, C/ ~& T7 D  e! |4 _
                                                else if(uiH < 2 + 2)( f7 d/ R/ {3 R6 E
                                                {* h9 P/ }# F  ^6 l- A9 i7 X+ x
                                                        uiH = 2 + 2;        
5 V% X" J6 ^( V8 V8 M8 r2 Y                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
; Q* ^( g2 P, z+ w$ m" |* _* g7 S                                                }                                                        
. V/ O1 ?1 q, t                                                state = 2;6 H- c, }( x* l4 h9 a4 y  x
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
0 j! _) v0 R5 `6 y% M" O                                        }
- X. |. [$ |* N; v# |! d& I  m! \                                        break;8 n9 j, Z) V" I
                                        case 2:
$ f$ k; U' \4 }' u. w                                        {
) ?' }1 [- F' b; u                                                if(uiL > uiH - 2) , O. V8 u: A. G0 r( g7 i& w& }
                                                {
  a( C* r  U( r% z  K4 M                                                        uiL = uiH - 2;
* M# g* [3 z' f  u9 E                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);% p% ~! X9 ^7 M4 O4 P8 p# z
                                                }+ Q$ d1 Z6 k; ]- P# J8 A3 B
                                                return;        
. y8 x1 E& _  Z8 f7 U                                                
" z& e9 k% d1 I1 f- G8 u                                        }
- U7 \$ @5 c; x0 w; I5 `                                        break;9 M( U6 L+ |8 L- K: i
                                }- Q* E6 |+ Z0 `
                                
  X& Q( l/ J2 h- v# R                        }
8 R* H5 i0 S, M3 g$ c5 N                        break;
  K( y& P; v! ]. U                        // 如果按的是增加键,改变相应数据并显示
% C: ~2 C# {5 W  m                        case DATA_KEY_INC:, E' g- o" Z5 K  M
                        {
* ~8 L* Q  {: V4 U                                switch(state)
, H: I% t5 G- L$ q0 E+ R1 K                                {* _  h# W; c$ a+ J' p: r7 X! e
                                        case 0:
% k6 ?( F" s8 N' n                                        {
! K+ g  N, Z6 F* j, q$ I6 w                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);# U6 M) h& }7 g# \8 v  t
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        
6 F; V3 i; ^4 l3 d: x$ _1 ^6 A6 ?                                        }
; s3 c5 c* f8 @  w3 g6 p) H                                        break;
7 z% D/ O6 C4 o7 D. y/ ?+ h                                        case 1:9 t2 ~4 L# G% E( d
                                        {. e. o+ G. Y) x' b4 d* o
                                                uchar tempMax = uiD - DATA_uiD_Min;& k- k3 r2 ^6 [+ w  ^+ a) y
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
5 j. I: f5 `/ r                                                uiH = INC_Number(uiH, 2, tempMax);                                                2 }- L4 [3 r5 p$ e7 K. [
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);          c) O$ ?6 I: c6 C& M8 Y/ J
                                        }
4 I9 ?2 m+ |# T" {: ]! j& ^                                        break;1 X" K9 i5 g+ O, Y6 T6 c: O
                                        case 2:
5 J- ^1 F; x7 r2 U9 h                                        {3 \" w' I5 S1 \7 R) d# X4 Q: G
                                                uiL = INC_Number(uiL, 0, uiH - 2);        ' K$ w- t3 \% f" B
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
1 }/ ^1 f7 q) J) }* h& ]                                        }
: D' \- B( W0 W1 ~. }  g& n# y                                        break;6 F$ Y/ W& ?& E$ B2 N  ]
                                }
$ q$ i" D  ]. N1 ~                                ; ^+ H! s& V" R( |6 Q& z
                        }2 F3 K* x* v! ^: }" s9 t
                        break;
3 j' j: X" m: ?                        // 如果按的是减少键,改变相应数据并显示  p  ?( L. d) Q+ b, A  @
                        case DATA_KEY_DEC:
7 H  n- U% t( h                        {0 a& G$ d8 I8 n4 _: E: q
                                switch(state)
, e9 @3 D3 B$ ^  R# d0 D- @) ]  f                                {
. c& s. N5 P4 o                                        case 0:
6 j+ B: b/ T) T9 ]7 m                                        {! M6 @  u- M. w. L
                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                       
$ o" e- i( s  e) K: S0 ~                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);+ J/ G! h8 N# K  A
                                        }
- y: \* R2 M* F! Y1 ?$ g3 z6 k                                        break;
4 ^# _6 F9 ^3 p0 E                                        case 1:
0 N5 s% Y# }8 @# _$ v) P1 B: n                                        {
7 E$ Y7 j! y: d4 l                                                uchar tempMax = uiD - DATA_uiD_Min;
! V" |+ r: N4 X$ E2 k* [3 |4 Y+ a                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
, K1 r; |7 R- a/ l                                                uiH = DEC_Number(uiH, 2, tempMax);                                                0 R- s5 d4 z" j$ i$ m. G
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
2 d8 d3 h$ r, _: t
8 k2 V8 Q+ `6 g! c                                        }
, F$ G' l7 t6 Y) O1 R  v/ V                                        break;
  L3 O! W& u; O& a                                        case 2:
8 R' b) j. S$ ?& P                                        {8 t* H& B/ g/ K) [) z  e, h
                                                uiL = DEC_Number(uiL, 0, uiH - 2);        
/ x% U0 Q, C0 f0 ~/ q9 X                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
  g7 Z; {" J+ @" t( D6 P% ?  l. S8 A$ I% B* p$ m2 {! a+ ]" C! H
                                        }
& m! w5 Z5 F! n- Y0 ]                                        break;
  o/ V- g1 h  L; y8 W  T                                }
, \+ A0 r5 J4 b; ~% ?                                2 {: o5 ?% c. I! O
                        }4 a$ W% ~; @: @2 I5 m
                        break;; B; D9 G2 M* S: v& H% a! C% N
                        7 o; k1 q, O# u! A
                }
7 G( Y; e+ I  P9 V  g5 Q, J               
0 H% L6 Y" s% I. @        }3 m+ D5 G  x* H& I8 P
        ( S. ^0 z2 P# s% n" Q6 D( t
}' [$ R0 o0 M8 C3 |( a; _

' }/ \% W$ [' X) U! W
# A, t3 U5 m; E* i' M3 X+ G4 j  {+ p# L- M3 r8 L
// 蜂鸣器          E4 m7 d5 v; @: I  p
void        buzzerCall(void)
/ m# M& E) ]8 C. B6 B# j{6 B( N) F4 a7 ^* ~& x' m
        uchar        i;
: J+ |* f9 h9 _% R; L3 `% g        
+ l. ~% M8 L- M# z- S: P: k                for(i = 0; i < 90; i++)+ p" A& ?, j( T1 }, z5 F
                {  S6 _; R2 U0 e7 `) C/ ^; h
                        io_Buzzer = 0;
& u& w# \9 N: l, B" i6 s* j                        delay100us();
6 r8 F: Y) ^7 q& ?% ?                        io_Buzzer = 1;% x6 ]# m8 C" B! V
                        delay100us();
- G" K  v# @8 n0 ]' G6 H% y                        delay100us();                . v  x9 N/ T1 T8 I: z' G
                }
$ z% S/ U( t# u7 Q                delay100us();        
1 \2 @# v. k/ k                delay100us();        
* r$ R" ]) R8 F1 w, c; I}
: O* z$ J: p, V6 z9 _% H: g9 R
1 t% _, V  ]+ K, a5 y+ D//计算水位- {# {1 O/ V* {& S
bool CalculatedWaterLevel(void)
: V% N. x5 Y; e! C$ s% Y9 I{
. n/ h% f8 ?7 T4 X- a        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置
3 k0 S6 m. ^* l) H& d        uint          uiTime;                                                //声波传播时间
( j/ I' m" K7 b8 u        ulong         ulDis;                                                //实时测量到距离        
0 |, V0 k+ H8 ^        
3 ~# f, p/ Z) O/ z1 C9 h        uiTime = TH0 << 8 | TL0;        
- |) P6 @) k  Q- O1 r  Z( F        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm
. v1 T% Z$ E2 @. J9 f/ q6 ?4 ^        
/ Y5 d. h7 L; C9 Q8 [! S2 Q        TH0 = 0;
& W6 _  |1 g. [" ]8 D& D        TL0 = 0;        # l, T, a4 a! `9 T- a
        
" g; ~' h8 ?! t# \4 P3 O( c        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;
: @1 h, M3 X/ G. v. ^1 {& t5 Z        {         / }0 }5 T& Q/ a: w3 C
                g_flag = isNo;               
; p" d- T0 N. B                TR0 = 0;
9 ~# B2 U  [0 F6 \' s/ @                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 
. ]2 S0 U& T% b2 x. _                & n& }: d, R- S; r
                //阀门动作:                ) G# b. V3 f: A: w7 D
                // if(g_flagSwitch == isYes)& Q1 M( p: U% l. e4 ]& M
                // {               
" z8 Y3 c0 P. l) p( y                        // io_Control_Inlet = isio_Control_Inlet_OFF;               
. h7 |5 Y1 r" [, ?7 |                        // io_Control_Outlet = isio_Control_Outlet_ON;
/ M, Z/ A; t, S6 v% A. J                        // g_flagSwitch = isNo;
1 N! b* X  ]' W. x                // }                9 R3 ^+ Q0 R4 U1 h$ c( Q
                ( W6 @0 ?6 P, Y( t. |: I: ~
                //指示灯:
- V8 Y( J7 M' \; `7 ^                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
6 L5 \: {4 X5 v( O2 j                ioLed_Green = ! ioLed_Green;: G: P( T5 H- X& B1 c, Y
                ioLed_Yellow = ! ioLed_Yellow;* _% I7 |' T0 J& j- S
                ' Z% U6 L# ]* r- a- ?" m4 ]6 \( T
                // 蜂鸣器叫:        
6 [1 W. P- `: Y                if(buzzerCallFlag == isCall)
# j( @, \% B- r1 W. C/ H                {
4 r$ ~3 s9 M# ^& h  t                        buzzerCall();                                        // 蜂鸣器叫        
7 w0 f8 E3 K# g" D( w) I1 c                }
5 h* E& j/ M! A# I$ y                # z  X" @" n4 f& J: N
                return isNo;                                                                        // 返回错误信息
9 R/ q/ l& r  d0 `        }
! x0 q" T2 A0 _4 z0 w2 X        else4 }& R9 ]2 S' r7 Y7 U$ k
        {2 S. N, z& Z7 r2 D8 ?) \
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离
8 n* r( h0 [+ ^6 R0 d) A               
4 i1 G2 ~+ b8 J7 R" w0 t  u# N                if(ulDis > uiH)                                                // 如果水位超高+ ?6 t( b* B/ W' q5 R, ]6 f( P
                {7 d  _: Y: Q! `/ ^- Z# K% k
                        
) x- l8 p, X( z5 t; A" h                        //阀门动作:0 Z  L$ m; F  {) E0 c2 B
                        io_Control_Inlet = isio_Control_Inlet_OFF;8 c0 I( u4 {) P
                        io_Control_Outlet = isio_Control_Outlet_ON;        
5 s4 D9 r9 T+ j1 j5 h* k  A( c  n                        g_flagSwitch = isNo;
5 x1 l/ B) j9 q8 e" o6 b  n                        * d$ K4 z/ }; R5 n1 g8 o- i2 s- `8 k
                        //指示灯:
- e# S  v1 _0 H8 g" T( `                        ioLed_Red = ! ioLed_Red;                        // 红灯闪0 y( C2 E! c" W2 b
                        ioLed_Green = isLedOFF;               
1 }! {; r7 E; b7 R- _0 j                        ioLed_Yellow = isLedOFF;                                
* @/ B: \9 D0 P' H7 M( G: B) F                        // 蜂鸣器叫:
( m# g0 q3 X( B$ P& @6 w1 L+ {! x                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
; W7 b/ t' E" e# C3 P                        {
) d: S9 O6 v: d2 [, Q; Z! v                                buzzerCall();                                        // 蜂鸣器叫
" O* }) c5 x# g0 d9 Z1 K                        }. o7 q0 M) d" L& _9 t
                        
9 A% P5 v+ t& d! M5 j& _$ l* P                }! d# p1 n8 W; K/ v
                else if(ulDis < uiL)                                        // 如果水位超低
8 F- L8 [: N- {% T                {1 i  m0 v* E9 G) l6 f1 U2 E
                        //阀门动作:        , Z+ [) Y7 I! ?* G7 G% f* O
                        if(g_flagSwitch == isYes)! q3 G2 b$ F0 ~- e- x- }
                        {                7 Y* e" H* f* K! O( l  j% w
                                io_Control_Outlet = isio_Control_Outlet_OFF;        
- d3 u7 O. Y9 y) j                                io_Control_Inlet = isio_Control_Inlet_ON;        ' I/ i3 z$ b2 N: O7 K" I
                                g_flagSwitch = isNo;
% x. e0 D3 W4 L( G1 {                        }        
# P: `2 s4 N% J                        
9 e3 `; n# ~6 A' L" m4 m                        //指示灯:
, H# R. l, q9 {# X9 Y- m                        ioLed_Red = isLedOFF;
$ N; ?4 _. W' X$ V                        ioLed_Green = isLedOFF;
" L7 P( z  ?; n5 X. z8 ]" w! t& e                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪. d* n! D% f% N: F) N
                        // 蜂鸣器叫:                                                
$ G: H0 _4 B4 R$ j; [$ r# J                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警& G5 J' Z7 L- S& W3 f
                        {
- b7 y0 e8 M: p                                buzzerCall();                                        // 蜂鸣器叫7 `& x6 Z0 c; \( v+ h2 |0 B. U& A; @
                        }# z% h* g- l+ m. c! n2 h
                        - Z8 s1 l$ }  X
                        
3 ^$ H1 ~' \: d" g2 M                }
( n' G8 \# b8 u2 A! O% U                else                                                                // 水位在正常范围
' q; ]" b+ |' |$ w% H+ H. A                {        
1 F0 Y5 a! I8 f2 J$ w                        ioLed_Red = isLedOFF;: m8 g3 s) e3 e9 J% l0 ]
                        ioLed_Green = ! ioLed_Green;; S- y; h& |+ v
                        ioLed_Yellow = isLedOFF;        
* U) G/ O& i0 R0 Q. y                        
  k4 Q1 u- Q* @* d) o* ?+ A                }
2 g- `. Q9 S& k& N; F) O5 i0 n                putThreeCharToLCD1602(lineTow, i, ulDis);( e7 b5 A5 i4 [: V6 ~) e
                return isYes;        8 a# H3 W+ Y; [+ D) w
               
+ Q2 d9 n8 d+ l2 A        }
- |" X% j% `; E2 L* [        return isYes;
6 U% r8 q7 L6 Z, X1 J  q  ]. s}
* j7 y) ]8 ^. _
3 w& k+ @1 ^, U1 B& d) [- q" t/*********************************************************/. P& e$ W2 ?3 k9 z! h. u
void main(void)* W2 P& a! Z) b% o$ k- y
{
2 F# e) W# n: W9 r5 G        initIO();                        //初始化IO端口        
8 R- L; H7 w4 y5 u/ m        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        
2 z4 M2 b9 ~& ?4 \0 }) [7 Q        initLCD1602();         //LCD初始化        
) }. i% S4 @2 i+ y$ ~3 }        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
* H0 U& P9 ?  R. a0 t, H; C/ f        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值  D3 k( A- i( a8 t" F
        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H+ e9 \$ P4 i7 G5 ]
        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值! C1 A( v; B: `% U* `" S& V
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L2 R! R6 _* P0 \- ~6 ?' g1 l
        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值
# h% t2 I) t9 j* ~! X7 @, G. ]        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C+ i2 I/ A9 S5 P) w2 h, Y4 K6 Q
        
* p" R- m( A8 w2 i/ a" V& {        initTimer0();                //初始化定时器0# k, O5 `2 t# I% u
        initTimer1();
2 j- N1 H& a, l' ]! p+ M# R/ h        + k1 K* F1 Q  G2 V
        //阀门动作:初始先排水
: n9 j  V: v. a! g6 m: r/ x        io_Control_Inlet = isio_Control_Inlet_OFF;        # O9 R" F4 {/ g( |# g: S) ~* X
        io_Control_Outlet = isio_Control_Outlet_ON;9 `8 t  ?0 f% o( _, ~7 ]
        g_flagSwitch = isNo;        , V/ @, _) Q$ ?1 M) H
        
' ~/ v; o4 I0 ~* |: M5 u        while(1)( }* I( A8 P, O5 D) h
        {9 A7 v$ ]* X( y. L( c
                io_US_TX = 1;                                //启动超声波模块信号
% |/ v2 Z) O# _  r; Q* d% D$ U                delay10us();
4 }) t( k5 N. t. ]/ v* U! g9 f6 F' Q1 Q                io_US_TX = 0;
% t. e1 J9 r: D                8 p9 k3 `; U) S# w
                while(io_US_RX == 0);                        //等待计时开始1 [; V" j0 j: N0 i6 ~8 ~7 z
                TR0 = 1;                                                    //开启定时器0,计时开始        4 l9 v# r2 w$ q  V/ S  ~
                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)
* [0 w' s& |" }                EX1 = 1;                        //使能外中断INT1                4 k* V0 q) n4 H7 C# X0 Y
                / i: U( r" T/ e' y
                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        ' V5 b# N; b5 p/ G& F- v
                {
- D0 W0 T7 Z$ N6 z( t# z5 @% {: M9 L& v                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
2 ~4 w% i! a; ]# v                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
+ A; s1 K' {5 W; _                }$ B& U1 q# B% j( L7 |' X
               
( U6 f+ |- U! k# [                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环                - z' n2 J1 B6 ^
                + y& r7 X+ h6 `
                TR0 = 0;                //暂时关闭定时器06 g1 q( ~$ M! g8 H
                //清零定时器和计数变量以及标志& E2 D$ V( F" e' X8 k# p% Y
                TL0 = 0;                . @1 L% f, |1 t) M! Z" {
                TH0 = 0;                7 e# Y# K6 ]5 Y5 A, i
                g_flag = isNo;
( ]* h3 y! o" ]! D+ V' l) X                ucCount = 0;3 e' z/ M+ Y+ |7 y- Z- n; D/ ^
                g_flag05s = isNo;. ?1 K  s& q! J; \' r2 f! C
               
! p' h/ B2 F# [& w* ~                TR0 = 1;                //打开定时器0                                        1 K6 F5 d5 b/ \: ]! B
                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果2 ~, O2 j# z! l5 ]" U
                {                        
9 L1 k! P! I! _9 v% s2 _2 H                        uchar ucKeyValue = GetKey();' T7 f* D/ Y+ Y3 F- v& {; D
                        if(ucKeyValue)
  C- ^4 Q) i' K: f                        {' A4 c% P8 L. i$ k
                                if(ucKeyValue == DATA_KEY_DEC)8 b7 d8 N  ^0 A- J7 T# T3 Y
                                {
  r" i0 T( z+ t& y                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志
/ M- I# l! B) E; |/ `                                }
# G6 X/ z* `& Z7 ?1 \- O  C( E+ S( `' |( M. A3 n7 v  P
                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        - v! K) a  E( N9 V
                        }                                
9 h$ Y6 i; Y1 c0 Q) i1 o- r2 `! x
. P* M3 @1 X. t2 A7 n" y) j& K                }        / B0 m  H( Z/ \  J1 P. z$ I' n
                TR0 = 0;                //暂时关闭定时器0# l& ]  `! X8 s+ F) \# ~, t. J
                //清零定时器和复位标志
+ J, @. w. I% o( d% x                TL0 = 0;        % }# \6 Z5 ~5 R1 t- i, t& {
                TH0 = 0;        
! b9 [- G: E! Z- r( b+ a8 I                g_flag = isNo;                ; A& [1 v; L1 b% r( n9 r3 @
               
% `% ~7 o) I% f0 h$ G6 p                //-----------------------------------9 m8 z7 F7 v6 W' Q8 |) {4 H4 T
                //水箱清洗提示:. T" a! l) ?3 `8 \6 T
               
/ F7 y: E1 }% W, J# }8 ~                if(g_flagBeepTimer == isYes)5 y) ]4 t+ s/ Z0 p6 C; y
                {
% ^1 y2 B) W! n: M( S                        buzzerCall();               
- q3 U  `9 c5 M                        //用减小按键取消报警标志/ S  i% |5 c1 P& b4 [) O
                        ) z/ r9 A$ u. Y0 w5 ^6 X
                }  C# T7 t$ \# [2 y$ ]
                //-----------------------------------
9 f+ w$ L# ?0 g8 q5 `, Q               
; E' S1 [8 _. {/ H6 R8 c        }0 z# M' _# s- \, c  P3 I
}7 ]4 v- I- j# `' |" n6 N+ p

8 u9 s8 R4 }/ p8 }* b2 v6 p; H2 }2 g, k$ |* |) X( x9 P8 T
#ifndef __MAIN_H__
6 q2 n" O/ S- H$ }. n" ]+ F% w4 C5 b* ]#define __MAIN_H__6 |* l6 W  j' Y) t
9 v& I" [0 p7 F" i1 I$ ^% U6 r/ e
//-----------------------------------------------$ P' Q# A8 l- l0 ]
typedef unsigned char         uchar;        //为了方便书写定义别名0 ?; F' ?6 v4 M2 r+ e5 |1 V
typedef unsigned int         uint;
2 \9 k! {4 _) t: X! ctypedef unsigned long         ulong;8 y% z/ }7 l3 H, r
typedef        bit                                bool;( d: x8 Z& R6 p$ y/ s4 V5 C; s

. S6 t. M/ J+ m- X9 i( r5 a% osbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口
, G2 k! _' a& f! g) _* G#define        isio_Control_Inlet_ON         0
3 q1 T) x$ Y' N- h* b0 p  [$ e#define        isio_Control_Inlet_OFF         1
2 S9 ~  J! L5 ?$ b* U4 K
0 n; T2 D+ M6 \! ksbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
6 h" M- V: `8 `+ g/ p" a8 l#define        isio_Control_Outlet_ON         0* g& M) h: Z+ j
#define        isio_Control_Outlet_OFF         1
7 N8 [/ N2 E6 G9 v2 e! Z
' x, m( A. o: O#define         isYes                1
; ^5 H" R, h5 H2 F#define        isNo                0
0 I; D+ \8 p* }) X0 E//----------------------------------------------------. O" H) v9 \' A0 `% z, l. n
//定义超声波模块引脚0 _: Y+ j& H6 t" |9 a9 m) i
sbit         io_US_RX          =        P3 ^ 3;        / X, p. n& Q, A
sbit         io_US_TX          =        P3 ^ 2;2 a2 e- I+ u3 W6 f) F: @
//----------------------------------------------------
( G! ~8 w0 G0 M4 ~//定义LCD引脚
4 w/ r% |- T+ ~  Q1 Tsbit         io_LCD_RW          =        P3 ^ 6;
$ j$ ]6 l4 G. @3 X1 l) Usbit         io_LCD_RS          =        P3 ^ 7;
; `. |; x# u% [4 C7 K0 e& U- q& Isbit         io_LCD_E           =        P3 ^ 5;            
2 J% X6 j9 _4 q' H#define          IO_LCD_Data                  P2
( A: X5 E) ^* b8 w3 L' ]  S- r  o" `#define         lineOne                        07 B( T" J% `9 y- ]0 m; w
#define         lineTow                        11 C. `& |- O, r. ]

( }5 i. f( W9 h#define        isReadBusy        1, m* M0 l) V8 o: I8 @. G$ C
#define        isNotReadBusy        0
: G( _1 c  P- \6 r1 n0 x( x3 A4 [% Z. `& y
#define        DATA_LineMax                0x01                //LCD最大的行索引数
' q+ Q9 f* v" n5 V#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置
; j& D8 {8 Y. e; K* F4 v) L" s#define        DATA_LineTow                0x01                //LCD第二行的索引值
+ p8 k  K7 t  ]& o( t//-------------------------------------------6 t" j0 l+ {- `* A  n
#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时
& m" b1 q& s- P) L' X" P( }! h//-------------------------------------------------% L* M8 p5 I. A  _4 R1 C
// 定义指示灯端口
% f2 D& T$ B6 F) l' \3 `sbit        ioLed_Red = P1 ^ 3;
3 F& t+ |8 [" S  j1 Rsbit        ioLed_Green = P1 ^ 2;
; B0 w. y  Q1 C# f- t2 L, Jsbit        ioLed_Yellow = P1 ^ 1;
, d4 Y% o  w5 L* F" s* P; L. `: A8 T' E8 @$ t; @. K  J/ ^
#define        isLedOFF                1                        // 关闭LED
3 q; V: U3 I6 L#define        isLedON                0                        // 点亮LED& _* I9 A9 f% d; N5 W$ ]/ Y
//---------------------------------------------
, x7 b+ K2 X( E* p: ^3 q//定义按键端口2 ]) F& s) F; c% {; Q$ b$ P
#define        IO_KEY                                P1        5 |) E  H1 A+ G! S( N

0 W% i5 n- B* A  ~#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据) j9 ~0 C; y8 P/ g" g$ ]$ p  L4 {
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据
) j9 _: F* V, e* F" Z8 D! T1 |! U
$ g# b9 m, [8 D; A) M  L#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据% q% K$ P, c( Y1 R& e
#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据
" |' Y( z2 q) c' \* b& A#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据9 `6 r1 w# z7 C* ]! l; ?% ?$ g, o
//---------------------------------------------' r2 O) }! q" A: L. J
//定义蜂鸣器端口0 K; n* B4 V, g. ?( E# c# i/ w
sbit        io_Buzzer        =        P1 ^ 0;        5 G3 L, |  i- D7 |; x( I8 H! M
//---------------------------------------------" u3 N/ S1 g: n
//定义检测探头到水库底部的设定距离范围 程序.jpg
$ @/ W6 K* M4 R7 f) l#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
6 p$ a- K- ~+ k* Q#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm5 L8 q% Q6 y" a9 @* g
( t% L! f3 f  \; R; U
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数
( v: {; Y, Y( X#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)1 R& |) r! W' h/ R& B# x7 m
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数5 n$ l: Q. X+ q0 k" A

2 z6 W  z/ @: s# P: L5 T+ r7 ysbit        buzzerCallFlag = P3 ^ 4;
9 _+ {8 K8 W8 @. [# y; y& K+ Q#define        isCall        0
( H1 O& Q: i0 Z7 D0 _0 R$ y#endif( ^/ B+ N: v  d, [6 |

9 A5 ?3 N4 W: }7 P2 b0 l1 p
2 S  y  V5 j' l3 y( M, i" K8 y4 z1 c# E' W- Q
9 g6 B9 s; `5 ?2 {1 Z

基于单片机超声波液位控制器设计.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; _) o: _9 B8 u7 ^/***************************************************************  m8 m& g& H9 f, g5 j
        名称:基于51单片机的超声波水位 ...

* u* Z! y4 z" r+ d又下载一次,打开跟你内容不一样?
- @- V: w4 B+ N4 n" t
QQ截图20201211202119.png
 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05
3 Z  c1 p; I, r0 `大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

; M) F  ~6 R% O4 f5 d/ o是的、是物体都可以检测到!. T9 h( C' O1 s' a  z4 L
发表于 2020-12-18 14:55 | 显示全部楼层
程序Keil、Protel99下载不了怎么办呢

本版积分规则

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

GMT+8, 2024-5-3 01:31 , Processed in 0.081375 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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