一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

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

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

[复制链接]
发表于 2020-11-24 09:12 | 显示全部楼层 |阅读模式
本帖最后由 leishidianzi 于 2020-12-15 14:56 编辑
8 d1 F1 V+ ?% M+ h/ W1 R0 h  S5 E4 t4 J* r! v! Y4 t* C
本设计中液晶显示有4个字母,分别为
H------容器的最高水位设定值(不能高于实际高度)
L------容器的最低水位设定值
D-----容器实际高度(可以设置)
C-----容器内液体的高度(在实际演示中,障碍物离探头越近,液晶C显示越大,因为障碍物好比液面,离探头近了说明水位高了)

% e( D& E2 C% w! }9 V0 M
特别提醒:如果容器实际高度D你设置为1米,那么C液体的高度最高能测到98cm,因为探头的盲区在2cm左右。如果D设为2米,那么最高能测到1.98m.

* Y7 N" s& ]) T( n3 T% |1 ~9 h* v
按键功能分别为:设置键 增加键 减小键 复位键

8 {; [, D4 m5 z6 r  ~: i6 m
三个指示灯的分别功能为:红色----超过设定的最高水位H  黄色-----低于设定的最低水位L 绿色----最高H和最低L中间
                                                             程序.jpg IMG_1539.JPG 基于单片机超声波液位控制器设计.zip (18.27 MB, 下载次数: 21)
! E) p8 H0 {* Z9 O& c1 S
发表于 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 编辑 & b4 Z% F7 ?1 f# i
tdc31224 发表于 2020-11-24 20:58
& P" q# ]2 i+ G没程序?

8 s6 y2 \3 A: H' Z
! P, t9 f$ a; J$ D+ a/ K/***************************************************************
5 i" P9 z1 m" Y7 C) ^6 h        名称:基于51单片机的超声波水位监测报警系统
0 {, R, v* N0 Y. h4 Z9 U. K7 P        单片机型号:AT89C51
$ P7 H! [) l3 C7 p4 c        单片机设置:时钟12T,晶体12MHZ
, H) `) c- a+ i        注:修改增加水泵控制和排水控制,即双继电器% V- O' k- S% d4 A4 L* N; Q
***************************************************************/4 w+ }2 g/ ]2 ~* H
6 U/ E) [  W$ Z6 @/ p! @1 J
#include <reg51.h>
/ [# ^( J0 A; }2 q' s& V#include <intrins.h>                // 包含循环移位:_cror_2 ~; V- k$ x+ P4 e* ]* x
#include "main.h"     * g) l: y  k' y( I! p2 j
//----------------------------------------------------------------------
6 |* j# [' W3 I6 O$ Q7 g! v1 |, i/ V# B0 d+ U" N
uchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};# f# o. \9 W5 O- H: r
$ R! ?9 d. F: ]7 o0 N/ E& e4 V- j& |
bool        g_flag = isNo;                //用于标记超时(65.536ms)           
4 o# p# Y  e6 F$ Mbool        g_flag05s = isNo;        //用于标记0.52秒  " E2 r, {' Q; x1 ]) z" Q) X
uchar         ucCount = 0;                        //用于计数0.52秒     ( r1 B) d  X, s2 s$ U! {

* S7 s9 g, T  \2 o  v# p$ G/ e) Guint        uiH =  86;                        //设定的最高报警水位 H* A3 P/ r3 i5 D
uint        uiL =  73;                        //设定的最低报警水位 L
3 u% T# _( Q4 a/ kuint        uiD =156;                         //检测探头到水库底部的距离 D 7 s$ U( z1 @. }! q: B( q4 {9 x

7 r9 R8 @8 T. v1 ]% O& Gbool        g_flagSwitch = isNo;                //控制阀门连续开启间隔延时(保护)标志0 L) v$ m; A: N# [9 G7 b
bool        g_flagBeepTimer = isNo;        //定时提醒标志9 i( `0 z7 G6 B" p0 E
                # c0 U/ `) {* p/ U8 ~
5 P7 g% |- h# c
//-----------------------------------------------------------------------: ?, x: b. _- J( m
// 延时10us
  {: }& p& d, I6 e3 T- ^, ~; ?void delay10us(void)                //@12MHz, ?* [5 p3 u+ x6 L, @7 Y. J; \9 b
{
0 x+ `* ?! j3 [8 o% c! `1 e5 y5 ^        unsigned char i;/ x- ^$ v$ e2 G. A! C
' i' p# b# ]9 s5 m
        _nop_();
7 e/ V7 `; \/ k1 j# L0 ^1 ?        i = 2;
& I4 A5 i3 G/ T) `& A        while (--i);0 G) ~! n7 o' C4 ?' y
}
& q# b: U: U/ T: D1 v$ Z/ h# O' e3 v/ l7 k. T, W2 h( D$ `( M
// 延时100us1 [% I5 v9 U1 d# Q& B, ~
void delay100us(void)                //@12MHz. B% W" W( S& l1 K. K5 \# p
{
6 k& f9 ^$ c- ~8 B1 T* B8 G        uchar i;  \4 s) \2 q& w

& J- l( Q5 S( W0 H9 N% Q        _nop_();% S" z1 u+ X1 ?* a6 Y3 j7 D
        i = 47;( o6 ]6 n0 [1 J' ^( K
        while (--i);
4 u3 I, M6 f2 H# k2 u$ c6 z}
; v' b, G. _5 `+ q$ [3 r
) \+ ~) N+ p  |2 H2 J& V/ R2 h, b// 延时125us4 [: s% B% T3 _% i
void delay125us(void)                //@12MHz/ r$ D9 B8 X& [
{2 x/ ~+ @6 p* C3 a& |6 B7 {; K; g6 ?
        unsigned char i;$ d6 ~  ^! {( J' L' `
        i = 60;
  R7 n/ o5 S; F2 |        while (--i);
) w0 \: L# H. u}
# d2 n, @+ t; v% H! ^$ e$ x( J( i! g3 [& G
// 延时5ms
6 r! [$ m0 c# p( X* Y: tvoid delay5ms(void)                //@12.000MHz. m! b+ I/ N5 E9 R
{
; a+ E) ^: j& R" O/ n8 ~" y        unsigned char i, j;, y6 `, q5 s+ d' _
1 n8 t# v8 F8 H' \! S/ |" }& w) ^+ W
        i = 10;
& @" ~% U% v7 x; N; R9 \' _. g        j = 183;
1 ^3 i( x) d3 |! m4 V& k0 P- B5 a        do& m+ G% z) B3 p( E
        {( \/ i$ Q+ S- L5 ^8 p
                while (--j);8 E( ]5 q8 `& l1 l
        } while (--i);
+ B( d7 n/ `9 X- [( B}: D# @+ }. ?# Z) b/ x" M

! `' s1 a/ J( W// 延时500ms6 E( B! p& a; @8 n% T
void delay500ms(void)                //@12MHz; x0 \8 ]5 V& F/ q* g
{
; [4 M& H1 q$ ^6 m! _' U$ |        unsigned char i, j, k;& v8 D$ {2 n1 M0 ~  }
1 ^+ T! j- a9 F& h: H0 h1 W3 ~
        _nop_();, C: u( [& K# t
        i = 4;
% R4 x# W$ a( m, q        j = 205;
/ F( r. h* x8 y8 q' [, j3 T        k = 187;
, \) n  Z( w& b$ @        do
- B; d7 q2 w' I        {
2 a2 }4 Y$ y- A9 I. ~                do
0 Q3 L* z3 x# f; e; }% W                {
5 H! n  K  e( t) P% X3 X1 }                        while (--k);
8 x. l5 ^4 z5 c7 k                } while (--j);
: w, |/ p' w( }        } while (--i);, w9 Q0 ?, f2 x4 @
}* `  v0 q1 j' G2 X8 H

- _4 V4 B$ U3 `& r//-----------------------------------------------------------------------
0 V4 p; U& Z+ q( q( l9 F" o/ C//初始化IO端口                        
) D6 m3 w. S# j% U- S# cvoid initIO(void)                                        / I4 f8 z! z5 a1 [; [; P- X' s
{
, z; q) O/ e; D0 [6 Q8 R        P0 = 0xff;
1 z& p& a( C/ v        P1 = 0xff;
# G( ?7 H; t8 g) T) y6 B! W        P2 = 0xff;
. l4 J: J( [4 X        P3 = 0xff;: H; ?& a( z' X
}
2 `4 }& z7 `8 C+ B' n8 y+ S
8 y# x; q& d2 c6 d// 初始化定时器0,定时器时钟12T模式 模式1,16位 @12.000MHz4 Q5 u% L. I8 w8 O3 f
void initTimer0(void)                : i8 A( B2 H+ ]( Y, H8 v
{0 E6 J5 ^% x7 g. e! b3 h
        TMOD &= 0xF0;                //设置定时器模式
& w) v+ \) Z' M        TMOD |= 0x01;                //设置定时器模式
" q9 l0 k6 K3 d7 ~2 k3 {% y4 |        TL0 = 0;                                //定时器初值清零
& P0 X/ K% M! C# T        TH0 = 0;                                //定时器初值清零/ V0 p4 a, f+ t$ m5 L+ W
        //TR0 = 1;                           //开定时器0
( z7 @$ ~0 z7 @7 P$ r5 `; R8 S    ET0 = 1;                          //开定时器0中断9 x4 d% |1 \* h! [' ^1 Z
    EA = 1;                             //开总中断            , g. d% }* B; `" j
        
4 B) C9 h, ^# Y. C" ~: c+ o, a& {: t" m}
" B. F$ J& W- ~7 x# }! Y4 s
- P5 M& S: z# f" i- t( i// 初始化定时器1,定时器时钟12T模式 模式1,16位 @12.000MHz
5 e0 [; [, _6 G4 T6 D) y( `1 H, Lvoid initTimer1(void)                //50毫秒@12.000MHz0 u3 P; z0 o) w, a
{        
, D( E" ^5 Z, a3 J% T        TMOD &= 0x0F;                //设置定时器模式- x7 k: `! L$ {4 ~7 t
        TMOD |= 0x10;                //设置定时器模式: g, Z; [7 ~' O( o0 g
        TL1 = 0xB0;                //设置定时初值
' S, B4 C& g- n* {        TH1 = 0x3C;                //设置定时初值        3 o- g& Q. R* L- ~- z
        TR1 = 1;                //定时器1开始计时! L  D5 d) s9 m
        ET1 = 1;          //开定时器0中断3 e) J. Y1 K" m. H0 W8 y) r9 C
}
2 }2 f- ~0 w7 S" [, a
- b1 f: W5 S4 n) E. R//-----------------------------------------------------------------------
& J3 N+ A5 q6 v$ C( b//定时器0中断4 z2 o$ o4 k) x9 C. a
void zd0(void) interrupt 1                  
# f8 X( A3 \6 ]2 \/ r- O' E. J{
: z1 ~, r0 W3 e: H' S  v7 o        5 `! ^) f9 U+ ~! J
        g_flag = isYes;                                                        //中断溢出标志,g_flag = isYes超过测距范围
4 V+ i+ E/ b! `* F1 c        if(++ucCount >= 8)/ H& X+ `* m7 V9 R6 j* G8 j% L
        {
, O# S& v6 Y5 e8 z) M# L% F                ucCount = 0;
4 U, B! V; f7 n5 v1 L, O4 e. K                g_flag05s = isYes;                                        //g_flag05s = isYes定时0.52秒到,用于测量周期延时
5 `: p( }5 C; Y0 y        }, c' \7 ~# p% X) L8 ~" a% D/ b
        TL0 = 0;                //设置定时初值
# |1 u+ Q9 d, V- n4 n        TH0 = 0;                //设置定时初值
* B/ Q0 \5 ~1 w7 {: B' c2 M        2 L! o+ F% T9 @7 V; g+ A8 O
}
# G# y9 M. K% Z9 G/ r. m5 {- {" f# b# T- M5 |& q, J2 O1 x
7 l4 H! Y- a% r5 a
//定时器1中断 定时50ms. s/ g6 E$ t2 U8 Y, W( ~8 Y
void tm1_isr() interrupt 3 using 1
9 A: Y, Z4 _. v* q, `. g{
2 U8 L, [4 ]$ w        static uchar count = DATA_switchTime;        //50ms的200倍 = 10S
4 |7 V1 S1 Q) }4 o/ K% J$ Y1 |        static uchar uiCount = 1200;                                //                        = 1分钟               
) c4 f) Y/ y/ f& F/ g. y- G        static uint uiCount_BeepTimer = DATA_BeepTimer;) j/ K% ?( R% c" ]* H/ |* j2 |
6 I6 b  O" C& s/ {1 O
        TL1 = 0xB0;                //设置定时初值
6 }" B1 d$ `7 }4 D        TH1 = 0x3C;                //设置定时初值
+ M, l. u; K# [2 z  x; V: ]# `, U4 H1 p+ d$ ]
        if (g_flagSwitch == isNo)/ j3 g- v8 H# H5 T5 E
        {
4 v9 `& I- x4 i6 }0 i' |                if (count-- == 0)               //50ms * 200 -> 10s
$ h& V+ k  H7 f6 J/ t  o8 F                {
' g5 L. W; v* ]: r                        count = DATA_switchTime;. ]& z* f$ }: @- E3 M  G- e
                        g_flagSwitch = isYes;5 M1 ?3 ?# q7 c+ O# a* U( E
                        // TR1 = 0;
! G3 L% p0 G! E) N4 p% ?+ e/ Z                }. ^' O# {8 R/ N" M5 X: Z0 Y4 n
        }        6 J  ~; S# `9 N; A5 _. s6 L
        ' A: B1 m6 i0 o6 R
        if(g_flagBeepTimer == isNo)! D. B+ q4 L+ i
        {+ l1 V  G3 N4 T- T1 U$ {
                if (uiCount-- == 0)               //= 1分钟
8 `8 O2 E* S. O* }                {
% Q" \2 [. Z: E' I# c5 H$ a6 j8 K. [                        uiCount = 1200;
3 U! v. U3 h! U( T                        if(uiCount_BeepTimer-- == 0)
- ^$ O% R4 ~$ K6 h: S8 j7 _                        {
/ t+ C+ h  ^" {  d: N1 W: X0 ?                                uiCount_BeepTimer = DATA_BeepTimer; # V6 z1 ~. F( u0 x, F1 `5 U" S
                                g_flagBeepTimer = isYes;. }: R& U' x& r4 I
                                // TR1 = 0;
9 s  `  ?( }7 F- I$ y                        }                        0 f6 M1 W: R- n, d; i1 S4 |1 y
                        
/ s; D2 _7 @$ j3 ~  L$ T                }: m5 \1 f& J7 [

# n" e8 P+ v$ n5 K        }
! A, q) P, Q$ i. |}
/ y  u1 I: _! x' F
3 e" |  l4 u, a. e8 V& m' `//-----------------------------------------------
5 P2 f# @* [* g6 T: v* G) B) p
% ]1 ~5 p' d  G" [6 X5 }; ?# u  {+ r5 A( E: B6 G
* c- L% T& E4 q) v$ H

) k8 N; W) `, p" z+ ]0 t0 y3 J' p: h  g0 w3 y' R1 k  w  ~
//外部中断1* }6 K$ ^  o% p8 B2 H
void exint1() interrupt 2 7 k" R) X6 A3 v" S- F3 G3 q
{! h2 C& G+ R; _' s! ^5 o
    EX1 = 0;                         //关闭当前中断! t5 g7 {# O' \+ M  J! [# x
        TR0 = 0;                           //关闭时器02 ^( [2 n( M5 p) k# ~: h' x
        
: P8 W* ?' X" v1 s5 b* j}$ P) f* r0 S5 ]$ s8 G( D9 G! @
//-----------------------------------------------------------------------0 ~  U# x8 e- Z3 L6 h2 y2 _3 o

; }  v, K' J, C6 t9 G4 a# }//读LCD忙状态并等待忙状态结束
3 X) ?4 y( D; a/ `0 l0 Wvoid LCD_waitNotBusy(void)% u+ V  n! E- I5 N
{7 ~% `7 d9 p' y8 ^
        IO_LCD_Data = 0xFF;
; I- o) d$ W. Q+ }7 a        io_LCD_RS = 0;
) n5 Z( n( _6 C2 l! p        io_LCD_RW = 1;! c5 N( L- j. ?' `
        io_LCD_E = 0;
, c6 e: Q! U( P  \- ~4 m( _  V% l        _nop_();, t0 m" d1 u4 U' f2 J% U" \
        _nop_();
' q: T0 s1 P' Y5 _# ~; ]        io_LCD_E = 1;
. b6 S- I& F! J" Z9 f5 P        while(IO_LCD_Data & 0x80); //检测如果是忙信号,一直等到不忙
* ]' E( L/ i5 C3 i% a1 _}$ [2 n( x" L( o0 P$ t7 j0 {( L

5 v/ `0 G8 T1 L0 u9 N//给LCD写指令$ y5 k4 n0 h, R; k9 h5 V: `
void LCDWriteCommand(uchar command,bool ifReadBusy) //ifReadBusy = 1 时先进行忙检测
: j2 x! b0 b& i: M( ]- V{0 r! @, m7 `3 V( Z1 P
        if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); //根据需要检测忙/ K5 c/ s2 T! n
        IO_LCD_Data = command;% T, t" a! E- ^0 g2 V5 ]4 Q: W
        io_LCD_RS = 0;  l$ N" Z/ Y$ S8 f7 }  ~5 B4 ?9 X: v
        io_LCD_RW = 0;        ' B7 n; S& ~' L6 q  M5 S% J3 F8 L
        io_LCD_E = 0;( O  B6 A5 V1 n6 q
        _nop_();. c. u- U; c+ Y; A) S) N
        _nop_();
: b0 X% I; {  E6 W( E        io_LCD_E = 1;        
+ m' \! S% T: u9 }7 u}' m! T1 N5 N% h+ ?2 w' j

# y9 m9 b( ]. C/ ^2 O//给LCD写数据
" B, y$ w  K' Z9 Y2 s  [; Avoid LCDWriteData(uchar dat)
+ ~. ~" e! H; k- A: T- X{- }3 u* Y4 B- Q" R7 f
        LCD_waitNotBusy(); //等到不忙4 Y& d( t2 T- k0 z( p5 P2 Y
        IO_LCD_Data = dat;
1 h( f& l) G4 d8 v! E        io_LCD_RS = 1;
* v9 U- M$ h& {        io_LCD_RW = 0;, [' L( |( m" x6 J
        io_LCD_E = 0; , G: p, _/ W: w6 ], r# L' g/ v- n
        _nop_();. y3 y; H3 k; j% k9 x
        _nop_();
, F% o! S; S; A" X        io_LCD_E = 1;
1 f- P! W$ J( D  ?# A: J}0 M( L9 V7 }* g) F
1 [, Q; M$ L3 a& s! ~
0 e+ u/ r7 r+ n" |
4 y% |; i, @! q4 [1 M3 l6 z
, I  v5 \& ~: Q
// 初始化LCD1602液晶显示屏" f! z. a4 q% U3 z1 S& T/ l7 m' X
void initLCD1602(void) ' J9 A0 I- m: q( M  g
{
8 l' ^& J6 o$ N( S3 w3 R; F/ j1 c        uchar        i;        
% I5 U; A+ C. h        IO_LCD_Data = 0;                                                                // 数据端口清零
, t2 Y: V- n( Z+ T        for(i = 0; i < 3; i++)                                                // 设置三次显示模式
3 Y% `  ?% _- N+ Z  Q        {7 r8 B2 Q2 H3 Z+ q7 J" c
                LCDWriteCommand(0x38,isNotReadBusy);        // 不检测忙信号+ S% H1 Y: f# ]5 t& y: f
                delay5ms();
  w; y+ r. N# n/ Z% c6 P* S  D4 w        }% ^" x( y% Q: g8 n9 A9 D% `3 Z7 k5 X
        ! |5 h  H+ s4 i, |+ r
        LCDWriteCommand(0x38,isReadBusy); // 设置显示模式,检测忙信号& x+ U) b: ~9 C% l! L
        LCDWriteCommand(0x08,isReadBusy); // 关闭显示  u+ ^3 v5 K& n4 N9 i4 w! F) v) O
        LCDWriteCommand(0x01,isReadBusy); // 显示清屏
+ G- r% A0 h3 d3 Y        LCDWriteCommand(0x06,isReadBusy); // 显示光标移动设置
2 b: f# d" B' D$ h: ]" K        LCDWriteCommand(0x0F,isReadBusy); // 显示开及光标设置
9 H+ B$ N- h. \/ H% \}
* ]" Y5 T5 D$ R: c) a0 ^
, P& z$ r  z6 N, T% d/ Q
; y8 _; Z3 t& b3 |% _2 f/ M
5 N  D- x1 M5 M//按指定位置显示一个字符
1 V" t* E4 u3 @* Fvoid putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
  w" \& T8 `: d3 J8 ~; i* g! j{
. w% u9 X0 x9 P) T6 K
- S" ~2 Q1 ]2 H/ C+ Y        line &= DATA_LineMax;/ n) E( m; K* o/ j7 X
        position &= DATA_PositionMax;- y% f& t! z3 m3 l5 g8 v9 x
        if (line == DATA_LineTow) position |= 0x40;                         //当要显示第二行时地址码+0x40;
5 @* G* W3 o/ D) [9 D& d1 s        position |= 0x80;                                                                         //设置两行显示格式 D7 = 1;
! Q2 i; E0 J4 x, e$ u        LCDWriteCommand(position, isReadBusy);                         //发送命令 设置字符地址
; f$ N( p( @8 C! O, y9 Q, \        LCDWriteData(ucData);                                                                  //写入字符的数据        
2 X! G( Y% j3 P- w' S4 s}
+ ~. h& j: }6 M! k% B# l6 I: Y. T- l$ [7 h, g$ m$ e+ T" D
//按指定位置显示一串字符+ b; @- @1 P* Q1 K: K  t0 n
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
# A' P. q' ?4 l" R/ b) h) \2 }! N- i{- ]: l& F: f! Y- N
        uchar i;6 v+ M% C7 f; C0 x( |7 E8 L; ]
        for(i = 0; i < count; i++)                                                        //连续显示单个字符) N0 [+ |: M/ I: v: C
        {
# M, T4 s# ^! p: ^; T. ^4 j9 X! D                putOneCharToLCD1602(line, position + i, ucData);        
4 W( T) v2 G) v! i* L5 ~& P        }
. c- k8 _& E  d  |" m}
0 P6 f* ]; N7 U% @' J
4 Z6 g0 s) {5 W4 o' d& g* @+ y8 a) n9 a* V5 s* W  p& d( m
//按指定位置连续显示三个字符(三位数字)
( D% M# v, N5 }( i6 x* vvoid        putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)
: g  q3 [/ g# T  s, i% _' a0 x{$ A! N/ W2 _, }. M: c
        uiNumber %= 1000;
* q2 ?. c8 ?* h- o) J5 o: [        putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);1 N+ R$ s# I& X  N% B9 t/ G  |
        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
# \# O/ ?1 N6 I" r$ u5 P8 `) _' P! C        putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        , v# e, g5 e  ?. D6 A& L
        
  s5 D- F  X7 m}
8 I6 k" A/ g. a5 d* g        
- x- e9 r! m3 n( E( R+ ?2 j- r7 {+ J; P+ o

& i/ W$ \9 V( F4 ]// 按键检测子程序,有键按下返回键端口数据,无键返回0
. X2 X' @8 T6 N3 R4 H- d/ Buchar GetKey(void)4 v1 Y# J3 X0 t' q- D( q8 X
{        
9 u8 @7 D9 d  z( V    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);                //获取按键端口数据        8 l5 w- ~5 v# v7 W' s
        
% c5 s$ `3 e' O7 l& W& u+ b        if( KeyTemp != DATA_KEY_Null )                                // 如果不为空) \1 k6 o3 \2 E& w2 M. X% M
        {6 K8 g& K- v1 M( P; U9 e
                uchar CountTemp = 0;
1 U7 A4 Z$ P& g3 V  D                do
3 C8 ^- K2 t; J( \& q                {
' X' ^. h! o* x7 ?4 s  {                        delay125us();
" b/ N. |0 ?8 r7 }* d                        if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;        //在延时期间检测键,如果不稳定保持则退出        
, ]; i" I* Y; B0 N                        ) w# N6 i' s* Y1 {6 |
                } while(++CountTemp > Data_Key20msCountMax);                                 // 延时20ms去抖动 2 ^3 m$ u2 P7 l/ @  {
               
  u* h( y  B( |+ B7 |( U                while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         //等键释放                ! c. j: s/ ^% k* X/ a3 s
               
( d4 I6 n" @: L; o2 h                return KeyTemp;        // 有键按下返回键端口数据
; r$ a% Q& `5 g+ `/ C        }. `/ d" Q) Z9 A
        1 Y8 o7 k! R; @
        return 0;        // 无有效键返回0
5 G0 [: B; K+ K; l9 X. F}
" i' }8 ]: A( `( ]2 X) v+ R+ F7 k' E- {3 v$ k/ I* F9 `4 L% G
  }. {' b2 d: Q) ^5 C5 A$ c

$ X& _9 M$ ~, E8 u( E( T1 }  ]1 k4 P  S//加一  U0 @5 f( W" W2 `* \
uchar  INC_Number(uchar Number, uchar Min, uchar Max)9 s( ]3 k* P" A9 C4 l' C' T( H
{
+ c$ W" u) Q# m. ]8 U( f        if(Number >= Max) return Min; else return (++ Number);
. R3 c) s+ \0 n, Z6 R                ! i2 l" B: [6 F
}
# C: d( W7 J. ^( {1 o( s7 ]
1 p( L1 |. u+ k//减一
; c3 L0 n- d1 E% `1 t) R: D' @uchar  DEC_Number(uchar Number, uchar Min, uchar Max)% S; N0 H+ ]* B) L2 ^7 w/ c2 {1 o5 ~
{8 _2 u5 f3 @# j- _$ w5 Q
        if(Number <= Min) return Max; else return (-- Number);( x: b# K! K8 n
                % l  o* E5 i- s6 K5 [( F( |6 f9 k
}
$ H5 n8 k2 L' n* p: r0 R3 H# o& w* _) Y
// 检测到有按键后 这里执行按键任务                        
. x1 H. r- S* s, vvoid execute_key_task(uchar ucKeyValue)        
' G2 W% M- J' t5 v% g# D, X4 V, l{7 X! h: }* h0 w- l) _$ @4 P" w* S
        uchar state = 0;                                                //定义调整数据的状态变量
+ i  K/ Q+ Z; N        uchar keyValue = 0;                                        //定义键值的临时变量4 j. j. i1 j  D) i. H
        $ U9 V0 @, z. g
        if(ucKeyValue != DATA_KEY_Set) return;        //不是设置键退出& ]5 ^1 X0 V0 U+ m  E2 {
        3 ^5 B) L' o& Q6 B* d. G( u9 U3 Q
        //是设置键继续-----------------------------------------------------
  Q0 r7 E$ G7 F" ~/ E/ s4 h9 V8 b        
- [5 w8 [* Y& N* W        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //清零显示当前距离CURRENT               
6 c* q& M5 q) y" w+ Z' K) B$ M        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //光标调整到调整总距离(检测探头到水库底部的距离“D:000cm”)        : a) |( t- m, g
        1 s" m8 x* I  C4 k8 z% L4 T
        while(1)' i% G/ \* D  B: q+ P, S/ Z" C
        {
+ x: R2 T$ P& I! L$ ~                keyValue = GetKey();        0 c- {2 C0 _9 s- T* ?) ~! F
                if(keyValue == 0) continue;& e$ C' q9 Z- c/ U
               
$ N3 K3 f7 V) K/ S  U4 ~/ ?8 d                switch(keyValue)
- b, \5 f- t. p1 k& L$ H                {
. P; d4 W) ~7 ]' E+ [                        case DATA_KEY_Set:
' e% p; G, W, j                        {% ~) x6 c3 N. L) F3 j& T# a2 X
                                // 如果按的是设置键,顺序设置总距离D——高水位H——低水位L——退出
# A6 i7 ?# V. z+ L$ o3 \1 q                                switch(state)
$ P, b) t: L, H- {3 j) Z                                {" r8 S2 A( I9 B. i  v/ y3 c+ _
                                        case 0:                        // 如果是设置总距离状态,改变为设置高水位状态,并显示高水位,实现移动光标到高水位后面' g0 j) C  {% R, z, j
                                        {
( ?* _* E% c3 V3 p$ R" y# F                                                state = 1;                                                
  M# N4 {$ I! \# k! I) L                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                                                
0 f5 S- t( z5 {4 D. w: F                                        }8 W' l# j3 X9 X. U+ m5 Q
                                        break;- ?5 u9 E: l' m3 w6 |5 @
                                        case 1:: l: y" ?5 {7 ~1 ^2 j) M( U' ?
                                        {0 N/ f) {- N" }
                                                uchar tempMax = uiD - DATA_uiD_Min;
( O" C* {: u/ D  Y3 M# O5 i2 h; _4 Y                                                if(tempMax < 2 + 2) tempMax = 2 + 2;                                                                                       
0 C0 d) p& ?5 `                                                if(uiH > tempMax)
0 A. E/ p& {5 T; o$ q/ `) k                                                {9 o6 y6 e' ]9 h+ T* j5 q
                                                        uiH = tempMax;
& {5 }/ U: l6 X4 T1 Q                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
/ _  ^. b& q0 I$ i- ^: L  p                                                }
3 c- g$ U3 Y6 _9 {" E                                                else if(uiH < 2 + 2)% t1 g4 m5 C& U& w. y4 f" L' C7 X
                                                {
7 M9 _/ B7 ~' h) s  }/ I                                                        uiH = 2 + 2;        ) {* \* J% G. U7 V
                                                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);5 u. K3 h+ X, C
                                                }                                                        ; x3 Y& S8 o- R7 E. g
                                                state = 2;
) O3 ?3 |8 ?' L' d) a                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
$ k2 Q+ \( U4 L- Q                                        }0 X, s" N" v- U3 U3 x  k- l) M( ~2 L
                                        break;
9 w. m2 g# T  J" k, R                                        case 2:
. B/ l* @' V- R, i  O$ Q% \                                        {
; U0 ^7 k$ ]3 T3 I2 A1 o3 P                                                if(uiL > uiH - 2) % n! l! @3 _4 M/ \% y* H
                                                {
8 v* V8 Z4 H# l                                                        uiL = uiH - 2;5 `% I5 _9 p8 s% W5 A; y
                                                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
6 H1 I5 e, w7 Y7 q7 w# C3 a8 z  m. T! _                                                }
. X& g$ F# F; f* @/ ~" h                                                return;        
+ @: a$ q" T! f! s                                                
, E* l5 O5 V# f. l                                        }
8 n9 u1 ~) I! s- I. l& [                                        break;  X, B+ @' R2 E$ w3 e/ i$ D: r# S
                                }
2 c/ S# s. c9 q: d# `; e4 X3 j                                ) @: n2 w  J, |" S( y& ~. q
                        }
8 X) k6 K  U3 F$ O8 O0 v' h2 b, B                        break;
" _/ x$ ^4 s2 \  `" D- m                        // 如果按的是增加键,改变相应数据并显示  W1 ]7 s) C1 B
                        case DATA_KEY_INC:# d0 ~" }5 M: l% H( p3 P
                        {
* v+ O* C3 ]: P3 H* ^                                switch(state); F0 l5 m( _5 ]4 j: t6 Z) m; S
                                {. P: S3 X; o4 q' B" D8 P
                                        case 0:
6 J0 E5 E# T8 m$ Y                                        {' F+ t& p% G1 ]$ z0 H7 t( b
                                                uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);, k7 }8 n# g2 J0 S7 i$ o
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                                                        
  b1 ]7 O1 J) X. H( r                                        }+ V; j& v4 v4 k+ l1 N
                                        break;  Q  v( S8 l5 L4 n1 n7 g( \; ^- {$ F
                                        case 1:1 F8 ?# W) Q  b5 ]! d
                                        {
; T3 `% K& X/ b: x  x9 y                                                uchar tempMax = uiD - DATA_uiD_Min;7 S8 q7 m( i  b* U- q
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;0 ^5 K: S2 ?3 l) R8 E- a* K; ~
                                                uiH = INC_Number(uiH, 2, tempMax);                                                % f! v- f% h9 _
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
9 C+ H: s' A  p+ _! ?8 A                                        }
0 [( B$ d- _" d# E                                        break;
! I9 U6 V" s6 f" t; J- z' B" V% }                                        case 2:- _. q! a, P+ ]- J
                                        {
% ]0 J$ [9 s8 V0 J. H$ k. F                                                uiL = INC_Number(uiL, 0, uiH - 2);        : v5 q2 B$ l, `2 B9 e+ ]6 w
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        # W6 q2 \2 m  [1 K
                                        }
9 A8 x" e- N6 P# O& F( x6 O                                        break;: S) [# B. X; H# M
                                }5 w, W0 l3 K; K' z  j
                                $ K* E& B9 E4 G. Q& V
                        }
" p% L* A$ W  v7 W; h& S4 @                        break;5 \) h* v) @, D. q
                        // 如果按的是减少键,改变相应数据并显示+ \- {: x4 N" H6 x: h  g
                        case DATA_KEY_DEC:( ^, N: ~: E* K4 P- c! S& U
                        {) X. D9 Y; z2 Z, n; ^) {
                                switch(state)
" a- J# u+ c+ Y                                {
- M. V! c/ F# d) c* }2 L9 g5 M5 ^; o                                        case 0:% K# B2 f) ?. I0 D& H& N/ v
                                        {7 f' u* {" \, |! U. c
                                                uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                                        ' @1 X+ U6 r& J% L; Q6 I
                                                putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
) p  V( E% |. c0 r' H* Z  r2 j* r7 t8 ^                                        }
7 n7 `6 M4 a  i- ]8 F" w7 Q, M                                        break;* t/ _# T, \+ r% W9 ^! Z
                                        case 1:
& [  v. m) |7 x9 u: [% y                                        {1 j0 A( g( s3 ~/ J- E6 d* D( f% C
                                                uchar tempMax = uiD - DATA_uiD_Min;1 D5 }: i+ w" A* O& a1 T
                                                if(tempMax < 2 + 2) tempMax = 2 + 2;
. ]! L3 z* q; A4 @                                                uiH = DEC_Number(uiH, 2, tempMax);                                                - a# v/ h% c, ?5 v9 ^; t
                                                putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        + R% ~4 H! N( {% h# D

4 K$ w: l% r$ W9 S: Q* t+ i9 x                                        }4 J/ `% U5 ^$ C/ k, B1 X
                                        break;
- K4 H7 f; d3 u# z! T* e                                        case 2:% y; _/ `( N" z, \& n2 K* V+ k4 r
                                        {
  g# D7 q, s6 m$ R                                                uiL = DEC_Number(uiL, 0, uiH - 2);        " W) K4 l+ y3 l1 d
                                                putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        ! w7 B  i- Q- w; `, T" I/ \

) j, S$ ?, i9 c$ d' ]8 ^5 d                                        }
) V6 F6 R- ?8 Z                                        break;+ q/ p/ u, \& K: A. m5 |
                                }$ B7 y( Q1 y. B! P7 f2 W8 p
                                ) P7 l# j7 r$ ~3 V( h- j
                        }
3 X* R" j, a- v4 k4 J5 B% h                        break;6 ?- Y% V; l0 S  q" X( n7 d
                        5 V( s8 l/ a& d5 d2 y# t
                }
2 u9 K1 ?+ T# U* m               
9 b+ N& I6 L  R. M6 |        }
2 P2 f( Z: ?/ T# H        
  Z( K8 g7 s9 z% {: p: Y8 L6 I6 q}. b: C3 i% N4 L" \

' f6 e3 A  f& {# j7 C
4 L$ I4 D4 S, t
( n! V- S: G6 M3 j9 R// 蜂鸣器        * ^. o$ Q- [2 Z
void        buzzerCall(void)7 z: ^: w" x2 N6 y8 Y1 |
{
7 N/ F$ Y9 ?- O) |/ K        uchar        i;
2 x. a" o/ b( |+ c( J) C/ ]: A* h        3 o0 O8 ?3 H1 f5 M. d
                for(i = 0; i < 90; i++)! I/ Y" d) q& K/ ]; B0 T
                {
# I* B# M, ]- x' f                        io_Buzzer = 0;
  L4 B: `' ^3 r                        delay100us();
8 l; t( R0 e* Z' S. q                        io_Buzzer = 1;% P/ d# v5 `1 m. h
                        delay100us();2 C' F* b" u% W, q- q/ W  c4 A
                        delay100us();                ' L. d! m  A: X- ^2 B
                }
7 H+ _: q- T& O( e7 Z4 ]                delay100us();        * p  j1 \1 b. f9 J" a  W7 m
                delay100us();        - X; U: L: }$ `2 T% g1 ]
}* q4 }4 r7 j# H- L, [! W
5 V, B/ s8 J# k5 Y! b
//计算水位
6 N' @6 |- t/ K" y  \" ~2 bbool CalculatedWaterLevel(void)3 C( e& V" `+ h
{
7 Y. M! K2 I5 n3 j8 r        uchar         i = 8 + 2;                                        //当前水位的数字在LCD屏显示的起点位置/ m7 `8 N: }7 w7 W: ^
        uint          uiTime;                                                //声波传播时间
: |) K7 w0 G+ x; \; q        ulong         ulDis;                                                //实时测量到距离        
% K& ~( b0 b6 F5 x' X# P        - _% W4 M# i9 O3 J) B  `
        uiTime = TH0 << 8 | TL0;        
- d# {1 k6 ?; F% ^2 e3 z        ulDis = (uiTime * 3.40) / 200;             //计算当前测量的距离,单位cm2 S" s3 P- R4 ^) g4 v
        2 V) P# T8 X. \' K1 Y+ H
        TH0 = 0;
3 W7 T+ e( x, X5 b        TL0 = 0;        
+ H2 v$ _6 o% u3 \        , Y& L! f7 ?5 k  ?
        if((ulDis > uiD) || (g_flag == isYes ))         // ulDis > uiD 超出测量范围;g_flag == isYes超时;
! g' s! D/ R9 J8 s1 r' r        {         
4 X' T7 q: |" Z3 o6 t, Z                g_flag = isNo;               
( b* Z; Q: Y: U8 d0 `: G/ x) T1 o                TR0 = 0;
4 u2 S" }! D5 [' \                putLineCharsToLCD1602(lineTow, i, 3, "Err");        // 显示Err                 ' ^$ u4 x- x  e
                % j/ ?1 C; ~) n5 t: N$ ]; `
                //阀门动作:                5 t, ^* ^8 ~7 q% x' z$ O
                // if(g_flagSwitch == isYes)
) M& b: n) K7 V% [                // {               
) F  _3 B8 J  P6 D# Y! V5 V                        // io_Control_Inlet = isio_Control_Inlet_OFF;               
3 @4 e. z# K$ p0 V7 h- A6 @                        // io_Control_Outlet = isio_Control_Outlet_ON;; E! M. A( ?% q0 [( D
                        // g_flagSwitch = isNo;
: q- _+ a1 p) k# t! X/ M                // }                6 ^- @0 |8 N3 j) _2 [
                1 }! W% t  I6 m0 A$ ?0 M7 G
                //指示灯:& C) s2 d" I. D; t1 q: U/ Q
                ioLed_Red = ! ioLed_Red;                                                        // 三个灯同时快速闪亮
& d/ H1 Q# @3 t8 `4 P                ioLed_Green = ! ioLed_Green;) ~; U( W) S' R3 J. l2 H  T& T5 \, @
                ioLed_Yellow = ! ioLed_Yellow;
3 g+ i& [' V0 Z) J                * Z: T# f$ {, i" E( R8 @* y. V
                // 蜂鸣器叫:        + D7 y1 E. W) y: P( Z7 {* I& Y
                if(buzzerCallFlag == isCall)
7 `- D! s. X9 F: ?5 o                {3 r$ u, q  R! C8 b' D
                        buzzerCall();                                        // 蜂鸣器叫        
; E/ A3 q. V; C& E8 e2 c; t                }
9 u8 S( _  ~) \" d                , ?' H7 m" Y& O# A6 d' ^% w8 z
                return isNo;                                                                        // 返回错误信息0 d4 s0 V3 N0 e
        }
2 N0 J6 l* T! l        else
. b2 K; d& Y& P9 b9 H2 Q        {0 K! e7 H( ~# p/ M2 T- |
                ulDis = uiD - ulDis;                                        // 当前水位C = 总距离 - 当前检测到的距离
8 k9 H' f# r; r: s8 q               
3 s5 E& p2 X% j; m! w/ t- ?                if(ulDis > uiH)                                                // 如果水位超高
0 z  I5 g0 ~# Y7 B) g) a. ^5 ~                {
7 H$ G$ s+ y  j2 O, b                        . v( k- E6 e5 i6 X+ C
                        //阀门动作:4 p5 x. ?3 @* p* J+ E
                        io_Control_Inlet = isio_Control_Inlet_OFF;  L6 ~3 g$ B3 K* Y* ?  O
                        io_Control_Outlet = isio_Control_Outlet_ON;        
) ^) t& w% I# W) c  h6 d                        g_flagSwitch = isNo;% l) |/ {. M' P
                        , r# F* w6 |# X& N! _! c/ b
                        //指示灯:
0 t+ R3 B4 X2 x7 q6 b                        ioLed_Red = ! ioLed_Red;                        // 红灯闪" e; M1 ?: Z# [; n4 B, z7 e  G
                        ioLed_Green = isLedOFF;                  H# U: ~" y2 N! e, E  g
                        ioLed_Yellow = isLedOFF;                                6 k- A' h  w. Y3 L6 C
                        // 蜂鸣器叫:
: R& M" B6 L7 w9 b) n                        if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) //当“当前水位”超出最高水位“ ((“总高度减高水位)除以2的值”)时报警
+ s5 [) g7 ~8 r! h) L: Q2 P# X                        {
! n/ n( Y& _' }9 [, I- l7 M                                buzzerCall();                                        // 蜂鸣器叫
  p- p# x6 b7 Y8 g+ ~( m                        }
0 M  S0 m3 T+ n4 y$ U' s) O                        
- W6 y+ [' Y9 _$ h3 L                }
" U/ y+ m$ o/ `8 v  n0 J- i                else if(ulDis < uiL)                                        // 如果水位超低4 N. R- `* ~) ^0 `
                {2 W; Z9 e# H% H7 e3 [
                        //阀门动作:        / L( O( ^& l- D; k6 {
                        if(g_flagSwitch == isYes)- z1 W' m$ N0 M0 c) z! U+ O
                        {               
9 d4 G; @" S6 S( s5 U* z$ o, I0 v                                io_Control_Outlet = isio_Control_Outlet_OFF;        
# s, Z, n/ [! P5 F                                io_Control_Inlet = isio_Control_Inlet_ON;        
; k+ `0 q% D  {$ L  ?6 S* L, A% G+ l                                g_flagSwitch = isNo;
, S* L! o& Q& W* n8 o8 `                        }        
8 W2 k5 `8 j" ?. I# J- g, Z/ n                        
" y" p# W: S! A! r                        //指示灯:
/ F* X/ @$ B1 P9 i! U3 c$ i                        ioLed_Red = isLedOFF;
; ]) s# e" ]6 F+ K5 t                        ioLed_Green = isLedOFF;
1 W% D9 @0 N& e7 u. f/ |5 C  k( y                        ioLed_Yellow = ! ioLed_Yellow;        //黄灯闪
! F+ h0 w2 E/ ^1 Z9 N2 \                        // 蜂鸣器叫:                                                
& e; |- P* m6 P: R8 V& y                        if( uiL - ulDis > uiL / DATA_alarmCoefficient)//uiL / 2 当“当前水位”低于“低水位” “低水位除以2的值”时报警0 _) J3 e7 T2 E2 f9 M# w
                        {
* ^; n" L/ j6 p/ I) A                                buzzerCall();                                        // 蜂鸣器叫
) S5 Q( ~3 Y+ A3 L" f4 @                        }* O" ~, b- Q8 M) i# \: K/ ?
                        ) V0 O6 [0 H) {  z: B# e
                        " J) }1 w& A' K/ @7 \/ {0 f9 v
                }
4 f, f3 Z5 M+ y% S( h                else                                                                // 水位在正常范围
" D$ ~+ A, ]4 u! C* U                {        - c9 |6 p% [" T
                        ioLed_Red = isLedOFF;
% g0 l8 e# K- Y                        ioLed_Green = ! ioLed_Green;
9 |& x. T2 N( {7 s2 ?. l3 H. R                        ioLed_Yellow = isLedOFF;        
2 @# y; T7 a0 t0 w5 P                        ( O2 T7 Z9 u2 C) a$ f! {7 b! w
                }
) S+ Y8 o1 o0 R% j9 \                putThreeCharToLCD1602(lineTow, i, ulDis);: p, F+ R* D/ f6 j: `) A7 d& z+ E
                return isYes;        
4 M+ m" q7 O; H# u               
; r5 b2 l& i$ A) R6 L. V) E        }1 `5 j- u8 a: }3 L, L
        return isYes;1 u, _# V! N8 s# D! z1 m
}
$ t: a; N& V9 B0 `( Y8 `2 X8 d* J" x; ^$ J, O4 i& v
/*********************************************************/
4 e! Y( B5 `1 H; \. K( Vvoid main(void)
! {. [" ?, Z* r% L- [{
5 f* j' _* C2 c; m- x+ f" g        initIO();                        //初始化IO端口        
: U" O, U8 l* w' C7 P7 S7 z        delay500ms();                 //启动延时,给器件进入正常工作状态留够时间        2 r+ l. _; ]! Q4 M% S8 T* A% l
        initLCD1602();         //LCD初始化        
9 x3 a+ }3 c* C7 |        putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        //显示distance (总)距离(检测探头到水库底部的距离)D
7 H& b8 M5 s. Z4 M        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);                //显示三位数值
2 ~. p- a( ?' X$ W7 `        putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");        //显示设定的最高报警水位H
+ u7 {0 ]& _% }* n2 z        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                //显示三位数值( C. y- e2 I( N; O0 D1 |9 r# h- c9 y
        putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");        //显示设定的最低报警水位L- G% G  g" o) e6 ]" R
        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);                //显示三位数值/ M6 r/ C/ B. U. z1 C2 B
        putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        //显示当前CURRENT水位C$ k+ p9 M+ _' t8 q* d
        6 i' ~8 y5 N5 b. v9 {9 g
        initTimer0();                //初始化定时器0
; s$ Q8 q" I0 p! _0 i5 F' b! X+ x1 M        initTimer1();
6 Y( R8 e% \- [  q        $ T- V; D  y* l5 e: W
        //阀门动作:初始先排水
) e' l" R$ g; ]. _+ j9 F        io_Control_Inlet = isio_Control_Inlet_OFF;        * I( f- Y" U# s: G+ s1 W7 n! b
        io_Control_Outlet = isio_Control_Outlet_ON;# d+ z; x5 K* N+ `
        g_flagSwitch = isNo;        
( n# |; ?1 V  x' R  S& G        / t+ r% {# O8 j) Z2 a
        while(1): ?' V, d$ C+ h' R) D
        {, G8 d4 t. P# O6 b) X: _+ V3 X
                io_US_TX = 1;                                //启动超声波模块信号6 G% o" e2 }* k( r2 g
                delay10us();
  K) e! A+ t3 @                io_US_TX = 0;
7 H1 h( C; Z: Z5 V& R                - [) t6 R( ?! @; v& v/ d- ~8 E6 c( C
                while(io_US_RX == 0);                        //等待计时开始; X! h2 o6 l. I5 ]( h* e7 G, {: k
                TR0 = 1;                                                    //开启定时器0,计时开始        ' t0 u* s* G4 M2 K
                IT1 = 1;                                                 //设置外中断INT1输入信号模式(1:Falling only仅下降沿有效 0:Low level低电平有效)' U8 U  E' ~5 g' a2 ~+ L
                EX1 = 1;                        //使能外中断INT1                  \- g5 \+ d5 D. ]
               
* u1 R1 b6 t0 J+ h                while(EX1 == 1 && g_flag == isNo)//等待中断或超时退出        
: f- q0 D4 T* m/ f  _                {8 A( \! }3 N4 X+ q
                        uchar ucKeyValue = GetKey();                                        //在等待中检测按键
/ Q1 s5 k9 G6 ]3 m                        if(ucKeyValue) execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        9 [) r8 @, _" F3 b5 k- g
                }: y/ i2 {8 p: h1 f; O% f* ~  z
               
# {$ }0 T% w4 }6 D1 i                if(CalculatedWaterLevel() == isNo) continue;                //计算水位,如果超出范围返回isNo并重新循环               
5 w; s" y2 ~1 b( m) m               
( \* Q* z5 U4 U1 ?2 n                TR0 = 0;                //暂时关闭定时器0
" I$ g: y$ Y8 V                //清零定时器和计数变量以及标志% x7 ?" ^( Y0 P
                TL0 = 0;               
! h; j3 x/ K4 G4 T$ O  E# U. z- X5 N' Y                TH0 = 0;               
% Q9 _( @+ U+ h/ E) k% a: w                g_flag = isNo;( C5 f% I# f8 e
                ucCount = 0;' U# ^3 f$ f$ E/ ~
                g_flag05s = isNo;
$ w4 ?; d: r3 u! f( M                ) k' I- M; b1 p# b0 D* U! m
                TR0 = 1;                //打开定时器0                                       
: Y  ~- @7 R4 i' w$ ^; d                while(g_flag05s == isNo)                //延时0.52秒,以防止此期间返回的超声波产生错误信息,并使显示变化放慢,保证视觉效果0 q! h- H% S9 p; U' ]
                {                        
* q8 J& C) z. |5 o                        uchar ucKeyValue = GetKey();
! G6 k$ _9 i6 F6 p% b/ r                        if(ucKeyValue)   Q! h( y2 f# Q0 K1 y2 w% |  v  i
                        {& R# W. l. j" q9 G% |7 D
                                if(ucKeyValue == DATA_KEY_DEC)
% G; [) S* v: s. q8 q- T                                {  S7 h0 N' w% U8 o" L5 p
                                        g_flagBeepTimer = isNo;//用减小按键取消报警标志
: G8 u" d, }6 C! e                                }
: j- t6 p: j% d/ u1 q- O" e8 h' w7 F% K
                                execute_key_task(ucKeyValue);        //如果有键按下则执行按键任务        
. Y* N; s! X0 X: a                        }                                & h9 \( c# c7 L. m
; p% y2 N* Z, X
                }        7 j# e4 n8 E* q& i
                TR0 = 0;                //暂时关闭定时器0
! [* ]: Q! ]- U- D6 c+ C, t# K                //清零定时器和复位标志
' A* j) k0 R& Q* |' X4 {                TL0 = 0;          Y' p  L" U2 [3 y/ ^/ V7 r! O
                TH0 = 0;        # {+ e# w, V+ I# W5 S4 H4 U7 p
                g_flag = isNo;                0 e4 j% n( E4 y0 m( S1 ^8 h. M* t0 c2 j
               
1 x: e9 U4 D' q9 O7 A# F                //-----------------------------------
* Y3 x3 L. {" j! g" W                //水箱清洗提示:
  C! d# J9 @+ D/ T                0 I6 J, X+ d) k" X6 o9 o2 q
                if(g_flagBeepTimer == isYes)
  J: m, G/ ^! T; }" m! t                {
( m( W2 o) \8 U) }( V                        buzzerCall();               
% ~/ D8 s" r4 q; [0 b1 Q                        //用减小按键取消报警标志
# ]1 |4 n5 R! E) x) a( z* X& ~6 p; l                        6 t: \( H0 A4 K7 y3 r; N
                }
1 I& z, t! S0 @1 x% w1 x                //-----------------------------------0 V3 c* i2 k. ]+ ~% H: h% b
               
5 x+ O5 B) v/ w  P3 n8 [7 F( z        }( D2 B  R7 L% s; C  t' o' C
}
3 _( ?8 O9 G+ H9 Q7 e5 e
6 I' i: {$ ?$ i% d5 _/ w$ Q, A4 @1 d3 x. @  q. O
#ifndef __MAIN_H__: n/ w  ~% q, ~
#define __MAIN_H__
4 l$ u+ ?% |3 O5 C' D& ?- `9 g
6 p& d0 Z# C1 t6 y//-----------------------------------------------" f0 R% O3 ]& F+ H# W
typedef unsigned char         uchar;        //为了方便书写定义别名
0 J/ W. l0 L) `: R( Jtypedef unsigned int         uint;' M% B2 M# \; Q7 i. I) F. D1 @
typedef unsigned long         ulong;
/ w- V  E7 l6 Z) [' Qtypedef        bit                                bool;7 N+ a5 n. U7 m$ d0 H6 y

/ H8 P( W  K; g, C* y8 q/ |' b- f" Hsbit         io_Control_Inlet = P1 ^ 7;        //定义进水继电器(水泵)控制端口
0 F  S) a( E2 x6 U# Y#define        isio_Control_Inlet_ON         0
5 T; Z" Z, J% \4 v#define        isio_Control_Inlet_OFF         1
( u. T( P% `. ~, R3 N" V1 P
$ B) S. t: k7 usbit         io_Control_Outlet = P0 ^ 0;        //定义出水继电器(水泵)控制端口
% I3 \  Q( n/ ^; ~$ d# }#define        isio_Control_Outlet_ON         0
' m% }# L% o: X% Y: _9 @+ G/ D: Y8 b#define        isio_Control_Outlet_OFF         1
. L1 K1 g! Q: B+ G  t) s7 S6 }  W/ I5 l: Q- i
#define         isYes                1
0 i! f, w# D% }8 O#define        isNo                01 X" o2 z- ^6 a" J+ d$ V
//----------------------------------------------------% L2 T' g9 x& X
//定义超声波模块引脚
4 a; E4 h! z7 I8 `0 [( m  msbit         io_US_RX          =        P3 ^ 3;        
5 H: q4 M9 I5 F. dsbit         io_US_TX          =        P3 ^ 2;
% W8 V6 }* z0 |6 ~: B//----------------------------------------------------
0 d: d( j; H6 j. z) v/ [5 s//定义LCD引脚
& X5 ^( v* W! h2 Y4 t. rsbit         io_LCD_RW          =        P3 ^ 6;
( f  }+ U' C4 {" K# r! k3 m% _sbit         io_LCD_RS          =        P3 ^ 7;
" Q/ U, n8 [6 vsbit         io_LCD_E           =        P3 ^ 5;             , w$ f/ U. E3 C  `( w0 t1 N
#define          IO_LCD_Data                  P2
  E3 g$ i" Z8 w- M#define         lineOne                        0) l7 f5 D7 z3 k2 e) }5 ?
#define         lineTow                        1
5 u! N! h( ^' _0 A  z5 ?' _6 p/ s' N8 l& A( L% p) Z
#define        isReadBusy        1  s7 V" e; I$ _1 o! d: Q; C
#define        isNotReadBusy        0
4 j& h' d- r, e6 c
' Q& `6 m' p! ~$ D4 H1 r; ~; p* c#define        DATA_LineMax                0x01                //LCD最大的行索引数3 t( G2 A6 `( j8 D) w, F
#define        DATA_PositionMax        0x0F                //(16 - 1) 字符在LCD一行中的最后一个索引位置
  x8 P  j+ D" e/ a/ c+ C3 g; v5 |#define        DATA_LineTow                0x01                //LCD第二行的索引值
: |7 ~) f4 R/ _. h//-------------------------------------------
8 e) H  t: g! Q4 T$ S& X7 L#define        Data_Key20msCountMax        160        //125us * 160 = 20ms 键去抖动延时# y; U3 N% M; o3 R
//-------------------------------------------------9 L# u9 A! @: x' W
// 定义指示灯端口
7 R, Q4 M9 J, U! P3 l( asbit        ioLed_Red = P1 ^ 3;; ?, }2 K2 b) H$ P- Z
sbit        ioLed_Green = P1 ^ 2;6 ]- a8 w" f2 D3 q
sbit        ioLed_Yellow = P1 ^ 1;2 G% L( ?7 Q$ @; P; {3 Q
* Z8 K" I3 o! p$ P; Y
#define        isLedOFF                1                        // 关闭LED
/ w3 z4 O6 r! I5 L/ h#define        isLedON                0                        // 点亮LED$ g* ~# p- [/ ]. N  F8 E
//---------------------------------------------
# w; N  Q) B3 S+ D* Q4 V" N; P//定义按键端口
9 g' @" C  ~6 ?$ a6 m+ R' x#define        IO_KEY                                P1        
! r7 O2 e7 K; Z( J6 M! J, @7 D( o. H5 v3 L% j& h8 ], g
#define        DATA_KEY_ORL                        0x8f        //10001111        //过滤按键以外的端口的数据& y3 o7 L# ?  P8 S1 C
#define        DATA_KEY_Null                        0xff        //11111111        //无键按下的数据8 S! L) Z4 b' P: |6 X7 Q

. }$ i: O' T& w) t% T8 R! j9 m1 S$ o#define        DATA_KEY_Set                        0xef        //11101111        //设置时间按键按下的数据
/ K0 F8 c' q- k; m- u1 p) H- O#define        DATA_KEY_INC                        0xdf        //11011111        //增加键按下的数据8 C0 E1 I. b4 {& ^
#define        DATA_KEY_DEC                        0xbf        //10111111        //减少键按下的数据
2 [6 W% `. d7 j& b, f//---------------------------------------------
" q6 R- N8 Q5 d( r; K  H1 |: z//定义蜂鸣器端口! d1 q/ }: }, H' `
sbit        io_Buzzer        =        P1 ^ 0;        . Z! p: |1 D) i
//---------------------------------------------; G9 o1 C3 `" d; |$ B
//定义检测探头到水库底部的设定距离范围 程序.jpg : s# }$ M# g  C+ z5 C
#define        DATA_uiD_Min                255                // 定义检测探头到水库底部的最小设定距离 单位cm
6 H9 j4 W( G' [0 H#define        DATA_uiD_Max                  20        // 定义检测探头到水库底部的最大设定距离 单位cm1 P& e' d' ]: y: ?- T! ^' A4 n
' d* c! F6 }1 L, k2 W. C! Q
#define        DATA_alarmCoefficient        2                // 超限报警阀值的系数& @0 O* E6 O9 h; q0 @+ _' `
#define        DATA_switchTime        200                //50ms的200倍 = 10S,控制阀门连续开启间隔延时(保护)0 b) x2 z5 k+ N. c6 F3 A
#define        DATA_BeepTimer        100                // 清洗水箱提示:分钟的倍数9 ]% s+ W' v/ n5 N/ h0 ^" k
+ _5 H- f+ x% ?3 ?
sbit        buzzerCallFlag = P3 ^ 4;
( V2 Y9 }& S/ J#define        isCall        0- s( H3 c8 w; @! }' M
#endif! ~5 _. ^( [. k  i

# p- c: Z/ h5 u0 P0 D! ]9 @3 Z8 C# M" H4 a3 ~5 |2 w
; k0 p) {; Z; O5 o! [: F7 v. @

& d1 H) K& x$ @2 ?% a

基于单片机超声波液位控制器设计.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
( _- Q8 G2 q8 X- `- J/***************************************************************& d; g. ^" M* s4 Q- ?1 B2 B
        名称:基于51单片机的超声波水位 ...

. v# B/ C+ W% ?6 p' S& b又下载一次,打开跟你内容不一样?
% m) w- d% n: p- O/ T% \, {2 s
QQ截图20201211202119.png
 楼主| 发表于 2020-12-14 08:40 | 显示全部楼层
金秋鸿叶 发表于 2020-12-11 19:05
* I9 |2 B* _- `2 `. @: m1 K大佬,我想知道,你那个探头检测液位现实吗?是清水还是污水?

8 M. H; `( K9 o' P& c7 V1 j7 w是的、是物体都可以检测到!4 }4 X$ b( J( w( u$ S( x8 P
发表于 2020-12-18 14:55 | 显示全部楼层
程序Keil、Protel99下载不了怎么办呢

本版积分规则

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

GMT+8, 2024-5-5 09:04 , Processed in 0.070075 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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