找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机系统的温度检测与无线收发设计

[复制链接]
跳转到指定楼层
楼主
ID:442604 发表于 2018-12-9 13:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
新型DS18B20温度传感器摆脱了传统的以热敏电阻为传感器的温度测量方法,而改为一种全新的,以数字温度传感器作感温元件的数字式温度计,解决了传统的温度检测可靠性差,测量温度准确率低的缺点,它以单总线的连接方式,使电路大大的简化。DS18B20传感器利用单片机进行控制,简单而且易于智能化控制。设计中还加入了nRF905无线收发模块,可以实现一定距离的温度数据传输,使得设计模块可以进行远距离的检测和控制。
此次设计根据具体实验制作,给出了系统实现的硬件原理图及软件流程图。该设计模块测量精度高、扩展方便,具有一定的参考价值。设计布线简单,结构紧凑,体积小,扩展方便,可在一定距离进行无线检测,在大型仓库,工厂,智能化建筑等领域的温度检测中有广阔的应用前景。

目录
摘要 3
Abstract 4
绪论   5
11  设计背景与意义 5
12  设计目的及应用 5
13  设计内容及要求  5
第二章  系统方案论证与选择  6
21  系统总体方案描述   6
22  系统总体框图 6
23  系统硬件构成 6
系统硬件主要单元设计 7
31  主控制模块 7
32  数据显示模块 9
33  信号采集模块 9
34  无线收发模块 10
系统软件设计 11
41  程序设计思路 11
42  程序设计框图 12
系统硬件调试结果图15
51  系统仿真15
52  系统硬件调试 15
53  调试结果16
心得体会及总结 16
参考文献 17
附录一:原理图 17
附录:源程序代码18

第一章  绪论
1.1研究背景与意义

随着社会的发展、科技的进步以及人们生活水平的逐步提高,现如今自动化、信息化程度越来越高,单片机和传感器的应用领域越来越广。各种方便于生活的自动控制系统进入了人们的生活。单片机和传感器在自动控制中的应用越来越广泛,它实用性强,使用方便,技术先进,它们的广泛应用是科技进步的标志。

现实中温度控制不适当导致的发霉,腐烂问题是仓库日常工作急需解决的问题,是衡量仓库管理质量的重要指标。它直接影响到储备物资的使用寿命和工作可靠性。为保持日常工作的顺利进行,首要任务是加强仓库的温度检测。同时专门的安排人员去定期去仓库测量温度也非常麻烦,因此设计一种自动检测和显示温度,并且能够进行较远距离的无限传输的温度控制设备很有必要。

1.2 研究目的及应用

温度的检测与控制是工业生产过程中应用比较广泛的课题,随着传感器在生产和生活中更加广泛的应用,利用新型单总线式数字温度传感器实现对温度的单点和多点的测试与控制得到很快开发。但就目前情况看,很少有人对仓库进行自动化检测和管理,大多数的仓库在管理过程中依然是使用传统的工作方法,利用温度计等简单检测工具人工检测仓库温湿度。这种方法不仅费时、费力,而且效率低下。市场需要普及一种简单、实用、易操作并且可以进行无线传输的温度检测设备。

1.3 设计内容及要求

本文着重阐述以单片机控制,温度传感器DS18B20对温度的数据采集和处理,NRF905无线发送和接收模块的应用,4位共阳极数码管对温度传感器处理后的温度进行显示,实现一定距离上的定点温度自动检测和发送接收。


第二章  系统方案论证与选择
2.1 系统总体方案描述
系统设计分为2个部分,第一个部分实现温度的检测、显示和发送,第二个部分为数据的接收和显示。第一个设计模块中,利用单片机STC89C52控制温度传感器DS18B20定点检测和处理温度数据,单片机将采集的温度数据发送给单片机,再通过单片机控制,对接收到的温度数据进行一定的转换和处理,然后存放在寄存器中,等待下一步处理,再经过无线发送模块nRF905将显示的数据打包发送给第二个模块。第二个设计模块中,同样利用STC89C52单片机作为控制主体,先控制nRF905无线接收模块接收第一个模块发送的数据,然后控制4位共阳极数码管显示接收到的数据。则完成整个设计流程。
2.2 系统总体框图
系统的设计框图如图1所示:

2.3 系统硬件构成
系统硬件方面主要由单片机最小系统,温度传感器DS18B20,4位共阳极数码管,还有nRF905无线收发模块组成,目的在于实现温度的准确检测和无线收发所检测的温度数据。
第三章 系统硬件电路设计3.1 单片机最小系统设计
单片机最小系统的设计主要有五个部分组成,电源电路,复位电路,晶振电路,串口电路和控制主体的STC89C52单片机。
电源电路由一个六脚的按键开关,一个1K的电阻,一个10uF的极性电容和一个显示电路供电状态的发光二极管组成。开关为了适应各种情况下能够方便供电,开关外接有一个USB接口和一个DC-5V的标准电源接口作为供电设备使用。除此之外还设计了一个外接电源接口。电源电路如图2所示。
图2 电源电路
复位电路组成很简单,仅仅有4个小器件构成,一个是作为复位控制的四脚按键,一个10uF的极性电容,还有两个电阻,阻值分别为1K和10K。电路与单片机的RST端口连接,电路上电后,按下按键控制系统复位。具体电路如图3所示:
图3 复位电路
晶振电路更为简单,只有3个器件,一个11.0592Hz的晶振外加二个30PF的普通电容组成,晶振两端分别与单片机的XTAL1和XTAL2口相接。电路如图4所示:
图4 晶振电路
串口电路主要利用MAX232来实现,MAX232是美信公司设计的一款单电源电平转换芯片,在本次设计中的使用的方法是在MAX232的1和3管脚之间,4和5管脚之间,2和16管脚之间,6和15管脚之间,还有16和16管脚之间全部加上一个0.1uF的电容,7和8管脚作为串口输入端,外接一个标准9孔串口母头,9和10管脚作为输出,分别与单片机的P3.0和P3.1连接。这样就构成了与单片机连接,可以进行串口通信的串口电路。具体电路图5所示:
图5 串口电路
单片机最小系统的主体部分使用的是STC89C52单片机,它是美国ATMEL公司生产的低电压,高性能的CMOS 8位单片机,片内寄存器可反复擦洗,含有32个可编程双向I/O口,3个16位定时/计数器,共8个中断源。需要指出且注意的是,单片机在系统设计时,管脚EA要始终接高电平。因为EA接高电平时,单片机读取内部程序存储器。当扩展有外部ROM时,读取完内部ROM后自动读取外部ROM,EA接低电平时,单片机直接读取外部ROM。 而设计中使用的STC89C52是有内部ROM的,所以此引脚始终接高电平。一般在设计单片机最小系统时,大多会加上流水灯和独立键盘的设计,但是在我的毕业设计中把这些部分作了改进。考虑到流水灯和独立键盘这些设计如果完整的加入就会造成一定的浪费,而且由于学校实验室的条件有限,PCB板的刻录存在很多问题,因此这些设备会大大增加硬件调试过程的难度,费时费力。同时,在设计单片机最小系统时,考虑到不加入这些设备的话,以后又有可能需要用到。所以中和上面各种因素,在最小系统的设计部分最后只是增加了二个独立键盘和二个LED发光二极管作为调试或需要时使用,同时,考虑到以后可能还会外接其它设备的介入,为了方便,特意留有两排20脚的单排插针外接端口,这样,设计的最小系统模块在需要时也可以控制其它外接装置。使得设计模块更加灵活多用,不仅仅局限在本次毕业设计中使用,还可以留作以后的开发板学习。
最小系统的主体STC89C52如图6所示:
图6 STC89C52管脚接线图
3.2 数据显示模块设计
数据显示电路使用的是SMA410364型号的4位共阳极数码管,其内部结构图如下面图7所示:





图7 数码管内部结构图
该数码管共有12个管脚,其中11,7,4,2,1,10,5,3管脚分别对应数码管的A,B,C,D,E,F,G,DP段选位,与单片机的P0口连接,对应单片机的P0.0-P0.7口,用来控制数码管显示数值大小,6,8,9,12管脚控制数码管的位选,分别与单片机的P2.0-P2.4口连接,通过单片机指令选择需要显示数据的数码管位。
我们知道,在单片机的端口上电后会一直存在高电平,而数码管的位选正好是高电平有效,所以会导致在不需要使用数码管的时候,数码管依然会保持打开状态。通常情况下会在单片机最小系统中使用锁存器与数码管连接,但是在这次设计中没有使用锁存器,而是改用在数码管与单片机端口连接之间加一个PNP三极管的方法,让三极管发射极接电源,基集与单片机端口连接,集电极与数码管连接,这样的设计就会导致单片机端口给低电平时才会选通数码管,不仅方便控制,而且电路设计简单。
设计原理图如图8所示:
图8 数码管电路
3.3 信号采集模块设计
信号采集部分主要由温度传感器DS18B20进行
1.DS1820温度传感器外观图和引脚图如图9所示,三个管脚定义如下:[10]
① 引脚1接地;
② 引脚2数字信号输入/输出;
③ 引脚3接高电平5V高电平。
2.DS18B20温度采集模块设计[10]
此模块的设计中STC89C52单片机作为控制主体,温度传感器DS18B20采集温度,
温度传感器DS18B20是一种单线接口传感器,所以连接电路很简单,只要将其管脚DQ接单片机的一个端口进行温度采集,VDD接高电平,GND接地即可。设计中的DQ端被设计成连接单片机的P1.3端口。
根据DS18B20的工作原理、内部结构图、时序图,还有DS18B20的ROM指令操作码,编写DS18B20的操作代码,采集温度样本,将采集的样本数据存放在寄存器中等待下一步处理。


3.4无线收发模块设计
无线收发模块的功能实现主要是用nRF905无线收发模块实现的
1.nRF905接口电路和管脚说明[9]

图11 nRF905管脚图

(1)VCC为电源接入端,一般接入的电压在3.3V-3.6V之间,不能超过3.6V,不然很容易将模块烧坏,建议使用3.3V
(2)TX_EN为数字输入端口,当TX-_EN置1时为TX输入模式,当TX-_EN置0时为RX输入模式
(3)TRX_CE也是数字输入端,它控制使能芯片的发射和接收
(4)PWR_UP是给芯片上电的数字输入端口
(5)uCLK为时钟输出端口,此管脚在使用过程中一般废弃不用
(6)CD数字输出端进行载波检测
(7)AM数字输出端进行地址匹配
(8)DR数字输出端,接收和发送数据完成
(9)MISO和MOSI分别为SPI输出输入端口
(10)SCK和CSN分别为SPI的时钟和使能端口
(11)13和14管脚为相同的二个接地端口.
2.nRF905无线收发模块设计
该模块的设计中使用到了AMS1117芯片,目的是将上电端口输入的5V电压转换成适合nRF905模块使用的3.3V工作电压,转换电路中由于使用的是AMS1117芯片,所以设计简单许多,只需要在芯片的输入端和接地端之间,输出端和接地端之间分别并联上一个普通电容和一个极性电容即可,电路设计如图12所示:
图12 AMS1117变压电路
芯片AMS1117输出的电压与无线收发模块的VCC口连接,PWR_UP,TX-_EN,TRX_CE,MISO,MOSI,SCK,CSN分别对应单片机的P1.0,P1.1,P1.2,P1.4,P1.5,P1.6,P1.7端口,AM,DR,CD分别对应单片机的P3.2,P3.3,P3.4端口,uCLK端口废弃不用,最后的两个GND端口全部接地,这样就组成了nRF905的无线控制模块。可以进行程序的调控使用了。
nRF905模块的无线发射接收电路主要利用nRF905与外围器件构成的电路组成,设计中使用的是购买的成品模块,其内部电路结构没有详细研究,其主要部分是天线。他利用特定的形状可以将电流转化为射频能量并以电波形式发射出去.或将无线电波接收进来。
第四章 系统软件设计4.1 程序设计思路
程序设计使用的软件是是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统Keil C51。与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
程序设计过程中,首要的是会熟练使用各种数码管,即要了解数码管的构造,也要了解其工作原理,并且能够编写各种数码管的显示程序,当能够做到这一步,然后还要了解温度传感器的内部结构和工作原理,还有寄存器的工作方式和读写时序图,然后根据它的ROM和RAM指令编写工作代码,通过单片机读取后控制数码管显示。
编写DS18B20的操作代码时,先初始化传感器,然后分别读它的位和比特,然后是写比特,然后开始主要的转换过程程序设计,转换时要判断正负,如果为负值,则取其值的反码后加1,得到正值,然后在前面显示“-”号,最后设计单片机控制读取DS18B20的寄存器数据,通过数码管显示。
设计了温度显示程序后开始设计无线发送程序,同样的需要了解nRF905的结构,工作原理寄存器和时序图,还有SPI口的设置。设计程序时,一般先给寄存器配置参数,通过SPI口想配置寄存器读写配置信息。然后编写它的写操作和读操作代码,主机通过SPI接口向配置寄存器写入信息,最后是它的发送指令代码。
在编写接收代码程序时,和发送的代码过程相似,参考后面的程序附录。
4.2 程序流程图
温度采集模块的程序设计要特别注意温度传感器DS18B20的代码编写,在充分了解很清楚DS18B20的基础上根据其指令码,寄存器等编写其读写指令,以及温度处理转换代码,然后编写数码管的显示程序,然后合并,构成总的程序流程。Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。其中uVision与Ishell分别是C51为Windows和Dos的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。使用简单方便。
设计的数据采集模块具体流程图15所示:



图15 数据采集流程图


温度采集时是,首先将DS18B20进行初始化设置,然后才能进行后面的操作。这也是使用各种传感器设备的最基本步骤,然后是根据先前编写的温度传感器代码读取传感器采集的温度数据,存储在其寄存器中,然后进行控制转换程序。如果采集的温度是正值,那么就控制单片机直接读取经NRF905发送。如果温度数据是负值,那么要进行取反加一后变成正值数据再通过无线设备发送出去。

无线发送流程图如图16所示:








图16 无线发送流程图


初始化nRF905,将接收点的地址和要发送的有效数据将通过SPI接口传送给nRF905。将TRX-CE和TX-EN全部置为高电平来激活nRF905的ShockBurst的发送模式。通过nRF905的ShockBurst可使射频寄存器自动开启,并完成数据包的发送,DR置高。

然后判断TRX-CE电平,如果置低将返回初始不进行后面的操作,如果置高,那么将AUTO-RETRAN也设置为高电平,从而使nRF905将连续不断地重复发送数据包,直到TRX-CE被设置为低电平为止;而当TRX-CE被设置为低电平时,DR=0,nRF905则结束数据传输,并将自己设置为空闲模式。

在ShockBurst模式下,只要开始发送数据,TRX-CE和TX-EN的引脚无论是高电平还是低电平,发送过程都会被保证处理完毕。  


无线接收流程图如图17所示:












图17 无线接收流程图

首先,将TRX-CE置为高,TX-EN置为低,nRF905进入接收模式,然后不断监测有无信号,等待接收;当nRF905检测到有和接收频率相同的载波时,其载波检测引脚CD置为高电平;此后,当nRF905接收到相匹配的地址时,地址匹配引脚AM置为高电平;在这之后,当nRF905接收完毕一个有效的数据包(CRC校验正确)时,nRF905将去掉前导码、地址和CRC位,同时将数据准备就绪引脚DR置为高电平,并用单片机将TRX-CN引脚设置为低电平,以进入空闲模式,从而使单片机能够通过SPI接口读出有效的数据;当所有的数据读出后,nRF905将AM和DR设置为低电平,以便使nRF905准备进入其它工作模式。

第五章 系统仿真与硬件调试5.1系统仿真

系统的仿真过程是使用proteus仿真软件进行,由于在proteus软件中找不到NRF905的仿真模块,所以仿真过程中没有实现无线收发的仿真电路,只是进行了温度检测和显示过程的仿真操作。仿真图如图18所示:









图18 温度采集仿真图

5.2 系统硬件调试

系统硬件的制作过程全部在学校实验室完成,在制作条件上受到一定的限制。在制作PCB电路板的过程中,由于打孔机上的打孔针只有一种直径的,所以导致过孔和焊接点的孔径大小一样,焊接时要特别注意分清。因为制作的过孔之间是没有伏铜,连接过孔的两层导线是不相通的,需要手工进行焊接,千万不可漏焊。所以在硬件的调试过程要注意过孔的问题。另外,在制作电路电路板时,使用的是腐蚀刻线,很容易出现断线现象,所以在焊接器件之前最好将断线全部焊接好,避免断线导致调试过程的不正常现象,因为焊接后电路板上的断线不容易补焊。

              在电路板的设计过程中要尽量在底层布线,同样是因为孔内没有加铜的原因,如果是顶层走线,就需要在顶层焊接,而顶层焊接时遇到像数码管之类的器件的管脚很难在正面焊接,即使焊接也很容易出现虚焊现象,导致接触不良。

              在调试过程中,我的电路板出现了正面布线焊接时出现短路和断路现象,导致串口无法使用,模块供电不正常等现象,最后经过使用万用表仔细的检测后才找出原因,过程繁琐异常。

              调试过程主要就是一个检测过程,一定要有耐心,够仔细,不然很难找出问题的根本原因。所以在电路PCB板的设计过程中,腐蚀刻线过程中,焊接电路板时都需要认真仔细对待,尽量减少因为硬件导致模块功能不正常的问题出现,但同时,电路板出现问题的调试过程也是一个很好学习和经验积累过程,一定要认真对待,自己找原因,不要总是让别人代劳。

5.3 调试结果

经过不断认真的调试过程,且电路的设计也没有任何问题,最后电路板终于能够完全实现预先设计的所有功能。

第六章 心得与体会

经过一个星期的现代检测技术课程设计,我们小组成功地完成了无线温度检测系统的设计。虽然整个设计中我们遇到了很多问题,但通过我们自己九个人的分工,查找资料,调试、仿真,不断地调整设计思路,最终成功地完成了设计目标。这次课程设计让我自己对于学习现代检测技术有了更深一步地了解,通过实际地操作,发现书上的理论知识与在实际运用中的还是有一定的出入的。经过自己不断地摸索,改进,从中学到了很多实际知识。

整个设计制作中也培养了我的实际操作能力和团队合作能力,不仅加强了自己独立工作地能力,而且还充分地体会到了设计创作地艰辛,看到制作完成时也体会到了成功地喜悦,收获了不少课外知识。还有要感谢李老师以及杨老师在我们遇到困难时,给予我们的建议与鼓励。

设计过程中感受最深的就是编写程序后的调试过程,确实是一个漫长而痛苦的过程。我们根据显示的结果不断寻找错误点,各个击破。虽然很累(每天都熬夜),但是当程序跳出来之后,心中的喜悦是不言而喻的,不管之前多么的痛苦都是值得的!

通过此次课程设计,我总结了几点:

①每一个系统的生成,都是经过层层周密的思考与测试而得到的,这需要团队的合作以及个人优秀的素质。

②写程序过程中,切记戒骄戒躁,踏踏实实,一步一个脚印。学会模块化编程,会让你少走很多弯路。

③当程序很多很复杂时,应该写一个模块就调试一个,这样下来会轻松的解决各个问题,而不像你一次性全写完,错了之后再来调就很复杂了。

④硬件电路的调试,也是需要极大的耐性,以及拥有良好的电子基础,这个需要多加练习。

再次感谢我们的李老师.,老师严谨细致、一丝不苟的作风一直是我工作、学习中的榜样;老师循循善诱的教导和不拘一格的思路给予我无尽的启迪;这次课程设计中离不开老师您的细心指导。而您开朗的个性和宽容的态度,帮助我能够很顺利的完成了这次课程设计。

   同时感谢对我帮助过的同学们,谢谢你们对我的帮助和支持,让我感受到同学的友谊。




附录一:原理图




上位机Labview数据显示程序
前面板
后面板labview程序

  1. //*************此程序为nRF905的发送程序***********
  2. #include <reg52.h>
  3. #include <intrins.h>
  4. #define uchar unsigned char
  5. #define uint  unsigned int

  6. //*******************定义命令字**********************
  7. #define WC 0x00  // Write configuration register command
  8. #define RC 0x10   // Read configuration register command
  9. #define WTP 0x20   // Write TX Payload  command
  10. #define RTP 0x21  // Read TXPayload  command
  11. #define WTA 0x22  // Write TX Address  command
  12. #define RTA 0x23

  13. //*******************管脚配置*********
  14. sbit              TXEN=P1^0;
  15. sbit              TRX_CE=P1^1;
  16. sbit              PWR=P1^2;
  17. sbit              MISO=P1^4;
  18. sbit              MOSI=P1^5;
  19. sbit              SCK=P1^6;
  20. sbit              CSN=P1^7;
  21. /////////////////////////////////////////////////////
  22. sbit              AM=P3^3;
  23. sbit              DR=P3^4;
  24. sbit              CD=P3^2;
  25. sbit DQ=P1^3;
  26. //uchar Txbuf[4];
  27. uchar display[5]={0x00,0x00,0x00,0x00,0x00};              //前面4字节是要发送的内容
  28. //从前往后是温度数据低位到高位
  29. // 温度小数部分查表
  30. uchar code ditab[16]=
  31. {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
  32. uint     h;
  33. uchar flag;
  34. //rf905控制信息
  35. uchar Rfconfig[10]={0x4c,0x0c,0x44,0x04,0x04,0xe7,0xe7,0xe7,0xe7,0x58};
  36. uchar data temp_data[2]={0x00,0x00};  

  37. void delay(uint x)
  38. {
  39. uint i;
  40. for(i=0;i<x;i++)
  41. {
  42.   _nop_();
  43. }
  44. }

  45. //18b20相关函数
  46. /***********18B20复位函数**********/
  47. void ow_reset(void)
  48. {
  49. char presence=1;
  50. while(presence)
  51. {
  52. while(presence)
  53. {
  54. DQ=1;_nop_();_nop_();
  55. DQ=0;    //
  56. delay(50); // 550us
  57. DQ=1;    //
  58. delay(6); // 66us
  59. presence=DQ; // presence=0继续下一步
  60.    }
  61. delay(45);    //延时500us
  62. presence = ~DQ;
  63. }
  64. DQ=1;
  65. }

  66. /**********18B20写命令函数*********/
  67. //向 1-WIRE 总线上写一个字节
  68. void write_byte(uchar val)
  69. {
  70. uchar i;
  71. for (i=8; i>0; i--) //
  72. {
  73. DQ=1;_nop_();_nop_();
  74. DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
  75. DQ = val&0x01;      //最低位移出
  76. delay(6);           //66us
  77. val=val/2;          //右移一位
  78. }
  79. DQ = 1;
  80. delay(1);
  81. }

  82. /*********18B20读1个字节函数********/
  83. //从总线上读取一个字节
  84. uchar read_byte(void)
  85. {
  86. uchar i;
  87. uchar value = 0;
  88. for (i=8;i>0;i--)
  89. {
  90. DQ=1;_nop_();_nop_();
  91. value>>=1;
  92. DQ = 0;             //
  93. _nop_();_nop_();_nop_();_nop_();   //4us
  94. DQ = 1;_nop_();_nop_();_nop_();_nop_();   //4us
  95. if(DQ)value|=0x80;
  96. delay(6);           //66us
  97. }
  98. DQ=1;
  99. return(value);
  100. }

  101. /***********读出温度函数**********/
  102. void read_temp()
  103. {
  104. ow_reset();       //总线复位
  105. write_byte(0xCC); // 发Skip ROM命令
  106. write_byte(0xBE); // 发读命令
  107. temp_data[0]=read_byte(); //温度低8位
  108. temp_data[1]=read_byte(); //温度高8位
  109. ow_reset();
  110. write_byte(0xCC); // Skip ROM
  111. write_byte(0x44); // 发转换命令
  112. }

  113. /***********温度数据处理函数**********/
  114. void work_temp()
  115. {
  116. uchar n=0;
  117. uchar doth,dotl;
  118. uchar flag3=1,flag2=1;       //数字显示修正标记
  119. if((temp_data[1]&0xf8)!=0x00)
  120. {
  121.    temp_data[1]=~(temp_data[1]);
  122.    temp_data[0]=~(temp_data[0])+1;
  123.    n=1;
  124.    flag=1;
  125. }//负温度求补码
  126. if(temp_data[0]>255)
  127. {
  128. temp_data[1]++;
  129. }
  130. display[4]=temp_data[0]&0x0f;
  131. display[0]=ditab[display[4]];
  132. doth=display[0]/10;
  133. dotl=display[0]%10;
  134. display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4);
  135. display[3]=display[4]/100;
  136. display[2]=display[4]/10%10;
  137. display[1]=display[4]%10;
  138. if(!display[3])
  139.    {
  140.     display[3]=0x0a;
  141.     flag3=0;
  142.     if(!display[2])
  143.     {
  144.      display[2]=0x0a;
  145.      flag2=0;
  146.     }
  147.    }//最高位为0时都不显示
  148. if(n)
  149. {
  150.    display[3]=0x0b;//负温度时最高位显示"-"
  151.    flag3=0;
  152. }
  153. }
  154. //905相关函数
  155. void Spiwrite(uchar dat)
  156. {
  157. uchar i=8;
  158. while(i--)
  159. {
  160. delay(10);
  161. SCK=0;
  162. MOSI=(bit)(dat&0x80);
  163. dat<<=1;
  164. delay(10);
  165. SCK=1;
  166. delay(10);
  167. SCK=0;
  168. }
  169. SCK=0;
  170. }

  171. void Txpacket(void)
  172. {
  173. TXEN=1;
  174. CSN=0;
  175. Spiwrite(0x22);
  176. Spiwrite(0xe7);
  177. Spiwrite(0xe7);
  178. Spiwrite(0xe7);
  179. Spiwrite(0xe7);
  180. CSN=1;
  181. _nop_();_nop_();
  182. CSN=0;
  183. Spiwrite(0x20);
  184. Spiwrite(display[0]);
  185. Spiwrite(display[1]);
  186. Spiwrite(display[2]);
  187. Spiwrite(display[3]);
  188. CSN=1;
  189. _nop_();_nop_();
  190. TRX_CE=1;
  191. delay(50);
  192. while(!DR);
  193. TRX_CE=0;
  194. }

  195. void ini_system(void)
  196. {
  197. uchar i;
  198. CSN=1;
  199. SCK=0;
  200. PWR=1;   //   PWR_UP  | TRX_CE |TXEN | M O D E
  201. TRX_CE=0;  // 1    |   0    |  0 | SPI Programming
  202. TXEN=0;
  203. _nop_();
  204. CSN=0;
  205. Spiwrite(0x00);
  206. for(i=0;i<10;i++)
  207. {
  208. Spiwrite(Rfconfig[i]);
  209. }
  210. CSN=1;
  211. }
  212. void setmode()
  213. {
  214. PWR=1;  //   PWR_UP  TRX_CE   TXEN      MODE
  215. TRX_CE=1; //      1        1     1 SHOCKBURST TX
  216. TXEN=1;
  217. delay(1000); //time must be >=650us
  218. }

  219. void nRF905Init(void)
  220. {
  221.     CSN=1;                                                                                    // Spi               disable
  222.               SCK=0;                                                                                    // Spi clock line init low
  223.               DR=1;                                                                                    // Init DR for input
  224.               AM=1;                                                                                    // Init AM for input
  225.               CD=1;                                                                                    // Init CD for input
  226.               PWR=1;                                                                      // nRF905 power on
  227.               TRX_CE=0;                                                                      // Set nRF905 in standby mode
  228.               TXEN=0;                                                                      // set radio in Rx mode
  229. }
  230. void main()
  231. {
  232. ow_reset();       // 开机先转换一次
  233. write_byte(0xCC); // Skip ROM
  234. write_byte(0x44); // 发转换命令
  235.               nRF905Init();
  236. ini_system();
  237. while(1)
  238. {
  239. read_temp();         //读出18B20温度数据
  240. work_temp();         //处理温度数据
  241. setmode();
  242. delay(100);
  243. Txpacket();
  244. delay(1000);
  245. }
  246. }

  247. 接收部分程序:
  248. /*****接收时用数码管显示接收到的数据**********/
  249. #include <reg52.h>
  250. #include <intrins.h>
  251. #define uchar unsigned char
  252. #define uint  unsigned int
  253. #define disdate P0                //段码输出口
  254. #define discan P2                //扫描口

  255. //############################################
  256. //数码管显示部分
  257. uchar dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
  258. //共阳LED段码表        "0"  "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" "不亮" "-"  
  259. uchar dis_can[4]={0xfe,0xfd,0xfb,0xf7};//列选代码
  260. #define WC 0x00  
  261. #define RC 0x10   
  262. #define WTP 0x20   
  263. #define RTP 0x21  
  264. #define WTA 0x22  
  265. #define RTA 0x23  
  266. #define RRP 0x24
  267. sbit              TXEN=P1^0;
  268. sbit              TRX_CE=P1^1;
  269. sbit              PWR=P1^2;
  270. sbit              MISO=P1^4;
  271. sbit              MOSI=P1^5;
  272. sbit              SCK=P1^6;
  273. sbit              CSN=P1^7;
  274. /////////////////////////////////////////////////////
  275. sbit              AM=P3^3;
  276. sbit              DR=P3^4;
  277. sbit              CD=P3^2;

  278. sbit DP=P0^7;
  279. unsigned char Rxbuf[4]={0x00,0x00,0x00,0x00};
  280. unsigned char Rfconfig[10]=
  281. {0x4c,0x0c,0x44,0x04,0x04,0xe7,0xe7,0xe7,0xe7,0x58};
  282. void delay110(uint z)
  283. {              uchar x;
  284.               uint y;
  285.               for(x=0;x<=110;x++)
  286.                             for(y=0;y<=z;y++);
  287. }
  288. void delay(uint x)
  289. { uint i;
  290. for(i=0;i<x;i++)
  291. {
  292.   _nop_();
  293. }
  294. }

  295. void Spiwrite(uchar dat)
  296. {uchar i=8;
  297. for(i=0;i<8;i++)
  298. {
  299. delay(10);
  300. SCK=0;
  301. MOSI=(bit)(dat&0x80);
  302. dat<<=1;
  303. delay(10);
  304. SCK=1;
  305. delay(10);
  306. SCK=0;
  307. }
  308. SCK=0;
  309. }

  310. unsigned char Spiread(void)
  311. {
  312. uchar i=8;
  313. uchar ddat;
  314. for(i=0;i<8;i++)
  315. {
  316. ddat<<=1;
  317. SCK=0;
  318. _nop_();
  319. _nop_();
  320. ddat|=MISO;
  321. SCK=1;
  322. _nop_();_nop_();
  323. }
  324. SCK=0;
  325. return ddat;
  326. }
  327. void Rxpacket(void)
  328. {
  329. unsigned char j=0;
  330. delay110(50);
  331. TRX_CE=0;
  332. PWR=1;
  333. CSN=0;
  334. delay(1);
  335. Spiwrite(RRP);
  336. for(j=0;j<4;j++)
  337. {
  338. Rxbuf[j]=Spiread();
  339. }
  340. CSN=1;
  341. delay110(5);
  342. //              TRX_CE=1;                                                                      // Set TRX_CE high,start Tx data transmission
  343. }

  344. void ini_system(void)
  345. {
  346. uchar i;
  347. CSN=1;
  348. SCK=0;
  349. PWR=1;   //   PWR_UP  | TRX_CE |TXEN | M O D E
  350. TRX_CE=0;  // 1    |   0    |  0 | SPI Programming
  351. TXEN=0;
  352. _nop_();
  353. CSN=0;
  354. Spiwrite(WC);
  355. for(i=0;i<10;i++)
  356. {
  357. Spiwrite(Rfconfig[i]);
  358. }
  359.   CSN=1;
  360. }
  361. void setmode()
  362. {
  363. PWR=1;  //   PWR_UP  TRX_CE   TXEN      MODE
  364. TRX_CE=1; //      1        1     0 SHOCKBURST RX
  365. TXEN=0;
  366. delay(500); //time must be >=650us
  367. }

  368. /***********显示扫描函数**********/
  369. void scan()
  370. {
  371. char k;
  372.     for(k=0;k<4;k++)         //四位LED扫描控制
  373.      {
  374.               disdate=0xff;
  375.       disdate=dis_7[Rxbuf[k]];
  376.       if(k==1){DP=0;}
  377.       discan=dis_can[3-k];delay(90);
  378.                 discan=0xff;
  379.      }
  380. }

  381. void nRF905Init(void)
  382. {
  383.     CSN=1;                                                                                    // Spi               disable
  384.               SCK=0;                                                                                    // Spi clock line init low
  385.               DR=1;                                                                                    // Init DR for input
  386.               AM=1;                                                                                    // Init AM for input
  387.               CD=1;                                                                                    // Init CD for input
  388.               PWR=1;                                                                      // nRF905 power on
  389.               TRX_CE=0;                                                                      // Set nRF905 in standby mode
  390.               TXEN=0;                                                                      // set radio in Rx mode
  391. }

  392. unsigned char CheckDR(void)                            //检查是否有新数据传入 Data Ready
  393. {
  394.               if (DR==1&&TRX_CE==1&&TXEN==0)
  395.               {
  396.        // Delay(50)  ;
  397.                             return 1;
  398.               }
  399.               else
  400.               {
  401.                             return 0;
  402.               }
  403. }
  404. uchar m;
  405. uint n;

  406. void main()
  407. {
  408. nRF905Init();
  409.   ini_system();
  410. while(1)
  411. {                           
  412.    setmode();
  413. while (CheckDR()==0);
  414. //                delay(10);
  415.   Rxpacket();
  416. //              delay(1);
  417.   while(DR==1)
  418.   {
  419.   for(m=0;m<=1;m++)
  420. {
  421.               scan();
  422. }
  423.   }
  424. //delay110(2);
  425. for(m=0;m<=100;m++)
  426. {
  427.               scan();
  428. }
  429. }
  430. }
复制代码

完整的Word格式文档51黑下载地址:
基于51单片机系统的温度检测与无线收发设计.doc (1.23 MB, 下载次数: 26)


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

使用道具 举报

沙发
ID:585189 发表于 2019-7-16 17:18 | 只看该作者
无线用的这个没学过 nRF905
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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