第一范文网 - 专业文章范例文档资料分享平台

基于单片机的智能温室温湿度控制系统的设计

来源:用户分享 时间:2025/9/10 12:38:45 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

基于单片机的智能温室温湿度控制系统的设计

摘要:在农业生产中,温室大棚的应用越来越广泛,为人们创造了更高的经济效益。在温室大棚中,最关键的是温湿度控制方法。传统的温湿度控制方法完全是人工的,不仅费时费力,而且效率低。本文旨在论述一种温室大棚温湿度控制系统的设计,该系统主要由单片机AT89S52、温湿度传感器DHT11、无线通信模块nRF2401、液晶显示LCD1602等组成。采用温湿度传感器DHT11来测量温湿度,它的精确度高,而且DHT11直接是输出数字信号,可直接与单片机相连。通过无线传感器nRF2401来进行信号传送,这样能够降低布线的麻烦。显示部分使用的是LCD1602来显示温湿度。本系统的核心是单片机AT89S52,接收传感器所测的数据并处理,然后执行各种操作。本系统智能度高,可靠性高,系统工作稳定,且综合性价比较高,具有较大的市场应用前景。

关键词:单片机,温湿度控制系统,温湿度传感器DHT11,LCD显示,

无线模块nRF2401

Design of temperature and humidity intelligent greenhouse

control system based on SCM

Abstract :In agricultural production, more and more extensive application in the greenhouse, create more economic benefits for the people. In the greenhouse, the most critical is the temperature and humidity control method. Temperature and humidity control of traditional methods is entirely artificial, not only time-consuming effort, and low efficiency. The system consist of the microcontroller AT89S52 ,digital temperature and humidity sensor DHT11,wireless sensor NRF2401,LCD1602 and other components. To measure the temperature and humidity using temperature and humidity sensor DHT11, its precision is high, and the DHT11 is directly output digital signal, can be directly connected with the single-chip microcomputer. Through the NRF2401 to transmit signals, it can reduce the trouble of wiring. The display part is using LCD1602 to display the temperature and humidity. The core of this system is AT89S52, the measured sensor data received and processed, and then perform various operations. The system of high intelligence, high reliability, the system is stable, and the higher price, has great market prospect.

Keyword:SCM, Temperature and humidity control system, Temperature and humidity sensor DHT11, LCD display, Wireless module NRF2401

目录

1 引言............................................................. 0 1.1 课题背景....................................................... 0 1.2 立题的目的及意义............................................... 0 1.3 国内外的研究现状及发展趋势..................................... 1 1.4 本系统主要研究内容............................................. 1 2 系统总体设计..................................................... 3 2.1 系统功能设计................................................... 3 2.2 系统的组成..................................................... 3 2.3 系统工作原理................................................... 4 3 系统硬件设计..................................................... 5 3.1 单片机系统设计................................................. 5 3.2 温湿度传感器设计.............................................. 10 3.3 无线模块设计.................................................. 15 3.4 液晶显示装置设计.............................................. 19 3.5 报警系统设计.................................................. 22 4 系统软件设计.................................................... 22 4.1 系统初始化模块................................................ 23 4.2 数据采集模块.................................................. 23 4.3 无线模块...................................................... 24 4.4 显示模块...................................................... 26 4.5 报警模块...................................................... 27 5 硬件调试........................................................ 28 结论............................................................... 32

附录............................................................... 33 参考文献........................................................... 67 致谢............................................... 错误!未定义书签。

1 引言

1.1 课题背景

在现代的大棚种植技术中,温度、湿度是大棚蔬菜能否茁壮成长的重要因素。目前我国大棚生产规模虽然 空前巨大,但是大棚的设备比较陈旧,温度采集方式落后,农村采用煤油温度计的温度采集方式,不仅温度采集较为老套,并且费时费力,不利于大棚生产规模的扩大,也不利信息化程度的提高[1]。

农业是人类社会最古老的行业,是各行各业的基础,也是人类顿以生存的最重要的行业,由传统农业向现代化农业转变,由粗放经营向集约经营转变,必须要求农业科技有一个大的发展,进行一次新的农业技术革命[2]。科技的发展促进了农业的发展,温室大棚在农业中的应用越来越广泛。传统的温室大棚的自动化程度很低,基本是是粗放型的人工操作,即便对于所给定的量,在操作中无法进行有效的控制,很大程度上限制了温室大棚的经济效益。

以前种植植被一般都用温室栽培,为了充分的利用好温室栽培这一高效技术,就必需有一套科学的,先进的管理方法,用以对不同种类植被生长的各个时期所需的温度及湿度等进行实时的监控。温湿度控制对于单片机的应用具有一定的实际意义,它代表了一类自动控制的方法,而且其应用十分广泛。 1.2 立题的目的及意义

AT89S52单片机是常用于控制的芯片,在智能仪器仪表、工业检测控制、机电一体化等方面取得了令人瞩目的成果,用其作为温湿度控制系统的实例也很多。使用AT89S52单片机能够实现温湿度全程的自动控制,而且AT89S52单片机易于学习、掌握,性价比高。

使用AT89S52单片机设计温湿度控制系统,可以及时、精确的反映室内的温度以及湿度的变化。完成诸如升温到特定温度、降温到特定温度、在温度上下限范围内保持恒温等多种控制方式,在湿度控制方面也是如此[3]。将此系统应用到温室

当中无疑为植被的生长提供了更加适宜的环境。 1.3 国内外的研究现状及发展趋势

美国是将计算机应用于大棚和管理最早,最多的国家之一。美国开发的大棚计算机控制与管理系统可以根据作物的特点和生长所需要的条件,对大棚内的光照,温度,湿度等诸多因素进行自动控制。这种自动控制系统需要种植者输入温室作物生长所需的环境的目标参数,计算机根据传感器的实际测量值与事先设定的目标进行比较,以决定大棚温湿度的控制过程,按照相应的机构进行加热,降温或者是浇水,通风等[4]。目前,我国绝大部分自主开发的大棚温湿度控制或者进口的国外设备都属于这种系统。

虽然这种自动控制系统实现了自动化,适合规模化生产,提高了劳动生产率,通过改变大棚温湿度的设定目标,可以自动的对大棚内温湿度进行调节,但是这种调节对作物的生长来说还是相对滞后的,难以介入作物生长的内在规律。所以在这种自动控制系统和实践的基础上,温湿度自动控制向着适合不同作物生长的智能化控制发展。

国外大棚业正致力于高科技发展,遥测技术,网络技术,控制局域网已逐渐应用于大棚的管理和控制中,近几年各国温度控制技术提出建立大棚行业标准,朝着网络化,大众化,大规模,无人化的方向发展的思路[5]。

目前国内外的温湿度检测使用的温湿度检测元件种类繁多、应用范围也较广泛加之单片机和大规模集成电路技术的不断提高,出现了高性能、高可靠性的单片机数据采集系统[6]。基于单机片的温湿度监测控制系统的设计研究较少。随着经济和社会的不断发展,人们对自己的生活环境要求越来越高。特别在温室大棚中,对温湿度要求更为严格。基于单片机的温室温湿度控制统设计,将对环境的温湿度监测系统做详细的设计与实现。 1.4 本系统主要研究内容

本系统主要完成的任务:

1. 进行温湿度控制系统的整体研究与设计。

2. 利用数字温湿度传感器DHT11测量大棚内的温湿度。

3. 通过采集温度及湿度值,准确的判断标准值与当前值之间的差异,及时的启动报警装置(包括警报灯的提示功能以及提示音等)进行报警,并采取相应的方案。

4. 利用LCD对温湿度进行实时显示。

5. 利用NRF24L01无线模块实现数据的远距离传输

2 系统总体设计

2.1 系统功能设计

1. 温湿度监控:实现对温室大棚温湿度参数的实时采集,测量空间的温度和湿度,由单片机对采集的温湿度值进行循环检测、数据处理、显示,实现温湿度的智能检测。

2. 控制处理:当温湿度越限时报警,并根据报警信号提示采取一定手段控制。 3. 无线传输:用温湿度传感器将测量的温湿度数据通过无线模块进行传输。

温湿度传感器达到的技术指标:

测量范围: 湿度20-90%RH, 温度0-50℃ 测量精度: 湿度+5%RH, 温度+2℃ 2.2 系统的组成

以单片机为控制核心,采用温湿度测量技术,通信技术,控制技术等技术,以温湿度传感器作为测量元件,构成智能温湿度测量控制系统。可分为温湿度测量电路,显示电路,报警电路,无线模块,图2.1选用的主要器件有:单片机AT89S52,温湿度传感器DHT11,1602LCD显示模块,LED灯,报警装置蜂鸣器,NRF2401无线模块等。

DHT11数字温湿度传感器AT89S52单片机1602LCD液晶NRF2401无线模块报警系统判断 图2.1 系统组成

2.3 系统工作原理

本系统以单片机AT89S52为核心,数据采集、传输、显示、报警都要通过单片机。数据采集通过单总线的智能数字温湿度传感器DHT11完成;通过单片机把采集的数据显示在1602LCD上;当采集的数据超出给定范围时,有蜂鸣器实时报警,并将数据通过NRF2401无线传输给另一个单片机上显示。单片机采用C语言编程。

系统初始化温湿度检测无线数据通信符合判断不符合不报警89S52单片机报警89S52单片机LCD液晶显示终止LCD液晶显示 图2.2 流程框图

3 系统硬件设计

3.1 单片机系统设计

经过上面的总体方案和实施措施的讨论后可以开始着手硬件系统的设计,硬件系统是应用系统的基础、软件系统设计的依据,根据总体功能和性价比及其运行速度等因素的考虑,选用AT89S52单片机。

AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编

程Flash存储器。AT89S52使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,AT89S52拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案

[11]

AT89S52具有以下标准功能: 8k字节Flash,256字节RAM,32 位I/O 口线,

看门狗定时器,2 个数据指针,三个16 位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止[12]。其引脚排列如图3.1所示:

图3.1 AT89S52引脚图

(1)电源及时钟引脚(4个) VCC:电源接入引脚; GND:接地引脚;

XTAL1:晶体振荡器接入的一个引脚(采用外部振荡器时,此引脚接地); XTAL2:晶体振荡器接入的另一个引脚(采用外部振荡器时,此引脚作为外部振荡信号的输入端)。 (2)控制线引脚(4个)

RST/VPD:复位信号输入引脚/备用电源输入引脚;

ALE/PROG:地址锁存允许信号输出引脚/编程脉冲输入引脚(低电平有效);

EA/Vpp:内外存储器选择引脚(低电平有效)/片内EPROM(或FlashROM)编程电压输入引脚;

PSEN:外部存储器选通信号输出引脚(低电平有效)。 (3) 并行I/O引脚(32个,分成4个8位口)

P0.0~P0.7:一般I/O引脚或数据/低位地址总线服用引脚; P1.0~P1.7:一般I/O引脚;

P2.0~P2.7:一般I/O引脚或高位地址总线引脚; P3.0~P3.7:一般I/O引脚或第二功能引脚。

其内部主要由CPU、RAM、ROM、通用I/O及总线构成,内部结构如图3.2所示:

并行I/O口 串行通信口 中断系统 时钟 程序存储器 数据存储器 定时计数器 数据 总线 地址 总线 控制 8051 总线

图3.2 AT89S52内部结构图

CPU:由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器; RAM:用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据;

ROM:用以存放程序、一些原始数据和表格; 单片机的寄存器

MCS-51器件有单独的程序存储器和数据存储器。外部程序存储器和数据存储器都可以64K寻址。

程序存储器:如果EA引脚接地,程序读取只从外部存储器开始。

对于 89S52,如果EA 接VCC,程序读写先从内部存储器(地址为0000H~1FFFH)开始,接着从外部寻址,寻址地址为:2000H~FFFFH。

数据存储器:AT89S52 有256 字节片内数据存储器。高128 字节与特殊功能寄存器重叠。也就是说高128字节与特殊功能寄存器有相同的地址,而物理上是分开的。

当一条指令访问高于7FH 的地址时,寻址方式决定CPU 访问高128 字节RAM 还是特殊功能寄存器空间。直接寻址方式访问特殊功能寄存器(SFR)[12]。 机器周期和指令周期

(1) 振荡周期: 也称时钟周期, 是指为单片机提供时钟脉冲信号的振荡源的周期。

(2) 状态周期: 每个状态周期为时钟周期的 2 倍, 是振荡周期经二分频后得到的。

(3) 机器周期: 一个机器周期包含 6 个状态周期S1~S6, 也就是 12 个时钟周期。在一个机器周期内, CPU可以完成一个独立的操作。

(4) 指令周期: 它是指CPU完成一条操作所需的全部时间。 每条指令执行时间都是有一个或几个机器周期组成。 中断

AT89S52 有6个中断源:两个外部中断(INT0 和INT1),三个定时中断(定时器0、1、2)和一个串行中断。每个中断源都可以通过置位或清除特殊寄存器IE 中的相关中断允许控制位分别使得中断源有效或无效。IE还包括一个中断允许总控制位EA,它能一次禁止所有中断。

IE.6位是不可用的,对于AT89S52,IE.5位也是不能用的。用户软件不应给这些位写1。它们为AT89系列新产品预留。

定时器2可以被寄存器T2CON中的TF2和EXF2的或逻辑触发。程序进入中断服务后,这些标志位都可以由硬件清0。实际上,中断服务程序必须判定是否是TF2 或EXF2激活中断,标志位也必须由软件清0。

定时器0和定时器1标志位TF0 和TF1在计数溢出的那个周期的S5P2被置位。它们的值一直到下一个周期被电路捕捉下来。然而,定时器2 的标志位TF2 在计数溢出的那个周期的S2P2被置位,在同一个周期被电路捕捉下来。 复位电路

本系统采用上电+按键复位,是上电复位和按键电平复位的组合,无论是上电还是按动按键都能使单片机复位。如图3.3所示:

C3 10uf R2 1K RESET R3 10K

图3.3 复位电路

在单片机系统中,系统上电启动的时候复位一次,当按键按下的时候系统再次复位,如果释放后再按下,系统还会复位。所以可以通过按键的断开和闭合在运行的系统中控制其复位。

复位电路的原理是单片机RST引脚接收到2US以上的电平信号,只要保证电容的充放电时间大于2US,即可实现复位,所以电路中的电容值是可以改变的。按键按下系统复位,是电容处于一个短路电路中,释放了所有的电能,电阻两端的电压增加引起的[13]。 时钟电路

时钟引脚为XTAL1、XTAL2,时钟引脚外接晶体与片内的反向放大器构成了一个振荡器,它提供单片机的时钟控制信号,时钟引脚也可外接晶体振荡器。 XTAL1(19脚):接外部晶体的一个引脚。在单片机内部,它是一个反向放大器的输入端。这个放大器构成了片内振荡器。当采用外接晶体振荡器时,此引脚应接地。

XTAL2(18脚):接外部晶体的另一端,在单片机内部接至内部反向放大器的输出端。若采用外部振荡器时,该引脚接收振荡器的信号,即把此信号直接接到内部时钟发生器的输入端[14]。

本系统采用晶振时钟电路。外部晶振以及电容C1和C2构成并联谐振电路,接在放大器的反馈回路中。对外接电容的值虽然没有严格要求,但电容的大小多少会影响振荡器频率的高低,振荡器的稳定性,起振的快速性和稳定性。外接晶振时,C1和C2通常选择30pf,晶振采用12MHz。本设计时钟电路如下图3.4所示:

30p C2 19 C1 30p

12MHZ CRYSTAL XTAL1 XTAL2

18

图3.4 时钟电路

3.2 温湿度传感器设计

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接[15]。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中

进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测型号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为给类应用甚至最为苛刻的应用场合的最佳选择。产品为4针单排引脚封装,连接方便。 DHT11的简介

·相对湿度和温度测量 ·全部校准,数字输出 ·卓越的长期稳定性 ·无需外加器件 ·超长的信号传输距离 ·超低能耗 ·4引脚安装

·完全互换 图3.5 DHT11 引脚说明

建议接线长度短于20米时,用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。

引脚1:VDD供电3-5.5V 引脚2:DATA串行数据,单总线 引脚3:NC空脚,悬空 引脚4:GND接地,电源负极

图3.6 典型应用

电源引脚

DHT11的供电电压为3-5.5V。传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。 串行接口(单线双向) 1.单总线说明

DHT11器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约5.1kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机[16]。 2.单总线传送数据位定义

DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据,高位先出。 数据格式:

8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。 3.校验位数据定义

“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”8bit校验位等于所得结果的末8位。 4.数据时序图

用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度

采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

图3.7 数据时序图

5.外设读取

(1)DHT11上电后,测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时DHT11的DATA引脚处于输入状态,时刻检测外部信号。

(2)微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms,然后微处理器的I/O设置位输入状态,由于上拉电阻,微处理器的I/O即DHT11的DATA数据线也随之变高,等待DHT11作出回答信号。

图3.8 主机发送起始信号

(3)DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA 引脚处于输出状态,输出80us的低电平作为应答信号,紧接着输出80us的高电平通知外设准备接受数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)后 ,等待80us 的高电平

后的数据接收。

图3.9 发送信号

(4)由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据“0”的格式为:50us的低电平和26-28us的高电平;位数据“1”的格式为:50us的低电平加70us的高电平。

图3.10 位数据“0”的格式

图3.11 位数据“1”的格式 测量分辨率

测量分辨率分别为8bit(温度)、8bit(湿度)。 电气特性

VDD=5V,T = 25℃,除非特殊标注

表3.1 电气特性表

参数 供电 供电电流 条件 DC 测量 平均 待机 采样周期 秒 min 3 0.5 0.2 100 1 typ 5 max 5.5 2.5 1 150 单位 V mA mA uA 次 3.3 无线模块设计

nRF24.L01是一款新型单片射频收发器件,工作于2.4 GHz~2.5 GHz ISM频段。内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合了增强型ShockBurst技术,其中输出功率和通信频道可通过程序进行配置。nRF24L01功耗低,在以-6dBm的功率发射时,工作电流也只有9 mA;接收时,工作电流只有12.3 mA,多种低功率工作模式(掉电模式和空闲模式)使节能设计更方便[17]。 主要特点

1.GFSK调制,硬件集成OSI链路层 2.具有自动应答和自动再发射功能 3.片内自动生成报头和CRC校验码 4.数据传输率为l Mb/s或2Mb/s 5.SPI速率为0 Mb/s~10 Mb/s

6.125个频道与其他nRF24系列射频器件相兼容

7.双通道数据接收,内置环行天线,开阔地无干扰条件通信距离20-50米 8.QFN20引脚4 mm×4 mm封装 9.供电电压为1.9 V~3.6 V 引脚说明

图3.12 nRF24L01

nRF24L01引脚排列如图3.12所示。各引脚功能如下: CE:使能发射或接收;

CSN,SCK,MOSI,MISO:SPI引脚端,微处理器可通过此引脚配置nRF24L01; IRQ:中断标志位; VDD:电源输入端; VSS:电源地;

XC2,XC1:晶体振荡器引脚;

VDD_PA:为功率放大器供电,输出为1.8 V; ANT1,ANT2:天线接口。 工作模式

通过配置寄存器可将nRF24L01配置为发射、接收、空闲及掉电四种工作模式,如表3.2所示:

表3.2 工作模式

模式 接收模式 发射模式 PWR_UP 1 1 PRIM_RX 1 0 CE 1 1 FIFO寄存器状态 - 数据在TX FIFO 寄存器中 发射模式 1 0 1→0 停留在发送模式,直至数据发送完 待机模式2 待机模式1 掉电 1 0 1 TX_FIFO为空 1 - 0 无数据传输 0 - - - 待机模式1主要用于降低电流损耗,在该模式下晶体振荡器仍然是工作的;待机模式2则是在当FIFO寄存器为空且CE=1时进入此模式;待机模式下,所有配置字仍然保留。在掉电模式下电流损耗最小,同时nRF24L01也不工作,但其所有配置寄存器的值仍然保留。 工作原理

图3.13 电路原理图

发射数据时,首先将nRF24L01配置为发射模式:接着把接收节点地址

TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从TX FIFO中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TX FIFO中数据保留以便再次重发;MAX_RT或TX_DS置高时,使IRQ变低,产生中断,通知MCU。最后发射成功时,若CE为低则nRF24L01进入空闲模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入空闲模式2[19]。

接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。当接收方检测到有效的地址和CRC时,就将数据包存储在RX FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。

图3.14 单片机与nRF24L01连接图

配置字

SPI口为同步串行通信接口,最大传输速率为10 Mb/s,传输时先传送低位字节,再传送高位字节。但针对单个字节而言,要先送高位再送低位。与SPI相关的指令共有8个,使用时这些控制指令由nRF24L01的MOSI输入。相应的状态和数据信息是从MISO输出给MCU[20]。

nRF24L0l所有的配置字都由配置寄存器定义,这些配置寄存器可通过SPI口访问。nRF24L01 的配置寄存器共有25个,常用的配置寄存器如表3.3所示:

表3.3 配置寄存器

地址(H) 00 01 02 03 04 07 0A~0F 10 11~16 寄存器名称 CONFIG EN_AA EN_RXADDR SETUP_AW SETUP_RETR STATUS RX_ADDR_P0~P5 TX_ADDR RX_PW_P0~P5 功能 设置24L01工作模式 设置接收通道及自动应答 使能接收通道地址 设置地址宽度 设置自动重发数据时间和次数 状态寄存器,用来判定工作状态 设置接收通道地址 设置接收接点地址 设置接收通道的有效数据宽度 3.4 液晶显示装置设计 液晶简介

1602液晶也叫1602字符型液晶 它是一种专门用来显示字母、数字、符号等的点阵型液晶模块,它有若干个5x7或者5x11等点阵字符位组成,每个点阵字符位都可以显示一个字符。每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,他不能显示图形(用自定义CGRAM,显示效果也不好)1602LCD是指显示的内容为16x2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,

控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶[23]。 1602LCD主要技术参数: 显示容量:16×2个字符 芯片工作电压:4.5-5.5V 工作电流:2.0mA(5.0V) 模块最佳工作电压:5.0V 字符尺寸:2.95×4.35(W×H)mm 图3.15 1602LCD引脚图 引脚功能说明: 1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下: 第1脚:VSS为地电源。 第2脚:VDD接5V正电源。 第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。 第7~14脚:D0~D7为8位双向数据线。 第15脚:背光源正极。 第16脚:背光源负极。 液晶显示原理

读写操作时序如图3.16和图3.17所示:

图3.16 读操作时序

图3.17 写操作时序

3.5 报警系统设计

本系统采用红LED灯作为光报警提示,当系统检测到的数据不符合给定的要求时,现场为红灯报警提示;本系统采用蜂鸣器作为声报警提示,当系统检测到的数据符合给定的要求时,现场没有蜂鸣器报警提示;当系统检测到的数据不符合给定的要求时,现场蜂鸣器报警提示。如图3.18:

图3.18 报警系统电路图

4 系统软件设计

本系统软件系统设计包括:系统初始化模块,数据采集模块,无线模块,1602LCD显示模块,报警模块。系统软件总体流程图如图4.1:

开始初始化温湿度检测单片机处理LCD显示范围判断YES终止无线信号发送NO光声报警 图4.1 系统流程图

4.1 系统初始化模块

系统初始化模块的主要功能是完成系统的初始化以及设定系统的工作状态,初始化部分包括以下方面的内容:

1.单片机初始化以及各种引脚定义 2.1602液晶初始化及工作方式 3.系统进入正常工作状态

4.2 数据采集模块

温湿度检测模块是本系统中的核心模块之一,它负责完成温度和湿度的测量及模拟量转换为数字量的全过程,这也是它为什么重要的原因。数字式温湿度传感器DHT11直接把检测到的模拟量转化为数字量送给单片机,在经过单片机的处理,把温湿度值显示在1602液晶上。温湿度传感器的精确度值直接影响到整个系统的检测与控制,所以本系统采用数字式温湿度传感器DHT11采集温室内的温湿度[25]。

温湿度判断控制模块也是系统的核心模块之一,所谓判断控制模块,就是对当

前温室内的实际温湿度与给定的温湿度范围进行比较,先进行判断,然后再进行控制,控制模块是决定系统将要进行什么工作的。如温度和湿度高于上限时或低于下限时需要进行启动警报,并且将温湿度结果以无线进行通信等。温湿度传感器程序流程图如图4.2所示:

开始NP2.0输出低电平从机80us低电平是否结束 YN延时18msP2.0输出高电平从机80us高电平是否结束Y单片机进行数据接收将数据按十进制数位存入数组延时40usN读2.0引脚判断是否为低电平Y开始

图4.2 温湿度传感器程序流程图

4.3 无线模块 无线发射模块部分

首先进行初始化操作,初始化包括设置单片机I/O和SPI相关寄存器两部分其可以和nRF24L01通信。通过SPI总线配置射频芯片使其进入正确的工作模式。发射数据时,首先将nRF24L01配置为发射模式[26]。接着把发送端待发射数据的目标地址TX-ADDR和数据TX-PLD写入nRF24L01缓冲区,延时后发射数据,其流程图如图4.3所示:

上电初始化单片机配置24L01为发射模式写数据并开启发送否是否接受到应答信号?是向串口传输数据结束

图4.3 无线发射软件流程图

无线接收模块部分

接收数据时,首先将nRF24L01配置为接收模式。接着延迟进入接收状态等待数据的到来。当接收方检测到有效地址和CRC时,就将数据包储存在接收堆栈中,同时状态寄存器中的中断标志位RX-DR置高,产生中断使IRQ引脚变为低电平,以便通知MCU去取数据,其流程图如图4.4所示:

上电初始化单片机配置24L01为接受模式检测载波信号否存在当前频率的载波信号?是结束

图4.4 无线接收软件流程图

4.4 显示模块

本系统采用1602液晶显示温湿度值,当系统刚开始上电时1602液晶不显示任何数据,等待AM2301的监测数据,双行显示在1602液晶上。第一行显示:TRH RH:--%,第二行显示:TRH T:--。C。

开 始 对 LCD1602A进行初

扫描按键 延时消抖

否 首行扫描字R3列扫描送

判第七位是否为0 LCD1602A写命令

延 时 结 束 显 示 扫描判定键值 键值入栈保护 是否按下 否 否 键值转化为ASII码,存入寄 判释放按键 否 继续扫描 图4.5 显示流程图

4.5 报警模块

报警模块具备两项功能,即为报警灯和声音报警。报警灯模块是完成LED有规律的转换,以便从视觉上提醒用户。LED是由单片机控制LED灯组成的,其转换规律为:

1.系统温湿度值在给定的范围时,LED不亮。 2.系统温湿度值超出给定的范围时,红色LED亮。

在LED灯转换的同时,声音报警也会同时启动,可采用延时的方式来延长声音报警的声音。

警报灯由1个LED灯组成,一共需要1根数据线,使用单片机AT89S52控制。要实现的功能是使LED灯有规律亮与熄灭,当系统上电后,系统进行实时的采样,并判断出当前温湿度与给定温湿度之间的差异,如果当前温湿度低于用户给定的下限温湿度值,则说明当前温湿度过低,系统自动启动红色警报灯,直至温湿度值升到适合范围时警报灯熄灭。反之,如果当前温湿度高于用户设定的上限温湿度值,则说明当前温湿度过高,系统也会自动启动警报灯,直至温湿度值降到适当范围时警报灯熄灭。

5 硬件调试

使用AT89S52单片机为控制核心芯片,DHT11温湿度传感器为空气温湿度检测模块,nRF24L01无线模块进行数据传输,进行数据的实时显示。在单片机开发板上连接好电路进行调试:

图5.1 正常室温中温湿度检测结果(湿度:22%,温度:31C)

图5.2 使用热水进行高温加热,查看其温湿度变化

图5.3 不断的进行使用热水加热,当温度超过其范围时报警,LED等同时亮

图5.4 当温度上升到超过适当范围时检测的温湿度值

图5.5 显示为无线模块NRF24L01,温度超过正常范围时进行数据的无线发送与接收

图5.6 温湿度数据接收板

图5.7 无线模块接收发送的数据后经单片机处理后在显示屏上显示的结果

结论

到此智能温室温湿度控制系统的设计已经完成了,在这段时间里,先后完成了资料的收集、设计方案的拟订、画图等多方面的工作。首先,通过这次应用系统设计,在很大程度上提高了自己的独立思考能力和单片机的专业知识,其次,我也深刻了解写一篇应用系统的步骤和格式,有过这样的一次训练,相信在接下来的日子我们都会了,而且会做得更好。

本系统主要根据目前温室大棚技术的发展趋势和国内实际的应用特点和要求,采用了自动化的结构形式,实现对空气温湿度的自动检测和控制。

系统以单片机AT89S52为核心部件,单片机系统完成对温湿度信号的采集、处理、显示等功能。该系统的主要特点是:

1.适用性强,用户只需对参数进行设置并启动系统正常运行便可实现对温室温湿度的实时监控。

2.实现无线信号传输。

3.可对作物的生产环境进行适时、适当的控制,不仅有利于作物的生长发育,而且避免了了资源的浪费,起到了提高作物产量的作用。

附录

发送部分程序 #include #include

typedef unsigned char uchar; typedef unsigned char uint;

//****************NRF24L01端口定义********************* sbit MISO=P1^5;sbit MOSI=P1^1;sbit SCK=P1^4; sbit

CE=P1^3;sbit CSN=P1^0;sbit IRQ=P1^2;

//*************************按键************************* sbit TRH = P2^1;//温湿度传感器DHT11数据接入

//**********************发送缓冲区********************** uchar TxBuf[32]= { 0 };

unsigned char receive_buf[32]={0}; unsigned char receive_data,receive_s,flag; unsigned char receive_beg;

//**********************NRF24L01************************ #define TX_ADR_WIDTH 5 #define RX_ADR_WIDTH 5 #define TX_PLOAD_WIDTH 32 #define RX_PLOAD_WIDTH 32

// 5 uints TX address width // 5 uints RX address width // 20 uints TX payload // 20 uints TX payload

uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址

uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址

//******************NRF24L01寄存************************ #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留

//*****************SPI(nRF24L01)寄存器地址****************

#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式

#define EN_AA 0x01 // 自动应答功能设置 #define EN_RXADDR 0x02 // 可用信道设置 #define SETUP_AW 0x03 // 收发地址宽度设置 #define SETUP_RETR 0x04 // 自动重发功能设置 #define RF_CH 0x05 // 工作频率设置

#define RF_SETUP 0x06 // 发射速率、功耗功能设置 #define STATUS 0x07 // 状态寄存器 #define OBSERVE_TX 0x08 // 发送监测功能 #define CD 0x09 // 地址检测

#define RX_ADDR_P0 0x0A // 频道0接收数据地址 #define RX_ADDR_P1 0x0B // 频道1接收数据地址 #define RX_ADDR_P2 0x0C // 频道2接收数据地址 #define RX_ADDR_P3 0x0D // 频道3接收数据地址 #define RX_ADDR_P4 0x0E // 频道4接收数据地址 #define RX_ADDR_P5 0x0F // 频道5接收数据地址 #define TX_ADDR 0x10 // 发送地址寄存器 #define RX_PW_P0 0x11 // 接收频道0接收数据长度 #define RX_PW_P1 0x12 // 接收频道0接收数据长度 #define RX_PW_P2 0x13 // 接收频道0接收数据长度 #define RX_PW_P3 0x14 // 接收频道0接收数据长度 #define RX_PW_P4 0x15 // 接收频道0接收数据长度 #define RX_PW_P5 0x16 // 接收频道0接收数据长度 #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置 //******************************************************** unsigned char TH_data,TL_data,RH_data,RL_data,CK_data; unsigned char TH_temp,TL_temp,RH_temp,RL_temp,CK_temp; unsigned char com_data,untemp,temp;

unsigned char respond;void Delay(unsigned int s);

void inerDelay_us(unsigned char n);void StartUART( void ); void init_NRF24L01(void);uint SPI_RW(uint uchar); uchar SPI_Read(uchar reg);void SetRX_Mode(void); uint SPI_RW_Reg(uchar reg, uchar value);

uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);

unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf); void read_TRH();char receive();

//**********************长延时*************************** void Delay(unsigned int s) { }

void delay_ms(unsigned char ms) {

unsigned char i;while(ms--) {

for(i = 0; i< 150; i++) {

_nop_();_nop_();_nop_();_nop_(); } } }

/*********************************************************/ /*********************************************************/ //5us级延时程序

/*********************************************************/ void delay_us() {

unsigned char i;i--;i--;i--;i--;i--;i--;

unsigned int i;for(i=0;i

}

//******************************************************** uint bdata sta; //状态标志 sbit

RX_DR=sta^6;sbit TX_DS=sta^5;sbit MAX_RT=sta^4;

/********************************************************** /*延时函数

/**********************************************************/ void inerDelay_us(unsigned char n) { }

//********************************************************** /*NRF24L01初始化

//**********************************************************/ void init_NRF24L01(void) {

inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable

SCK=0; // Spi clock line init high

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写for(;n>0;n--)

_nop_();

本地地址

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //

写接收端地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答

允许

SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,

如果需要多频道可以参考Page21

SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,

收发必须一致

SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长

度,本次设置为32字节

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);

//设置发射速率为

1MHZ,发射功率为最大值0dB

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);

// IRQ收发完成中断响

应,16位CRC,主发送 }

/******************************************************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序

/********************************************************/ uint SPI_RW(uint uchar) {

uint bit_ctr;

for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit {

MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB.. SCK = 1; // Set SCK high..

uchar |= MISO; // capture current MISO bit

SCK = 0; // ..then set SCK low again

}

return(uchar); // return read uchar }

/********************************/*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序

/********************************************************/ uchar SPI_Read(uchar reg) { }

/*********************************************************/ /*功能:NRF24L01读写寄存器函数

/*********************************************************/ uint SPI_RW_Reg(uchar reg, uchar value) {

uint status;

CSN = 0; // CSN low, init SPI transaction status = SPI_RW(reg); // select register uchar reg_val;

CSN = 0; // CSN low, initialize SPI communication... SPI_RW(reg); // Select register to read from.. reg_val = SPI_RW(0); // ..then read registervalue

CSN = 1; // CSN high, terminate SPI communication return(reg_val); // return register value

}

SPI_RW(value); // ..and write value to it.. CSN = 1; // CSN high again

return(status); // return nRF24L01 status uchar

/**********************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数

/************************************************************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) {

uint status,uchar_ctr;

CSN = 0; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read status

uchar }

/***************************************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)

/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数

/**********************************************************/

for(uchar_ctr=0;uchar_ctr

return(status); // return nRF24L01 status uchar

uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { }

/*********************************************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf中数据

/************************************************/ void nRF24L01_TxPacket(unsigned char * tx_buf) {

CE=0;

//StandBy I模式

uint status,uchar_ctr;

CSN = 0; //SPI使能 status = SPI_RW(reg);

for(uchar_ctr=0; uchar_ctr

SPI_RW(*pBuf++);

CSN = 1; //关闭SPI return(status); //

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //

装载接收端地址

SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);

//

装载数据

// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); 应,16位CRC,主发送

CE=1;

//置高CE,激发数据发送

// IRQ收发完成中断响

inerDelay_us(10);

}

//*************************主函数*************************** void main(void) { }

char receive() {

unsigned char i; // ST=0; com_data=0;

for(i=0;i<=7;i++) {

respond=2;

while((!TRH)&&respond++);

uchar temp =0; init_NRF24L01();

nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(6000); while(1) { }

read_TRH();

nRF24L01_TxPacket(TxBuf);// Transmit Tx buffer data

Delay(10000); //可变

SPI_RW_Reg(WRITE_REG+STATUS,0XFF); flag=0;

delay_us();delay_us();delay_us(); if(TRH) {

temp=1;respond=2;while((TRH)&&respond++); } else

temp=0;com_data<<=1; com_data|=temp; }

return(com_data); }

/******************************************************/ /******************************************************/ //湿度读取子程序 //温度高8位== TL_data //温度低8位== TH_data //湿度高8位== RH_data //湿度低8位== RH_data //校验 8位 == CK_data

//调用的程序有 delay();, Delay_5us();,RECEIVE(); /****************************************************/ void read_TRH() {

//主机拉低18ms

TRH=0;delay_ms(18);TRH=1;

//DATA总线由上拉电阻拉高 主机延时20us

delay_us();delay_us();delay_us();delay_us(); //delay_us();

//delay_us();delay_us();delay_us();delay_us(); //主机设为输入 判断从机响应信号 TRH=1;

//判断DHT11是否有低电平响应信号 如不响应则跳出,响应则向下运行

if(!TRH) {

respond=2;

//判断DHT11发出 80us 的低电平响应信号是否结束 while((!TRH)&& respond++); respond=2;

//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态 while(TRH && respond++); //数据接收状态

RH_temp = receive(); RL_temp = receive(); TH_temp = receive(); TL_temp = receive(); CK_temp = receive(); TRH=1;//ST=1; //数据校验

untemp=(RH_temp+RL_temp+TH_temp+TL_temp); if(untemp==CK_temp) {

RH_data = RH_temp;RL_data = RL_temp; TH_data = TH_temp;TL_data = TL_temp;

CK_data = CK_temp; } }

//湿度整数部分

TxBuf[0] = (char)(0X30+RH_data/10); TxBuf[1] = (char)(0X30+RH_data); TxBuf[2] = 0x2e; //小数点 //湿度小数部分

TxBuf[3] = (char)(0X30+RL_data/10); TxBuf[4] = 0X25;//\ TxBuf[5] = 0X52; //\ TxBuf[6] = 0X48; //\ //温度整数部分

TxBuf[7] = (char)(0X30+TH_data/10); TxBuf[8] = (char)(0X30+TH_data); TxBuf[9] = 0x2e;//小数点 //温度小数部分

TxBuf[10] = (char)(0X30+TL_data/10); TxBuf[11] = 0X27; //\ TxBuf[12] = 0X43; //\}

接收部分程序 #include #include

typedef unsigned char uchar;

typedef unsigned char uint;

//************************IO端口定义************************ sbit MISO=P0^5;sbit MOSI=P0^1;sbit SCK=P0^4; sbit CE=P0^3;sbit CSN=P0^0; sbit

IRQ=P0^2;uchar RxBuf[32]={0};

unsigned char code dianya1[]={\温度显示:\; unsigned char code dianya2[]={\湿度显示:\;

//*************************按键************************** //*******************数码管0-9编码********************** uchar

seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}

//0~~9段码

void delayms(unsigned char); void keyscan();//记忆按键状态

void da_in();//将按键值转化并送入到DA中 void dianliu_to_lcd();//将按键状态值送入LCD void dianya_to_lcd();//将按键状态值送入LCD void ad();//得到AD采样的值

void sendcom(unsigned char com);//向LCD发命令 void senddata(unsigned char dat);//向LCD发数据 void lcd_init();//LCD初始化 void T_init();//定时器初始化 void autosaodianliu();

int od_data,op_data,oz_data;

void change(int dat);

unsigned char code dianliu1[]={\设置电流:mA\;

unsigned char code dianliu2[]={\实际电流:mA\; sbit sid=P3^6;//LCD串行数据输入端 sbit clk=P3^4;//LCD时钟输入端 sbit cs=P3^5;//LCD片选 unsigned char key_button=0;

unsigned char key[3],j=0,i=0;//KEY数组用来存放按键按下的值 unsigned int ad1,ad2,advalue;//用于取AD采样值 bit flag=0;int d_data,pf_data,t_data;

unsigned char z1_data,z2_data;int knum,aa=0,p_data,z_data,t_on;//**************************************************** #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5

// 5 uints RX address width

#define TX_PLOAD_WIDTH 32 // 20 uints TX payload #define RX_PLOAD_WIDTH 32

// 20 uints TX payload

uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};地地址

uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};收地址

//*******************NRF24L01寄存器指令******************* #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令

#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令

//本//接 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留

//******************SPI(nRF24L01)寄存器地址*****************

#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式

#define EN_AA 0x01 // #define EN_RXADDR 0x02 // #define SETUP_AW 0x03 // #define SETUP_RETR 0x04 // #define RF_CH 0x05 // #define RF_SETUP 0x06 // #define STATUS 0x07 // #define OBSERVE_TX 0x08 // #define CD 0x09 // #define RX_ADDR_P0 0x0A // #define RX_ADDR_P1 0x0B // #define RX_ADDR_P2 0x0C // #define RX_ADDR_P3 0x0D // #define RX_ADDR_P4 0x0E // #define RX_ADDR_P5 0x0F // #define TX_ADDR 0x10 // #define RX_PW_P0 0x11 // #define RX_PW_P1 0x12 // #define RX_PW_P2 0x13 // #define RX_PW_P3 0x14 // 自动应答功能设置 可用信道设置 收发地址宽度设置 自动重发功能设置 工作频率设置

发射速率、功耗功能设置 状态寄存器 发送监测功能 地址检测 频道0接收数据地址 频道1接收数据地址 频道2接收数据地址 频道3接收数据地址 频道4接收数据地址 频道5接收数据地址 发送地址寄存器 接收频道0接收数据长度 接收频道0接收数据长度 接收频道0接收数据长度 接收频道0接收数据长度

#define RX_PW_P4 0x15 // 接收频道0接收数据长度 #define RX_PW_P5 0x16 // 接收频道0接收数据长度 #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置 //****************************************************

void Delay(unsigned int s);void inerDelay_us(unsigned char n); void init_NRF24L01(void);uint SPI_RW(uint uchar); uchar SPI_Read(uchar reg);void SetRX_Mode(void); uint SPI_RW_Reg(uchar reg, uchar value);

uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf); //**********************长延时*********************** void Delay(unsigned int s) { }

//****************************************************** uint bdata sta; //状态标志 sbit

RX_DR =sta^6;sbit TX_DS=sta^5;sbit MAX_RT=sta^4; unsigned int i; for(i=0; i

/******************************************************* /*延时函数

/*******************************************************/

void inerDelay_us(unsigned char n) { }

void delayms(unsigned char i) {

unsigned char j=120; while(i--) }

void sendcom(unsigned char com)//向LCD发命令 {unsigned char a,i; cs=1;clk=0;a=0xf8; for(i=0;i<8;i++) {sid=(bit)(a&0x80) clk=0;clk=1;a=a<<1;

}

while(j--); for(n>0;n--)

_nop_();

a=com&0xf0; for(i=0;i<8;i++) {sid=(bit)(a&0x80); clk=0;clk=1;a=a<<1;

}

a=com<<4;

for(i=0;i<8;i++)

{sid=(bit)(a&0x80); clk=0;clk=1;a=a<<1;

}

cs=0;delayms(1); }

void senddata(unsigned char dat)//向LCD发数据 {unsigned char a,i; cs=1;clk=0;a=0xfa; for(i=0;i<8;i++) {sid=(bit)(a&0x80); clk=0;clk=1;a=a<<1;

}

a=dat&0xf0; for(i=0;i<8;i++) {sid=(bit)(a&0x80); clk=0;clk=1;a=a<<1;

}

a=dat<<4; for(i=0;i<8;i++) {sid=(bit)(a&0x80); clk=0;clk=1;a=a<<1;

}

cs=0; delayms(1); }

void lcd_init()//LCD初始化 {

delayms(100);sendcom(0x30);sendcom(0x02);sendcom(0x06); sendcom(0x0c);sendcom(0x01);sendcom(0x80); }

void keyscan()//按键扫描,将其存入KEY[3]中 {

unsigned char temp;

if(i>=3)

i=0;

if(flag==1)//按下过START后才执行以下程序

{

P2=0xfe;temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

delayms(10);temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{ temp=P2; key_button++; switch(temp) { case 0xee:

key[i++]=1;break; case 0xde:

}

key[i++]=2;break;

case 0xbe:

key[i++]=3;break; case 0x7e:

key[i++]=4;break;

}

while(temp!=0xf0) }

{

temp=P2;temp=temp&0xf0; }

P2=0xfd;temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

delayms(10);temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

temp=P2;key_button++; switch(temp)

{

case 0xed:

key[i++]=5;break;

case 0xdd:

key[i++]=6;break;

}

}

}

case 0xbd:

key[i++]=7;break;

case 0x7d:

key[i++]=8;break;

while(temp!=0xf0) }

{

temp=P2; temp=temp&0xf0;

}

P2=0xfb;temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

delayms(10);temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

temp=P2; switch(temp)

{

case 0xeb:

if(flag==1)//按下过START后才执行以下程序

key[i++]=9;

}

key_button++;

break;

case 0xdb:

if(flag==1)//按下过START后才执行以下程序

key[i++]=0; key_button++;

break;

case 0xbb:

if(flag==1)//按下过START后才执行以下程序 }

key[i++]='.';

break;

case 0x7b:

{

key[0]=0;key[1]=0;key[2]=0;

} Break;

while(temp!=0xf0) }

{

temp=P2;temp=temp&0xf0;

}

P2=0xf7;temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

delayms(10);temp=P2;temp=temp&0xf0; if(temp!=0xf0)

{

temp=P2; switch(temp)

{

case 0xe7:

i=0;flag=1;break; case 0xd7:

i=0;flag=0;break;

case 0xb7:

{

if(!(key[0]>=5&&key[1]>=0&&key[0]>=0))

{

key[2]=key[2]+5; if(key[2]==10) {

key[2]=0;key[1]++; if(key[1]==10) {

key[1]=0; key[0]++; } }

}

}

}

Break;

case 0x77:

{

if(key[2]>0||key[0]>0||key[1]>0)

{

if(key[2]==0)

{ } else

key[2]=key[2]-5;

key[2]=5; if(key[1]==0) {

key[1]=9; key[0]--; } else key[1]--;

}

}

Break;

while(temp!=0xf0)

}

}

{

temp=P2; temp=temp&0xf0;

}

}

void da_in()//将KEY数组中的数送入DA中 {

if(flag==0)//未按下START,或按下了END

//P1=40*key[0]+4*key[1]+4*(key[2]+5)/10;//0~200,0~500; }

{ }

if(key_button==2) { } else

if(key_button==3) { }

key_button=0;

P1=100*key[0]+10*key[1]+key[2];//0~200,0~500; key_button=0; P1=10*key[0]+key[1];

void dianya_to_lcd()//将电压按键值和AD采样值分别送入LCD显示 {

unsigned a; if(od_data!=d_data)

{

sendcom(0x85); for(i=0;i<6;i++) }

senddata(' ');

if(od_data!=d_data) { }

if(od_data!=d_data) { }

od_data=d_data;op_data=pf_data;oz_data=t_on;sendcom(0x80); for(a=0;a<9;a++)

senddata(dianya1[a]);senddata(RxBuf[0]);

sendcom(0x8d); for(i=0;i<6;i++)

senddata(' '); sendcom(0x95); for(i=0;i<6;i++)

senddata(' ');

senddata(RxBuf[1]);senddata(RxBuf[2]);senddata(RxBuf[3]);

senddata(RxBuf[4]);senddata(RxBuf[5]);senddata(RxBuf[6]); sendcom(0x90); for(a=0;a<9;a++)

senddata(dianya2[a]);senddata(RxBuf[7]); senddata(RxBuf[8]);senddata(RxBuf[9]); senddata(RxBuf[10]);senddata(RxBuf[11]); senddata(RxBuf[12]);

}

void T_init()//定时器初始化 { TMOD=0x11;TH0=0xf0;TL0=0xff;TH1=0x4f;TL1=0xff; EA=1;ET0=1;ET1=1;TR0=1;TR1=1; }

//********************************************************** /*NRF24L01初始化

//**********************************************************/ void init_NRF24L01(void) {

inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable

SCK=0; // Spi clock line init high

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //

写接收端地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答

允许

SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,

如果需要多频道可以参考Page21

SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,

收发必须一致

SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);//设置接收数据长度,

本次设置为32字节

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);

//设置发射速率为

1MHZ,发射功率为最大值0dB

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);

// IRQ收发完成中断响

应,16位CRC ,主接收 }

/************************************/*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序

/**********************************************************/ uint SPI_RW(uint uchar) {

uint bit_ctr;

for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit {

MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB..

SCK = 1; // Set SCK high..

uchar |= MISO; // capture current MISO bit SCK = 0; // ..then set SCK low again

}

return(uchar); // return read uchar }

/********************************************************** /*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序

/***********************************************************/ uchar SPI_Read(uchar reg) { }

/***********************************************************/ /*功能:NRF24L01读写寄存器函数

/***********************************************************/ uint SPI_RW_Reg(uchar reg, uchar value) {

uint status;

CSN = 0; // CSN low, init SPI transaction uchar reg_val;

CSN = 0; // CSN low, initialize SPI communication... SPI_RW(reg); // Select register to read from.. reg_val = SPI_RW(0); // ..then read registervalue

CSN = 1; // CSN high, terminate SPI communication return(reg_val); // return register value

}

status = SPI_RW(reg); // select register

SPI_RW(value); // ..and write value to it.. CSN = 1; // CSN high again

return(status); // return nRF24L01 status uchar

/************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数

/************************************************************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) {

uint status,uchar_ctr;

CSN = 0; status = SPI_RW(reg);

// Set CSN low, init SPI tranaction // Select register to write to and

read status uchar }

/*********************************************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数

for(uchar_ctr=0;uchar_ctr

pBuf[uchar_ctr] = SPI_RW(0); //

CSN = 1;

return(status); // return nRF24L01 status uchar

/**********************************************************/ uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { }

/**********************************************************/ /*函数:void SetRX_Mode(void) /*功能:数据接收配置

/**********************************************************/ void SetRX_Mode(void) {

CE=0;

// IRQ收发完成中断响

uint status,uchar_ctr;

CSN = 0; //SPI使能 status = SPI_RW(reg);

for(uchar_ctr=0; uchar_ctr

SPI_RW(*pBuf++);

CSN = 1; //关闭SPI return(status); //

// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); 应,16位CRC ,主接收 }

CE = 1; inerDelay_us(130);

/********************************************************/ /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如rx_buf接收缓冲区中

/********************************************************/ unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) {

unsigned char revale=0;

sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况 if(RX_DR) {

CE = 0;

//SPI使能

// 判断是否接收到数据

SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive

payload from RX_FIFO buffer

}

SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后

revale =1;

//读取数据完成标志

RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志 }

/********************************************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf中数据

/***********************************************************/ void nRF24L01_TxPacket(unsigned char * tx_buf) {

CE=0;

//StandBy I模式

return revale;

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //

装载接收端地址

SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); //

装载数据

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);

// IRQ收发完成中断响

应,16位CRC,主发送 }

//*******************串口初始化****************************** void StartUART( void ) { }

//*************通过串口将接收到数据发送给PC端*************** void R_S_Byte(uchar R_Byte) {

SBUF = R_Byte;

//查询法

//波特率4800

CE=1;

//置高CE,激发数据发送

inerDelay_us(10);

TMOD=0x21;//设置定时器1为工作方式2

TH1=0xfa;TL1=0xfa;TH0=(65535-100)/256;TL0=(65535-100)%6; TR1=1;TR0=1;ET0=1;REN=1;SM0=0;SM1=1;EA=1;ES=1;

while( TI == 0 ); TI = 0; }

//*****************主函数*************************************** void main(void) {

uchar i;init_NRF24L01() ;StartUART();//T_init();

lcd_init();key[0]=0;key[1]=0;key[2]=0; P1=0;Delay(600); while(1) {

SetRX_Mode();

if(nRF24L01_RxPacket(RxBuf)) { }

dianya_to_lcd();delayms(5);

}

}

参考文献

[1] 高职富.温室环境控制技术的现状及发展前景[J].中国市场,2007年第35期:106-107

[2] 吉红.自动控制在国外设施农业中的应用[J].农业环境与发展,2007(5):52-54 [3] 杨志强,周士冲,陈磊.我国设施农业的发展分析[J].农业机械化,2006年第12期:42-43

[4] 王世明,王冰.现代农业温室系统[J].山西农业科学,2008,36(9):69-73

[5] 毕玉革,麻硕士.我国现代温室环境控制硬件系统的应用现状及发展[J]. 农业化研究,2009年第3期:226-229

[6] 范薇薇.基于无线传感器网络的温室控制系统研究[D].中国知网,2010 [7] 王中心.温室土壤温湿度无线信息采集与监控系统的设计与实现.中国知网,2010

[8] 李文仲,段朝玉.短距离无线数据通信入门与实战[M],北京航空航天大学出版社,2006

[9] 张金波,张学武.制约数据远距离传输的因素及解决方法[J].微型机与应用, 2000,21(10):77- 82

[10] 徐爱钧.单片机原理实用教程.电子工业出版社,2011,3 [11] 朱定华.单片机原理与接口技术.电子工业出版社,2001,4 [12] 刘瑞新.单片机原理及应用教程.机械工业出版社,2003,7

[13] 李朝青.PC机及单片机数据通信技术[M].北京:北京航空航天大学出版社, 2000

[14] 刘文涛.单片机应用开发实例[M].清华大学出版社,2005 [15] 韩太林. 单片机原理及应用[M].电子工业出版社,2005

[16] 李迎霞,杜尚丰.中国温室环境智能控制算法研究进展[N].农业工程学报,2004,20(2):267-272

[17] LEWIS R.Modeling control system using IEC 61499[M].Institution of Electrical Engineers,2001

[18] CHRISTENSEN J H. Basic concept of IEC 61499[C].Fachtagung Verteilte Automat isierung,Magdeburg DE,2000:22- 23

[19] IEC 65/240/CD,Function blocks for industrial- process measurement and control systems - Part 1:Architecture[S].1999

[20] IEC 61499 - 2 (and Committee Draft to be published),Function blocks for industrial- process measurement and control systems - Part 2:Engineering Task Support[S].1999

[21] Deng.X.P,Shan.L,Zhang.H.P,Turner.N.C. Improving agricultural water use efficiency in arid semiarid areas of china. Agric. Water Manage,2006.80(1-3):23-40 [22] T.Boulard,B.Draoui,F.Neirac.Calibration and validation of a greenhouse climate

control model.Acta Horticulturae.1996,(406):46-61 [23]

Willing

A.Wireless

sensor

net

work

concept

challenges

and

approaches.Elektroteelnik & Informationsteehnik,2006,123(6):224-231

[24] Dan Suciu,Gottfried Vosen,The World Wide Web and databases,Springer,2001.1[24] Samsung Electronies.S3C44BOX Risc microprocessor data sheet.2002

[25] Kim,J,A Web-Based Speaking Test Development Using Visual Basic 6.0. Multimedia Assisted Language Learning,2006.9(2):77-98 [26] AT89C51 DATA SHEEP Philips Semiconductors 1999.dec [27] AT89S52DATASHEET,Atmel Corporation 2005

[28] Philips Semiconductors.Application Notes and Development Tools for 80C51 Microcontrollers.2003

[29] 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

[30] Somma, Jetal., Rapid Development and Validation of a Three-Compartment Non-Linear with Covariate PK Simulator Using Visual Basic 6.0 and the Simulink Component of MatLab. Anesthesiology, 2003. 99(A510): pp. A510

基于单片机的智能温室温湿度控制系统的设计.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c55oky1a2tj5dq8n1sig30fluh9boav00ui3_1.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top