找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10541|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机水位AD检测

[复制链接]
跳转到指定楼层
楼主
ID:342789 发表于 2018-6-1 13:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

水位AD检测
摘要        1
1、概述        2
2、系统主要器件选择介绍        3
2.1 方案论证        3
2.2系统介绍        5
2.3 STC89c52单片机        5
2.4 压力传感器        9
2.5 ADC0832        9
2.6 1602液晶        12
3、系统电路设计        15
3.1 最小系统电路设计        15
3.2 1602显示电路设计        15
3.3 电磁继电器电路设计如下:图11        15
3.4 压力传感器采集电路设计如下;图12        16
3.5 蜂鸣器电路设计如下;图13        16
4、 系统程序设计        17
4.1系统程序程图设计如下;图13        17
4.2压力传感器采集显示程序流程图设计        17
4.3按键程序流程图设计        18
5、结论        19
致    谢        19
附录1        20
附录2        22
附录3:源程序        23


摘要
该系统以STC89c52单片机为控制核心设计的水位检测装置,该系统主要有单片机最小系统、按键模块、1602液晶显示模块、压力传感器模块、电磁继电器驱动模块和ADC0832组成。STC89c52系列单片机内部自带资源丰富、运算速度较快,适用于强干扰和要求速度较高的场合。以电磁继电器开环控制和压力传感器闭环实现对该系统的控制,达到系统的稳定可靠























1、概述
液位检测在许多控制领域已较为普遍,各种类型的液位检测传感器较多,按原理分有浮子式、压力式、超声波式、吹气式等。各种方式都根据其需要设计完成,其结构、量程和精度适用于各自不同的场合,大多结构较为复杂,制造成本偏高;市面上也有现成的液位计,有投入式、浮球式、弹簧式等,多数成品价格偏高。以上液位计多数输出为模拟量电流或电压,有些为机械指针读数,不能用于远程监视;普遍适用于静止液面,在波动液面易引起读数的波动;也有用电容法测液位的系统,此法是一种简单易行的方案。本文利用压力传感器测液体压力的原理,结合单片机设计出一种智能液位监控器。
本设计是在学完有关单片机系统和传感器相关课程的基础上,为了能更好的掌握这些课程的内容,把理论应用于实际而提出来的。旨在发挥我们的设计,创新意识。通过本课程设计可以掌握和巩固传感器的基本设计方法,工业水位的测量方法,单片机的基本应用,显示电路的连接等知识。进一步加强对课堂理论知识的理解与综合应用能力,从而提高我们解决问题的能力和创造发明能力。
如今传感器的应用是非常的广泛,并且已经融入到我们的生活、工作、科研等领域中。在进行设计中首先对压力传感器输出的电压和对应的液体高度进行整理和多次测量得出一个比较与实际高度符合的函数。通过压力传感器测出液体压力,利用ADC0832芯片对压力传感器的输出电压进行采集并将模拟电压信号转换成数字电平信号0,1。
液位监控器的应用虽然非常广泛,但是现在高精度的液位监控器的价格非常贵,实现民用还有一定的难度。所以我们的设计应更加创新利用更小的成本设计生产出更好的传感器。

2、系统主要器件选择介绍
2.1 方案论证
(1)主控器件的比较与选择
方案一:采用ARM7作为主控器件,虽然速度很快,资源很多,但价格        比较高,资源浪费,缺乏市场竞争力。
方案二:采用SST89C52作为主控器件,虽然该款单片机较便宜,运行        速度较慢,但是运行速度相对而言足够系统臀形并有富余,也可以对单片机        操作,来完成系统的功能设置,且电机的控制可以增加简单的外围电路设计。        单片机就显现出来它的优势——控制简单、方便、快捷。这样一来,单片机        就可以充分发挥其资源、有较为强大的控制功能及可位寻址操作功能。
综上所述,为简化外围电路设计,提高市场竞争力,我们选择方案二。

(2)压力传感器的比较与选择
根据压力的大小可以呈线性的改变输出的电压,通过对电压的采集处理比较,输出相应的高度值。
方案一:采用桥式压力传感器
桥式压力传感器是通过应变片的应力变形,当有应力变形时,传感器会输出电压,随着中立重力的加大输出电压会出现线性变化。但是由于桥式压力传感器,应力变形很小,输出的电压变化幅度小、电压值小,所以通AD简单的外围电路组成的采集模块一起使用,是电路简化,操作方便,易于固定、控制,称量值精度高。
方案二:采用分立元件搭建一个压力传感模块
采用压敏电阻和外围电路搭建一个压力传感器,通过放大电路对敏电阻的电        压放大,有普通的AD采集。该方案容易受到外界干扰,有时甚至检测不到,        还要用到AD采样和电压比较器来处理,这样加大了电路设计的难度。这样        的灵敏度不够,误差大,功耗大,增加了开发成本。
比较以上两种方案,方案一占有很大的优势。这样不但能准确完成测量,        而且能避免电路的复杂性,因此拟选择方案一。

(3)AD器件的比较与选择
方案一:采用12位AD芯片
采用12位AD芯片,分辨率比较高,成本高,但系统用不到那么高的分辨率,资源浪费,缺乏市场竞争力。
方案二:采用8位AD芯片
采用8位AD芯片,分半路256,在0-5v电压模数转换时,变量变化1,才有19.53mv的变化,足够系统的需求。
综上所述,我们选择方案二。
(4)水泵驱动电路的比较与选择
方案一:采用主控器件89C51单片机的定时器1定时中断,改变IO口的高低电平产生模拟的pwm信号。由于定时器0的根据系统的需要定时产生实时时钟,用另一个定时器,避免产生干扰。通过简单地测试,微控制器不断地进出中断,占用CPU太多时间,液晶显示部分、数据处理部分工作效率不高。
方案二:通过驱动继电器驱动水泵
继电器可低压控制高压,或小电流控制大电流,单片机驱动继电器很简单,方便,继电器另外一端开关反映也很灵敏,使用寿命较长,电流过大的时候不影响、单片机工作。
综上所述,根据系统的需求,我们选择方案二。
(5)显示器件的比较与选择
显示模块现在的技术已经很成熟,是集成LED一些成型的模块。
方案一:采用1602液晶显示,1602液晶只能显示二行,每行16个字符,并且不利于显示汉字(1个汉字占用2个字节),根据系统的要求,能很好地满足系统的需要。
方案三:采用12864液晶显示,12864屏幕大,显示控制相对复杂,相对功耗大、成本高。
综上所述,我们选择方案一。

2.2系统介绍
根据设计内容要求,经仔细分析计算,充分考虑各种因素,制定整体制作方案。整体方案以AT89C51为控制核心,对各传感器采集数据进行综合分析,作出相应的处理,保证精确稳定、快速的完成设计任务。系统方框图如图1所示。

2.3 STC89c52单片机
STC89C52RC是宏晶科技推出的新一代超强抗干扰、高速、 低功耗的单片机,基于 Intel 标准的 8052,指令代码完全兼容传统的 8051 系列单片机,12 时钟/机器周期和 6 时钟/机器周期可任意选择。
主要特性
� 增强型 6 时钟/机器周期,12 时钟/机器周期 8051CPU。
� 工作电压:5.5V - 3.4V(5V 单片机) / 3.8V - 2.0V(3V 单片机) 。
� 工作频率范围:0 – 40 MHz,相当于普通的 8051 的 0 ~80 Mhz,实际工作频率可达到 48MHz。
� 用户应用程序空间 4K、8K、13K、16K、20K、32K、64K 字节。
� 片上集成 1280 字节、512 字节 RAM。
� 通用 I/O(32/36 个) ,复位后为:P1、P2、P3、P4(PDIP-40 封装是没有引出 P4 口的)是准双向口、弱上拉(普通 8051 传统 I/O 口) ,P0 口是开漏输出,作为总线拓展用时,不用加上拉电阻,作为 I/O 口用时,需要加上拉电阻
� 共 3 个 16 位定时器、计数器,其中定时器 0 还可以当成 2 个 8 位定时器使用
� 外部中断 4 路,下降沿中断或低电平触发中断,Power Down 模式可由外部中断低电平触发中断方式唤醒

� P0
P0 口是一个 8 位漏极开路的双向 I/O 口。 作
为输出口,每位能驱动 8 个 TTL 逻辑电平。对 P0
端口写“1”时,引脚用作高阻抗输入。
当访问外部程序和数据存储器时,P0 口也被
作为低 8 位地址/数据复用。 在这种模式下, P0 具
有内部上拉电阻。
� P1
P1 口是一个具有内部上拉电阻的 8 位双向
I/O 口, P1 输出缓冲器能驱动 4 个 TTL 逻辑电
平。 对 P1 端口写“1”时, 内部上拉电阻把端口拉高,
此时可以作为输入 口使用。作为输入使用时,被
外部拉低的引脚由于内部电阻的原因,将输出电流(IIL) 。
此外,P1.0 和 P1.2 分别作定时器/计数器 2 的外部计数输入(P1.0/T2)和时器/计数器 2 的触发输入
(P1.1/T2EX) 。
引脚号第二功能:
P1.0 T2(定时器/计数器 T2 的外部计数输入) ,时钟输出。
P1.1 T2EX(定时器/计数器 T2 的捕捉/重载触发信号和方向控制) 。
� P2
P2 口是一个具有内部上拉电阻的 8 位双向 I/O 口, P2 输出缓冲器能驱动 4 个 TTL 逻辑电平。 对
P2 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低
的引脚由于内部电阻的原因,将输出电流(IIL) 。在访问外部程序存储器或用 16 位地址读取外部数据存
储器(例如执行 MOVX @DPTR)时,P2 口送出高八位地址。在这种应用中,P2 口使用很强的内部上拉发
送 1。在使用 8 位地址(如 MOVX @RI)访问外部数据存储器时,P2 口输出 P2 锁存器的内容。在 flash
编程和校验时,P2 口也接收高 8 位地址字节和一些控制信号。
� P3
P3 口是一个具有内部上拉电阻的 8 位双向 I/O 口, p2 输出缓冲器能驱动 4 个 TTL 逻辑电平。 对
P3 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低
的引脚由于内部电阻的原因,将输出电流(IIL) 。
端口引脚第二功能如表 2-4-1。
表 2-4-1
引脚 第二功能
P3.0        RXD(串行输入口)
P3.1        TXD(串行输出口)
P3.2        INT0(外中断 0)
P3.3        INT1(外中断 1)
P3.4        T0(定时/计数器 0)
P3.5        T1(定时/计数器 1)
P3.6        WR(外部数据存储器写选通)
P3.7        RD(外部数据存储器读选通)

� 其他引脚
RST——复位输入。当振荡器工作时,RST 引脚出现两个机器周期以上高电平将使单片机复位。
ALE/PROG——当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低 8 位字节。一般情况下, ALE 仍以时钟振荡频率的 1/6 输出固定的脉冲信号, 因此它可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个 ALE 脉冲。对 FLASH 存储器编程期间,该引脚还用于输入编程脉冲(PROG) 。如有必要,可通过对特殊功能寄存器(SFR)区中的 8EH 单元的 D0 位置位,可禁止 ALE 操作。该位置位后,只有一条 MOVX 和 MOVC 指令才能将 ALE 激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置 ALE 禁止位无效。
PSEN——程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当 AT89C52 由外部程序存储器取指令(或数据)时,每个机器周期两次 PSEN 有效,即输出两个脉冲,在此期间,当访问外部数据存储器,将跳过两次 PSEN 信号。EA/VPP——外部访问允许,欲使 CPU 仅访问外部程序存储器(地址为 0000H-FFFFH) ,EA端必须保持低电平(接地) 。需注意的是:如果加密位 LB1 被编程,复位时内部会锁存EA端状态。如EA端为高电平(接 Vcc 端) ,CPU 则执行内部程序存储器的指令。
2.4 压力传感器
压力传感器是通过应变片的应力变形,当有应力变形时,传感器会输出电压,随着中立重力的加大输出电压会出现线性变化。但是由于桥式称重压力传感器,应力变形很小,输出的电压变化幅度小、电压值小,所以通过8位AD芯片ADC0832和简单的外围电路组成的采集模块一起使用,是电路简化,操作方便,易于固定、控制,称量值精度高。我们选用D3B压力传感器。
D3B压力传感器工作电压:4.2v—6.2v;压力范围:0-----1000mm水柱,0----0.1Kg/c㎡;电压输出:0.23v---4.9v;线性度0.2%;外型:30×30×20mm


I接 5V    O接IO口   G接GND
2.5 ADC0832
ADC0832 为 8 位分辨率 A/D 转换芯片,其最高分辨可达 256 级,可以适应一般的模拟量转换要求。其内部电源输入与参考电压的复用,使得芯片的模拟电压输入在 0~5V 之间。芯片转换时间仅为 32μS,据有双数据输出可作为数据校验,以减少数据误差,转换速度快且稳定性能强。独立的芯片使能输入,使多器件挂接和处理器控制变的更加方便。通过 DI 数据输入端,可以轻易的实现通道功能的选择。 正常情况下 ADC0832 与单片机的接口应为 4 条数据线,分别是 CS、CLK、DO、DI。但由于 DO 端与 DI 端在通信时并未同时有效并与单片机的接口是双向的,所以电路设计时可以将 DO 和 DI 并联在一根数据线上使用。
当 ADC0832 未工作时其 CS 输入端应为高电平,此时芯片禁用,CLK 和 DO/DI 的电平可任意。当要进行 A/D 转换时,须先将 CS 使能端置于低电平并且保持低电平直到转换完全结束。此时芯片开始转换工作,同时由处理器向芯片时钟输入端 CLK 输入时钟脉冲,DO/DI 端则使用 DI 端输入通道功能选择的数据信号。在第 1 个时钟脉冲的下沉之前 DI 端必须是高电平,表示启始信号。在第 2、3个脉冲下沉之前 DI 端应输入 2 位数据用于选择通道功能,其功能项见表一。与单片机接口电路图如下:图2

图2

如表 1 所示,当此 2 位数据为“1”、“0”时,只对 CH0 进行单通道转换。当 2 位数据为“1”、“1”时,只对 CH1 进行单通道转换。当 2 位数据为“0”、“0”时,将 CH0 作为正输入端 IN+,CH1作为负输入端 IN-进行输入。当 2 位数据为“0”、“1”时,将 CH0 作为负输入端 IN-,CH1 作为正输入端 IN+进行输入。
到第 3 个脉冲的下沉之后 DI 端的输入电平就失去输入作用,此后 DO/DI 端则开始利用数据输出 DO 进行转换数据的读取。从第 4 个脉冲下沉开始由 DO 端输出转换数据最高位 DATA7,随后每一个脉冲下沉 DO 端输出下一位数据。直到第 11 个脉冲时发出最低位数据 DATA0,一个字节的数据输出完成。也正是从此位开始输出下一个相反字节的数据,即从第 11 个字节的下沉输出 DATD0。随后出 8 位数据,到第 19 个脉冲时数据输出完成,也标志着一次 A/D 转换的结束。最后将 CS 置高电平禁用芯片,直接将转换后的数据进行处理就可以了。更详细的时序说明请见表 2。

2.6 1602液晶
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图3是1602的内部显示地址。

图3液晶内部显示地址
例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图10-58所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。

图4 字符代码与图形对应图
初始化过程如下:图5
延时15mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
以后每次写指令、读/写数据操作均需要检测忙信号
写指令38H:显示模式设置
写指令08H:显示关闭
写指令01H:显示清屏
写指令06H:显示光标移动设置
写指令0CH:显示开及光标设置
图5:初始化活成(复位过程)
基本操作时序如下:


图6;读写指令
读操作时许如下:图7

图7;读操作时序图
写操作时序如下:图8

图8;写操作时序图

3、系统电路设计
3.1 最小系统电路设计
最小系统由单片机,P0口上啦排阻,外部时钟振荡电路,复位电路组成。如下;图9

图9;单片机最小系统电路图
3.2 1602显示电路设计
根据1602的数据手册,1602与单片机的接法如下:图10

图10;单片机与1602连接原理图
3.3 电磁继电器电路设计如下:图11

图11;单片机驱动继电器原理图
3.4 压力传感器采集电路设计如下;图12

图12;压力传感器采集原理图
3.5 蜂鸣器电路设计如下;图13

图13;蜂鸣器驱动原理图


4、系统程序设计
4.1系统程序程图设计如下;图13

图13:主程序流程图
4.2压力传感器采集显示程序流程图设计

4.3按键程序流程图设计

5 .1系统功能及指标参数
5.1.1 系统功能
本次设计的智能液位传感器主要能实现以下功能:
1、压力传感器采用的测量液体的压强的方式来实现测量液面高度;
2、设计的单片机系统能控制ADC对压力传感器的输出电压信号进行采集并转换;
3、测量范围能基本达到设计的要求在0-1米的范围内误差较小;
4、能在上位机上直观的显示出测量的液面高度;
5.2.1  AD部分调试参数
















在调通AD后我们对AD的数据采集功能进行了测试,测试数据如下图5.1:
序号        高度(CM)        AD值
1        0        2
2        2        7
3        3        9
4        4        11
5        5        14
6        6        16
7        7        19
8        8        21
9        9        24
10        10        26
11        11        28
12        12        31
13        13        33
14        14        36
15        15        38
16        16        40
17        17        43
18        18        45
19        19        48
20        20        51
21        30        74
22        40        98
23        50        122
24        60        146
25        70        170
26        80        194
27        90        218
28        100        242


                       图 5.1 AD的采集数据与给定的输入数据






这几组数据都是在室内测得的,都是在室温接近30度的情况测得。我们对所测得的数据进行了处理,一共测了28组数据(给定的高度读取ADC0832输出的AD值),说明AD的线性度还是比较高的。

总结出来公式:水位高度=(AD值-2)/2.4
5.2.3 调试总结
通过调试我们发现调试时最费时间的是考虑很多因素,调试过程要将整个系统组合起来看工作是否正常,能否达到基本的要求。
我们设计的只能液位传感器能基本满足设计的基本要求,通过压力传感器测量液位的压强方式,ADC0832对压力传感器的输出的模拟电压进行采集和转换送入单片机然后通过液晶屏幕显示液面的高度。量范围在0-1米内时误差能基本满足要求。误差主要就是来至压力传感器的输出与ADC0832的输入有一定的差距。

6、结论
本次设计的智能液位传感器达到了预期的基本要求,主要特色之一就是直接利用压力传感器测液体的压力的方式实现了测液面的高度,这种方式实现起来比较容易;其二就是将测量系统与PC机相结合起来这样对数据的读数比较直观,并且能精确到厘米。不过此设计也有很多不足之处,测量时要在容器的底部开口才能读出压力,还可以加入报警系统,当测量超出范围时,系统自动报警。还有就是还可以加上一定的数据存储能力,这样要对以前的数据进行研究的地方非常有帮助。






致    谢



通过这一阶段的努力,我的毕业设计终于完成了,这意味着我的大学生活即将结束。在大学阶段,我在学习上和思想上都受益匪浅,这除了自身的努力外,与各位老师、同学和朋友的关心、支持和鼓励是分不开的。
在本论文的完成过程中,我的指导老师倾注了大量的心血,从选题到开题报告,从写作提纲到一遍又一遍地指出每稿中的具体问题,严格把关,循循善诱,在此我衷心感谢。同时我还要感谢在我学习期间给我极大关心和支持的各位老师以及关心我的同学和朋友。
写作毕业论文是一次在系统学习的过程,毕业论文的完成,同样也意味着新的学习生活的开始,我将铭记我曾是一名工大学子,在今后的工作中把工大的优良传统发扬光大。
感谢各位专家的批评指导。














附录1
参考文献
[1] 赵国强,智能台灯,科学启蒙,2007, 第Z1期
[2]赵继文,传感器与应用电路设计,北京,北京科学出版社,2002.3,6
[3]黄继昌,电子元器件应用手册,北京,北京人民邮电出版社, 2004年,5
[4]赵辉,Protel99电子线路CAD,北京,北京邮电大学出版社,2007
[5]毕淑娥,电工与电子技术基础,哈尔滨,哈尔滨工业大学出版社,2008.6
[6]李全利,单片机原理及应用,北京,清华大学出版社,2006.2
[7]黄长艺,机械工程测试技术基础,北京:机械工业出版社,2009.3,68-124
[8]金发庆,传感器技术与应用,北京 : 机械工业出版社, 2004.8,281-290
[9]王港元,电子技能基础,成都,成都科技大学出版社,1999
[10]热释电红外传感器,http://baike.baidu.com/view/1788636.htm
[11]光敏电阻,http://baike.baidu.com/view/55997.htm
[12]夏路易,单片机在控制系统中的应用,北京,北京希望电子出版社,2006
[13]李朝青,单片机原理及接口技术,北京,北京航空航天大学出版社,2004
    [15] AT89C51 DATA SHEEP Philips Semiconductors 1999.dec
[16]Yang. Y., Yi. J., Woo, Y.Y., and Kim. B.: ‘Optimum design for linearityand                               efficiency of microwave Doherty amplifier using a new loadmatching technique’, Microw. J., 2001, 44, (12), pp. 20–36








附录2
系统原理图





















附录3:源程序

#include<reg52.h>                                 //头文件
#include<intrins.h>
#include"eeprom52.h"                         //STC89C52 EEPROM   程序文件
#define uchar unsigned char                 //宏定义
#define uint unsigned int

#define LCD1602_dat P0            //LCD1602数据口宏定义

sbit LCD1602_rs=P2^5;                //LCD1602控制数据IO口
sbit LCD1602_rw=P2^6;
sbit LCD1602_e=P2^7;
sbit beep=P1^4;                //蜂鸣器  IO
sbit led_1=P1^6;                //LED指示灯  IO
sbit led_2=P1^7;
sbit key_1=P3^0;                //系统控制按键IO口
sbit key_2=P3^1;
sbit key_3=P3^2;
sbit alarm_1=P2^0;                //控制继电器IO口


sbit ADC0832_CS=P1^2;        //ADC0832  控制IO口          使能口
sbit ADC0832_CLK=P1^1;        //时钟IO口
sbit ADC0832_DIO=P1^0;        //数据输入输出IO口

uint sum;                          //10次AD值的综合变量
uchar RH,RH_H=12,RH_L=8,state,ms,cs;  //当前水位,  水位上限,下限,  设置项变量,50ms变量   ,cs 为计次数变量    ,
bit beep1,zt,s1;          //报警标志位,   工作模式标志位,   闪烁标志位


unsigned int  A_D()            //ADC0832   读值程序
{
        unsigned char i;
        unsigned char dat;                                         
        ADC0832_CS=1;   //一个转换周期开始
        ADC0832_CLK=0;  //为第一个脉冲作准备
        ADC0832_CS=0;  //CS置0,片选有效
        ADC0832_DIO=1;    //DIO置1,规定的起始信号  
        ADC0832_CLK=1;   //第一个脉冲
        ADC0832_CLK=0;   //第一个脉冲的下降沿,此前DIO必须是高电平
        ADC0832_DIO=1;   //DIO置1, 通道选择信号  
        ADC0832_CLK=1;   //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道RH0
        ADC0832_CLK=0;   //第二个脉冲下降沿
        ADC0832_DIO=0;   //DI置0,选择通道0
        ADC0832_CLK=1;    //第三个脉冲
        ADC0832_CLK=0;    //第三个脉冲下降沿
        ADC0832_DIO=1;    //第三个脉冲下沉之后,输入端DIO失去作用,应置1
        ADC0832_CLK=1;    //第四个脉冲
        for(i=0;i<8;i++)  //高位在前
        {
                ADC0832_CLK=1;         //第四个脉冲
                ADC0832_CLK=0;
                dat<<=1;       //将下面储存的低位数据向右移
                dat|=(unsigned char)ADC0832_DIO;          //将输出数据DIO通过或运算储存在dat最低位
        }                                  
        ADC0832_CS=1;          //片选无效
        return dat;         //将读书的数据返回     
}


/********************************************************************
* 名称 : delay()
* 功能 : 小延时。                                                                                                         
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay(uint T)                                          //延时函数
{
        while(T--);
}
/********************************************************************
* 名称 : LCD1602_write(uchar order,dat)
* 功能 : 1602写如数据函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void LCD1602_write(uchar order,dat)                                  //1602 一个字节  处理
{
    LCD1602_e=0;
    LCD1602_rs=order;
    LCD1602_dat=dat;
    LCD1602_rw=0;
    LCD1602_e=1;
    delay(1);
    LCD1602_e=0;                                                                                                                                                                                                     
}
/********************************************************************
* 名称 : LCD1602_writebye(uchar *prointer)
* 功能 : 1602写入数据函数  指针式
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void LCD1602_writebyte(uchar *prointer)                                   //1602 字符串    处理
{
    while(*prointer!='\0')
    {
        LCD1602_write(1,*prointer);
        prointer++;
    }
}
/********************************************************************
* 名称 : LCD1602_cls()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void LCD1602_cls()                                                                         //1602 初始化
{
        LCD1602_write(0,0x01);     //1602 清屏 指令
        delay(1500);
        LCD1602_write(0,0x38);     // 功能设置 8位、5*7点阵
        delay(1500);
        LCD1602_write(0,0x0c);     //设置 光标   不显示开关、不显示光标、字符不闪烁
        LCD1602_write(0,0x06);
        LCD1602_write(0,0xd0);
        delay(1500);
}
/********************************************************************
* 名称 : show()
* 功能 : LCD1602液晶显示程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void show()
{
        if(state==0)                //当前水位及工作模式显示
        {
                LCD1602_write(0,0x80);
                LCD1602_writebyte("Water level:");        //当前水位
                if(RH>9)LCD1602_write(1,0x30+RH/10%10);
                else LCD1602_writebyte(" ");
                LCD1602_write(1,0x30+RH%10);
                LCD1602_writebyte("cm");

                LCD1602_write(0,0xC0);
                LCD1602_writebyte("State:");          //工作模式
                if(zt==0)
                {
                        LCD1602_writebyte("Manul     ");
                }else
                {
                        LCD1602_writebyte(" Aoto     ");
                }
                       
        }else                  //水位上下限设置界面
        {
                LCD1602_write(0,0x80);
                LCD1602_writebyte("Water_H:");   //水位上限
                if(state==1&&s1==1)                   //通过闪烁标志为  达到闪烁的效果
                {
                        LCD1602_writebyte("  ");
                }else
                {
                        if(RH_H>9)LCD1602_write(1,0x30+RH_H/10%10);
                        else LCD1602_writebyte(" ");
                        LCD1602_write(1,0x30+RH_H%10);               
                }

                LCD1602_writebyte("cm    ");

                LCD1602_write(0,0xC0);
                LCD1602_writebyte("Water_L:");  //水位下限
                if(state==2&&s1==1)                 //通过闪烁标志为  达到闪烁的效果
                {
                        LCD1602_writebyte("  ");
                }else
                {
                        if(RH_L>9)LCD1602_write(1,0x30+RH_L/10%10);
                        else LCD1602_writebyte(" ");
                        LCD1602_write(1,0x30+RH_L%10);
                }
                LCD1602_writebyte("cm    ");       
        }
}
/********************************************************************
* 名称 : key()
* 功能 : 按键控制程序     实现系统各个控制功能
* 输入 : 无
* 输出 : 无
***********************************************************************/
void key()
{
        if(!key_1) //设置按键  设置  功能:切换显示及设置的选项
        {
                delay(888);   //按键去抖
                if(!key_1)        //再次判断按键
                {
                        while(!key_1) show();  //按键判断是否释放
                        state=(state+1)%3;          //执行按键功能   切换设置项
                }
        }

        if(!key_2)   //切换设置项值的大小    及非设置模式下切换系统工作模式按键
        {
                delay(888);   //按键去抖
                if(!key_2)   //再次判断按键
                {
                        while(!key_2)show();  //按键判断是否释放
                        if(state==1)                  //执行按键功能   切换设置项
                        {
                                if(RH_H<100)RH_H++;                   //设置上限值
                                SectorErase(0x2000);         //保存上限值         保存到单片机中EEPROM
                                byte_write(0x2000,RH_H);
                        }else if(state==2)
                        {
                                if(RH_L<RH_H-1)RH_L++;          //设置下限值
                                SectorErase(0x2200);         //保存下限值         保存到单片机中EEPROM
                                byte_write(0x2200,RH_L);
                        }else
                        {
                                zt=!zt;                                 //切换系统的工作模式   自动   手动
                        }       
                }
        }

        if(!key_3)    //切换设置项值的大小    及手动模式下切换系统工作状态‘开关’
        {
                delay(888);        //按键去抖
                if(!key_3)    //再次判断按键
                {               
                        while(!key_3)show();  //按键判断是否释放
                        if(state==1)                  //执行按键功能   切换设置项
                        {
                                if(RH_H>RH_L+1)RH_H--;
                                SectorErase(0x2000);         //保存上限值  保存到单片机中EEPROM
                                byte_write(0x2000,RH_H);
                        }else if(state==2)
                        {
                                if(RH_L>0)RH_L--;
                                SectorErase(0x2200);         //保存下限值        保存到单片机中EEPROM
                                byte_write(0x2200,RH_L);
                        }else
                        {
                                if(zt==0)
                                {
                                        alarm_1=!alarm_1;           //手动模式切换系统的工作状态
                                }
                        }
                }
        }               
}
/********************************************************************
* 名称 : proc()
* 功能 : 系统处理程序部分
* 输入 : 无
* 输出 : 无
***********************************************************************/
void proc()
{
        if(zt==1)          //zt==1  为自动模式    如果系统在自动模式下
        {
                if(RH>=RH_H)           //如果当前水位值达到水位上限值则
                {
                        alarm_1=1;   //关闭继电器   
                        led_1=0;                //显示对应的指示灯
                }else                  //否则
                {
                        led_1=1;           //显示对应的指示灯
                }

                if(RH<=RH_L)           //如果当前水位值低于水位下限值则
                {
                        alarm_1=0;   //开启继电器
                        led_2=0;           //显示对应的指示灯
                }else            //否则
                {
                        led_2=1;           //显示对应的指示灯
                }

                if(RH>=RH_H|RH<=RH_L)  //蜂鸣器处理部分   如果当前水位超出水位上下限  则
                {
                        beep1=1;                   //开始报警
                }else                 //否则
                {
                        beep1=0;           //停止报警
                }
        }else
        {
                beep1=0;                 //手动模式关闭指示灯及蜂鸣器
                led_1=led_2=1;
        }
}





void main()
{       
        float Ad_dat=0;
        alarm_1=1;        //继电器状态初始化
        TMOD=0x01;    //定时器配置初始化
        TH0=0x3c;            //16位定时   定时50ms
        TL0=0xb0;
        ET0=1;
        TR0=1;           //开启总中断    及打开定时器0
        EA=1;
        LCD1602_cls();           //LCD1602  初始化
        RH_H=byte_read(0x2000);           //读取EEPROM中的水位上下限的值
        RH_L=byte_read(0x2200);
        if((RH_H>99)||(RH_L>99)||(RH_L>=RH_H))   {RH_H=14;  RH_L=7;} //如果超出水位上下限设置的范围,则重新赋值
          
        while(1)
        {
                if(cs<10)                                 // 滤 //数字滤波器   是ADC0832读出的值变化幅度小
                {
                        cs++;
                        sum+=A_D();                // 波    //读取10次 AD值
                }
                else                                        // 算
                {
                        cs=0;                                // 法
                        Ad_dat=(uchar)(sum/10);         //求出当前水位值
                        //ad_dat1=255-ad_dat1;
                        if(Ad_dat>2)
                        {
                                Ad_dat=(float)((Ad_dat-2)/2.4);  //计算水位
                                RH=(uchar)(Ad_dat);       
                        }
                        else
                        RH=0;               
                        sum=0;
                }               
                show();          //调用子程序
                key();
                proc();
        }
}

void UART_1() interrupt 1  //定时器0 中断
{
        TH0=0x3c;                         //重新赋值
        TL0=0xb0;
        ms++;                    //50ms计数
        if(ms%5==0)                //250ms  计时
        {
            s1=!s1;            //改变闪烁标志为的值
        }
        if(ms%10==0)           //500ms定时
        {
                if(beep1==1) //蜂鸣器报警处理   
                {
                        beep=!beep;
                }else
                {
                        beep=1;
                }       
        }
        if(ms>19)
        {
                ms=0;
        }       
}










评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:704309 发表于 2020-4-5 19:48 | 只看该作者
有系统原理图吗?
回复

使用道具 举报

板凳
ID:715032 发表于 2020-5-13 15:38 | 只看该作者
能说明一下水位是怎么计算的吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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