基于51单片机及DS18B20温度传感器的数字温度计设计
zkreate摘要
本设计采用的主控芯 片是 ATMEL公司的ATS52单片机,数字 温度传感器 是
DALLAS公司的DS18B20。本设计用数字传感器DS18B20测量温度,测量精度高,传感器体积小,使用方便。所以本次设计的数字温度计在工业、农业、日常生活中都有广泛的应用。
单片机技术已经广泛应用社会生活的各个领域,已经成为一种非常实用的技术。 51单片机是最常用的一种单片机,而且在高校中都以51单片机教材为蓝本,这使得51单片机成为初学单片机技术人员的首选。本次设计采用的 ATS52是一种flash型单片机,可以直接在线编程,向单片机中写程序变得更加容易。本次设计的数字温度计采用的是DS18B20数字温度传感器,DS18B20是一种可组网的高精度数字式温度传感器,由于其具有单总线的独特优点,可以使用户轻松地组建起传感器网络,并可使多点温度测量电路变得简单、可靠。
本设计根据设计要求,首先设计了硬件电路,然后绘制软件流程图及编写程序。本设
计属于一种多功能温度计,温度测量范围是-55C到125C。温度值的分辨率可以被用户设定为 9-12 位,可以设置上下限报警温度,当温度不在设定的范围内时,就会启动报警程序报警。本设计的显示模块是 用四位一体的数码管动态扫描显示实现的。在显示实时测量温度的模式下还可以通过查询按键查看设定
的上下限报警温度。
关键词:单片机、数字温度计、DS18B20、ATS52
目录
1概述-1 -
1.1系统概述-1 -
2系统总体方案及硬件设计-2 -
2.1系统总体方案-2 - 2.1.1系统总体设计框图-2 - 2.1.2各模块简介-2 - 2.2系统硬件设计-5 -
2.2.1单片机电路设计-5 -
2.2.2DS18B20 温度传感器电路设计
2.2.3显示电路设计-6 -
2.2.4按键电路设计-7 -
2.2.5报警电路设计-8 -
3软件设计-9 -
3.1DS18B20 程序设计-9 -
3.1.1DS18B20 传感器操作流程-9
3.1.2DS18B20 传感器的指令表-9
3.1.3DS18B20 传感器的初始化时序 -10
3.1.4DS18B20 传感器的读写时序- -
3.1.5DS18B20 获取温度程序流程图 10-
3.2显示程序设计-12 - -11
3.3按键程序设计-13 - -
4 实物制作及调试 - 14 -
5电子综合设计体会 - 15 -参考文献 - 15 - 附1 源程序代码 - 17 - 附2 系统原理图 - 32 -
1概述
1.1系统概述
本系统所设计的数字温度计采用的是DS18B20数字温度传感器测温,DS18B20直接输出的就是数字信号,与传统的温度计相比,具有读数方便,测温范围广,测温准确,上下限报警功能。其输出温度采用 LED数码管显示,主要用于对测温比较准确的场所。
该设计控制器使用的是51单片机ATS52,ATS52单片机在工控、测量、仪器仪表 中应用还是比较广泛的。测温传感器使用的是 DS18B20,DS18B20是一种可组网的高精度数字式温度传感器,由于其具有单总线的独特优点,可以使用户轻松地组建起传感器网络,并可使多点温度测量电路变得简单、可靠。显示是用4位共阴极LED数码管实现温度显示,LED数码管的优点是显示数字比较大,查看方便。蜂鸣器用来实现当测量温度超过设定的上下限时的报警功能。
- 1 - / 35
2系统总体方案及硬件设计
2.1系统总体方案
2.1.1系统总体设计框图
由于DS18B20数字温度传感器具有单总线的独特优点,可以使用户轻松地组建起传感器网络,并可使多点温度测量电路变得简单、可靠,所以在该设计中采用 DS18B20数字温度传感器测量温度。
温度计电路设计总体设计框图如图2-1所示,控制器采用单片机ATS52,温度传感器采用DS18B20,显示采用4位LED数码管,报警采用蜂鸣器、LED灯实现,键盘用来设定报警上下限温度。
图2-1 温度计电路总体设计框图
2.1.2各模块简介
1?控制模块
系统编程的Flash 只读程序存储器,器件采用ATMEL 公司的高密度、非易失性存储技术生产,兼容标
ATS52 单片机是美国ATMEL公司生产的低功耗,高性能 CMOS8 位单片机,片内含 有8kb的可
准8051指令系统及引脚。在单芯片上,拥有灵巧的8位CPU和在系统可编程的Flash,使得ATS52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
ATS52具有以下标准功能:8k字节Flash,256 字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外, ATS52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
2.显示模块
显示电路采用4位共阴LED数码管,从P0口输出段码,P2口的高四位为位选端。用动态扫描的方式进行显示,这样能有效节省 I/O口。
3.温度传感器模块
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9?12位的数字值读数方式。DS18B20的性能特点如下:独特的单线接口仅需要一个端口引脚进行通信;多个 DS18B20可以并联在惟一的三线上,实现多点组网功
能;无须外部器件;可通过数据线供电,电压范围为 3.0?5.5v;零待机功耗;温度以9或12位二进制数字表示;用户可定义报警设置;报警搜索命令识别并标志超过程序限定温度
<温度报警条件)的器件;负电压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作; DS18B20采用3脚TO— 92 封装或8脚SO或pSOP封装,其其封装形式如图2-2所示0
|
|
|
| |
| BOnWEMElV: |
| □NC | S-Pui pSOP |
TOL92 | ||||
(DSISB20) | S Pin 150UHISO GND | |||
(DS1SB20U) | ||||
(DS1SB20Z) | ||||
图2-2 DS18B20 的封装形式 | ||||
位,最后8 位是前面56 位的CRC 检验码,这也是多个 DS18B20 可以采用一 线进行通信的原因。温度报 | ||||
警触发器TH和TL,可通过软件写入户报警上下限。
DS18B20温度传感器的内部存储器还包括一个高速暂存 RAM和一个非易失性的可电擦除的EEPRAM。高速暂存RAM的结构为8字节的存储器,结构如图2-3所示。
-3- / 35
SCRATCHPAD | BYTE | E'RAM |
rEMPERAILKE LSB | |
|
TEMPERATLTE MB | ||
TH/USERBYTE 1 | ||
TVUSER BYTE 2 | ||
CONFIG | | |
RESERVED | ||
RESERXTD | ||
RESERXTD | ||
CRC | ||
图2-3 DS18B20 的高速暂存RAM 的结构 | ||
表2-1:配置寄存器
D7 | D6 D5 D4 D3 | D2 | D1 | D0____________________________________ | |||||
TM | | R1 | ] R0 | | 1 | | | 1 | | | 1 丨 1 | | | 1 |
配置寄存器的低5位一直为1,TM是工作模式位,用于设置DS18B20在工作模式还是在测试模式,DS18B20出厂时该位被设置为0,用户要去改动,R1和R0决定温度转换的精度位数,来设置分辨率,“ R1R0”为“00”是9位,“01”是10位,“10”是11位,
“11”是12位。当DS18B20分辨率越高时,所需要的温度数据转换时间越长。因此,在实际应用中要将分辨率和转换时间权衡考虑。
高速暂存RAM的第6、7、8字节保留未用,表现为全逻辑1。第9字节读出前面所有8字节的CRC码,可用来检验数据,从而保证通信数据的正确性。
16位带当DS18B20接收到温度转换命令后,开始启动转换。转换完成后的温度值就以
符号扩展的二进制补码形式存储在高速暂存存储器的第口读出该数据,读数据时低位在先,高位在后,数据格式以
1、2字节。单片机可以通过单线接 0.0625C/LSB形式表示。
当符号位s=0时,表示测得的温度值为正值,可以直接将二进制位转换为十进制;当符号位s=1时,表示测得的温度值为负值,要先将补码变成原码,再计算十进制数值。输出的二进制数的高5位是符号位,最后4位是温度小数点位,中间7位是温度整数位。表2-2 是一部分温度值对应的二进制温度数据。
表2-2DS18B20输出的温度值
温度值 | 二进制输出 | 十六进制输出 |
+125C | 0000 0111 1101 0000 : | 07D0h |
+85 C | 0000 0101 0101 0000 | 0550h |
+25.0625C | 0000 0001 1001 0001 1 | 0191h |
+10.125C | 0000 0000 1010 0010 | 00A2h |
+0.5C | 0000 0000 0000 1000 | 0008h |
0C | 0000 0000 0000 0000 | 0000h |
-05C | 1111 1111 1111 1000 | FFF8h |
-10.125C | 1111 1111 0101 1110 | FF5Eh |
-25.0625C | 1111 1110 0110 1111 | FF6Fh |
-55 C | 1111 1100 1001 0000 | FC90h |
DS18B20 完成温度转换后,就把测得的温度值与RAM 中的TH、TL字节内容作比较。 若T>TH或TVTL,贝U将该器件内的报警标志位置位,并对主机发出的报警搜索命令作出响应。因此,可用多只 DS18B20 同时测量温度并进行报警搜索。在 位ROM 的最高有效字节中存储有循环冗余检验码 <CRC)。主机ROM的前56 位来计算CRC值,并和存入 DS18B20 的CRC值作比较,以判断主机收到的ROM 数
4. 调节模块介绍 据是否正确。
调节模块是由四个按键接地后直接接单片机的I/O口完成的。当按键没有按下时单片机
管脚相当于悬空,默认下为高电平,当按键按下时相当于把单片机的管脚直接接地,此时为低电平。程序设计为低电平触发。
5.报警模块介绍
报警模块是由一个PNP型的三极管9012驱动的5V蜂鸣器,和一个加一限流电阻的发光二极管组成的。报警时蜂鸣器间歇性报警,发光二极管闪烁。
2.2系统硬件设计
2.2.1单片机电路设计
*a-
—
….—
图2-4单片机最小系统原理图
单片机最小系统是由晶振电路,上电复位、按键复位电路, ISP下载接口和电源指示灯
组成。原理图如图2-4 所示。
DS18B20 温度传感器是单总线器件与单片机的接口电路采用电源供电方。2.2.2DS18B20 温度传感器电路设计
电源供电方式如图2-7,此时DS18B20的1脚接地,2脚作为信号线,3脚接电源。
图2-7DS18B20电源供电方式
当DS18B20处于写存储器操作和温度A/D转换操作时,总线上必须有强的上拉,上拉开启时间最
大为10us。采用寄生电源供电方式时VDD端接地。由于单线制只有一根线,因此发送接口必须是三态
的。
2.2.3显示电路设计
显示电路是由四位一体的共阴数码管进行显示的,数码管由三极管 9013驱动。
四位一体的共阴数码管的管脚分布图如图2-5所示
图2-5四位一体的共阴数码管管脚分布图显示电路的总体设计如图2-6所示。
TO |
|
|
|
| ||||||
PO.D | o 口址區出口 | |||||||||
1 | ||||||||||
P0.1 | ||||||||||
K2 |
Pj4
rol
P0.6 | |
图2-6显示电路
2.2.4按键电路设计
按键电路是用来实现调节设定报警温度的上下限和查看上下报警温度的功能。电路原理图如图2-10所示。
图2-10按键电路原理图
报警电路是在测量温度大于上限或小于下限时提供报警功能的电路。该电路是由一个2.2.5 报警电路设计
蜂鸣器和一个红色的发光二极管组成,具体的电路如图 2-9所示。
图2-9报警电路原理图
3软件设计3.1DS18B20 程序设计
3.1.1DS18B20 传感器操作流程
根据DS18B20的通讯协议,主机<单片机)控制DS18B20完成温度转换必须经过三个步骤:? 每一次读写之前都要对DS18B20进行复位操作
? 复位成功后发送一条ROM指令
? 最后发送RAM指令
这样才能对DS18B20进行预定的操作。复位要求主CPU将数据线下拉500卩s,然后释放,当DS18B20收到信号后等待16?60卩s左右,后发出60?240卩s的存在低脉冲,主CPU收到此信号表示复位成功。
DS18B20的操作流程如图3-1所示。
如图3-1DS18B20 的操作流程
3.1.2DS18B20 传感器的指令表
DS18B20传感器的操作指令如表3-1所示。传感器复位后向传感器写相应的命令才能实现相应的 功能。
表3-1DS18B20的指令表
指令 | 指令代码 | 功能 |
读ROM | 0x33 | 读DS1820 温度传感器ROM 中的编码 <即 位地 址) |
符合ROM | 0x55 | 发出此命令之后,接着发出 位ROM 编码,访问 单总线上与该编码相对应的 DS1820 使之作出响应, 为下一步对该DS1820 的读写作准备。 |
搜索ROM | 0xF0 | 用于确定挂接在同一总线上DS1820 的个数和识别 位ROM 地址。为操作各器件作好准备。 |
3.1.3 DS18B20 传感器的初始化时序 |
DS18B20的初始化时序如图3-2所示。首先控制器拉高数据总线,接着控制器给数据总线一低电
平,延时480卩s,控制器拉高数据总线,等待传感器给数据线一个60-240卩s的
低电平,接着上拉电阻将数据线拉高,这样才初始化完成。
LINE TYPE LEGEND Bus |
pulling 曲 |
OS16B20 pulinglow
------ pulup
图3-2DS18B20初始化时序
3.1.4DS18B20 传感器的读写时序
1.写时序
DS18B20传感器的读写操作是在传感器初始化后进行的。每次操作只能读写一位
当主机把数据线从高电平拉至低电平,产生写时序。有两种类型的写时序:写“ 0”时
序,写“1”时序。所有的时序必须有最短60[1s的持续期,在各个写周期之间必须有最短1卩s的
恢复期。
在数据总线由高电平变为低电平之后,DS18B20在151s 至601s 的时间间隙对总线采样,如果
为“1”则向DS18B20写“1”,如果为“0”则向DS18B20写“0”。如图3-2的上半部分。
对于主机产生写“1”时序时,数据线必须先被拉至低电平,然后被释放,使数据线在写时序开始
之后151s 内拉至高电平。
对于主机产生写“1”时序时,数据线必须先被拉至低电平,且至少保持低电平 601
2.读时序
在数据总线由高电平变为低电平之后,数据线至少应保持低电平11s,来自DS18B20
的输出的数据在下降沿151s 后有效,所以在数据线保持低电平11 s 之后,主机将数据线拉高,等待
来自DS18B20的数据变化,在下降沿151s 之后便可开始读取DS18B20的输出数据。整个读时序必须有
最短601s 的持续期。如图3-2的下半部分。读时序结束后数据线
由上拉电阻拉至高电平
START 4TAST
伽孕4卜
MASTERREAD W SLOT MASTERREAD -1r,SLOT
LINETYPE LEGEIND
住grn^lQrpu.ng l°w pidlingIIQWV
Rtti^lrarpull up
图3-3DS18B20传感器的读写时序
3.1.5DS18B20 获取温度程序流程图
DS18B20的读字节,写字节,获取温度的程序流程图如图 3-3所示
|
| 开始 | |||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||
DS18B20 初始化 | |||||||||||||||||||||||||||||||||||||||||||||
程序流程图 | |||||||||||||||||||||||||||||||||||||||||||||
结束程序流程图 | |||||||||||||||||||||||||||||||||||||||||||||
| return d Q 结束 DS18B20 读字节 程序流程图 | ||||||||||||||||||||||||||||||||||||||||||||
DS18B20获取温度
程序流程图
图3-4DS18B20程序流程图
显示电路是由四位一体的数码管来实现的。由于单片机的动态扫描的方式来进行显示。程序流程图如图 3-4 所示。
I/O口有限,所以数码管采用
结束
图3-5 显示程序流程图
按键是用来设定上下限报警温度的。具体的程序流程图如图3-5 所示。3.3 按键程序设计
图3-6 按键程序流程图
4实物制作及调试
制作好的实物如图4-1所示
中 | 埠 | 钊 |
| | 乜 | | ◎ | 匚 | ◎ | 霊 | 一 | 右 |
口 | |||||||||
亡 | |||||||||
| |||||||||
申 | |||||||||
口 | 斗 | | 庁 | 巾 | 怜 | 右 | | 匸 | 岔 |
帕 | |||||||||
七 | |||||||||
口 | 电 | 匕 | |||||||
』 | 勺 | 自 | |||||||
自 | 必 | ||||||||
右 | |||||||||
七 | 乜 | 才 | |||||||
口 | ◎ |
图4-1数字温度计实物正面图
在做实物时出现了不少问题。比如本来是采用NPN型9013驱动蜂鸣器,但是在实际调
试中蜂鸣器驱动不了,经多次实验,在三极管的基极电阻与单片机的接口处接一个 1、2kQ
响,所以将NPN 型9013换成了 PNP 型的9012三极管,效果还不错。
的上拉电阻就能驱动了。但考虑到单片机的I/O 口默认状态时为高电平,这样一上电蜂鸣器就会
5电子综合设计体会
经过将近一个月的设计、焊接、编程、调试,我们终于完成了数字温度计的设计,基本能够达到设计要求,而且还设计了一些其他功能,比可以开启或消除按键音功能,开机动画功能,查看报警上下限温度功能。
此次的设计使我从中学到了一些很重要的东西,那就是如何从理论到实践的转化,怎样将我们所学到的知识运用到实践中去。在大学课堂的学习只是给我们灌输专业知识,而我们应把所学的知识应 而用到我们现实的生活中去。这次的设计不仅使我们将课堂上学到的理论知识与实际应用结合了起来,且使我们对电子电路、电子元器件、印制电路板等方面的知识有了更进一步的认识,同时在软件编程、焊板调试、相关调试仪器的使用等方面得到较全面的锻炼和提高,
为今后能够进行某些单片机应用系统的开发设计工作打下一定的基础。此次单片机设计也为我们以后进行更复杂的单片机系统设计提供了宝贵的经验。
在本次设计的过程中,我们遇到不少的问题,刚开始焊好的板子下不进去程序,经过一再仔细的检查,才发现是在下载口处出了问题,由于焊盘口比较小,排针插不进去,最后使了很大力气才插进去,插进去后才发现坏了,结果在去排针的时候把焊盘给去下来了,最后只能在旁边将下载口引了出来。还有就是文章中提到的蜂鸣器驱动问题等等。经过此次的硬件制作与调试,锻炼了我们的动手实践能了。本次设计的另一个重点就是软件程序的设计,其中需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,有好多的东西,只有我们去试着做了,才能真正的
通过此次的综合设计,我们初步掌握了单片机系统设计的基本原理。充分认识到理论学习与实践
掌握,只学习理论,有些东西是很难理解的,更谈不上掌握。
相结合的重要性,对于书本上的很多知识,不但要学会,更重要的是会运用到实践中去。在以后的学习中,我们会更加注重实践方面的锻炼,多提高自己的动手实践能力。
参考文献
[1] 谭浩强.C 程序设计 <第三版).北京:清华大学出版社,2005.7
[2]余发山,王福忠.单片机原理与应用技术.徐州:中国矿业大学出版社,2008.6[3]求是科技.单片机典型模块设计实例导航.北京:人民邮电出版社,2005.5
[4]求是科技.8051系列单片机C程序设计完全手册.北京:人民邮电出版社,2006.4
[5] 于永 ,戴佳 ,刘波 .51 单片机 C 语言常用模块与综合系统设计实例精讲版
社,2008.10
<第2版).北京:电子工业出
附1源程序代码
/********************************************************************
*程序名。基于 DS18B20的测温系统
*功能: 实时测量温度,超过上下限报警,报警温度可手动调整。K1是用来*进入上下限调节模式的,当按一下 K1进入上限调节模式,再按一下进入下限*调节模式。在正常模式下,按一下 K2进入查看上限温度模式,显示1s左右自动
*退出;按一下 K3 进入查看下限温度模式,显示
1s左右自动退出;按一下K4消除
* 按键音,再按一下启动按键音。在调节上下限温度模式下, K2 是实现加 1 功能,* K1 是实现减 1 功能, K3 是用来设定上下限温度正负的。
* 编程者: zicreate
* 编程时间: 2009/10/2
*******************************************************************
#include<ATX52.h> #include<intrins.h>延时) | // 将 ATX52.h 头文件包含到主程序 |
#define uint unsigned int //变量类型宏定义,用uint 表示无符号整形 <16 位)
#define uchar unsigned | 〃变量类型宏定义,用 | uchar 表示无符号字符型<8 位) | s=0 不显示 |
uchar max=0x00,min=0x00 。 //max 是上限报警温度, min 是下限报警温度char | |||
bit s=0 。 | //s 是调整上下限温度时温度闪烁的标志位, | ||
200ms, s=1 显示 1s 左右
bit s1=0 。 void display1(uint z> 。 | 〃声明display1<)函数 | |
#include"ds18b20.h" #include"keyscan.h" #include"display.h" | //将 display.h 头文件包含到主程序 | |
/*********************** | 主函数 ************************/ | |
void main(>
{
//关闭蜂鸣
beer=1 。led=1 。 timer1_init(0> 。 get_temperature(1> 。 | 器 | //关闭 LED 灯 |
//初始化定时器 1<未启动定时器 1 ) //首次启动 DS18B20 获取温度 <DS18B20 上点后自动将 EEPROM | ||
中的上下限温度复制到 TH 和 TL 寄存器)
while(1> // 主循环 {
keyscan(> 。 // 按键扫面函数get_temperature(0> 。// 获取温度函数
//按键扫面函数keyscan(>。
display(temp,temp_d*0.625> 。 //显示函数 alarm(> 。
//报警函数 |
|
keyscan(> //按键扫面函
。 数
}
******************************************************************
*程序名。__ds18b20_h__
*功能: DS18B20的c51编程头文件
*编程者:zicreate
*编程时间:2009/10/2
*说明:用到的全局变量是:无符号字符型变量 temp(测得的温度整数部分>,temp_d
*( 测得的温度小数部 | ,标志位f<测量温度的标志位‘ 0'表示“正温度”‘ 1'表 | 1'表 |
分 > | f max<上限温度的标志位 0'表示 正温度、 | |
* 示“负温度”),标志位 | f mi*下限温度的标志位 0'表示 正温度、 | |
* 示“负温度”),标志位 | w(报警标志位‘ 1'启动报警‘ 0'关闭报警>。 | |
* 示“负温度”),标志位******************************************************************* | ||
#ifndef __ds18b20_h__ | II 定义头文件 | |
#define __ds18b20_h__
#define uint unsigned | II 变量类型宏定义,用uint 表示无符号整形<16 位) | ||
int | // 变量类型宏定义,用 uchar 表示无符号字符型 <8 位) | ||
sbit DQ= P2A3。 | II 可位寻址变量定义,用DQ 表示P2.3 口 | ||
sbit beer=P1A0。sbit led=P1A1 。 | II 用led 表示P1.1 | ||
uchar temp=0 。 uchar temp_d=0。 bit f=0 。 | | ||
〃测量温度的标志位,0'表示“正温度”’1'表示“负温度”)
bit f_max=0 。 | 〃上限温度的标志位‘ 0'表示“正温度”‘ 1'表示“负温度”) |
bitf_min=0 。//下限温度的标志位‘0'表示“正温度”、‘1'表示“负温度”)
bitw=0 。 //报警标志位‘1'启动报警‘0'关闭报警>
I*********************延时子函数
**************************************I
voidds18b20_delayus(uint II延时几(I
t> s
{while(t-->
。}
voidds18b20_delayms(uint II延时1ms左右
t>{uint i,j 。for(i=t。i>0。i-- j>0。j-
>for(j=1 20 。I************************** ->。}*************************I
ds18b20初始化函数
void IIDS18B20 初始化
ds18b20_init(>
DQ=1 。 | 〃延时480 卩s 左 | 〃拉高数据 | |
DQ=0 。 | 线 | ||
ds18b20_delayus(30> | |||
。DQ=1 。 | 右 | 〃控制器拉高总线, | |
while(DQ> 。 | II 等待DS18B20 拉低总线 |
| |
ds18b20_delayus(20>。 //延时,等待上拉电阻拉高总线
DQ=1。 //拉高数据线,准备数据传输;
/*************************** ds18b20 字节读函数
************************/
uchar uchar DQ = | { //定义一个局部变量i (局部变量只在本函数中有效 > //定义一个局部变量d //准备读; |
1 。
for(i=8。i>0。i-
->
//一位一位的读,循环8次
d >>= 1 | //d 左移一位,低位先 | |
。 | DQ = 0 | |
。
_nop_(> 。 _nop_(>。
预期的数据; | _nop_(> 。 | //必须写 1,否则读出来的将是不 | |
。 | //在 12us 处读取数据,送给 d 的最高位 | ||
if(DQ | |||
> | d |= | ||
0x80 。
ds18b20_delayus(10>
d 。 。
}return
void ds18b20_write(uchar d> ds18b20 字节写函数 /*************************
uchar i。
for(i=8 。 | i- | //一位一位的 | //写数据 | |
{ DQ=0 。 | -> | 写 | ||
_nop_(> 。 _nop_(>。 _nop_(>。 DQ=d&0x01 。 | ||||
ds18b20_delayus(5> | DQ=1 | d >>= | ||
。 | 。 | 1 。 | ||
/*************************** void get_temperature(bit f> {
获取温度函数****************************/
uchar a=0,b=0,c=0,d=0 。
uint i 。
ds18b20_init(> 。//DS18B20 初始化
ds18b20_write(0xcc> 。 //向 DS18B20 发跳过读 ROM 命令
ds18b20_write(0x44> 。 //写启动 DS18B20 进行温度转换命令,转换结果存入内部 RAM if(f==1>
值。
display1(1> //用开机动画耗时
。}else
ds18b20_delayms(1>。
ds18b20_init(> 。 ds18b20_write(0xcc> 。 ds18b20_write(0xbe> 。 a=ds18b20_read(>。 if(f==1> { max=ds18b20_read(> 。min=ds18b20_read(> 。 | //DS18B20 初始化 //读内部 RAM <TH ) |
}
if((max&0x80>==0x80>// 若读取的上限温度的最高位<符号位)为 1'表明是负温度
{f_max=1。max=(max-0x80>。}//将上限温度符号标志位置’1'表示负温度,将上限温度装换成无符号
数。
if((min&0x80>==0x80>//若读取的下限温度的最高位<符号位)为‘1'表明是负温度
符号数。
{f_min=1 。min=(min-0x80> 。}//将下限温度符号标志位置‘1'表示负温度,将下限温度装换成无
i=b。i>>=4。
if (i==0> {
f=0 。 | //i 为 0,表示读取的温度是正温度,设立正温度标记 | |
temp=((a>>4>|(b<<4>> 。 | //整数部分 | |
a=(a&0x0f>。
temp_d=a。 | //小数部分 |
}
else
{
f=1 。 | //i 为 1 ,表示读取的温度是负温度,设立负温度标记 | |
a=~a+1 。 | //负数的小数部分取反加 1 | |
b=~b。 | //负数的整数部分取反 | |
temp=((a>>4>|(b<<4>> 。 | //整数部分 | |
a=(a&0x0f> 。 | //小数部分 | |
temp_d=a。
}
voidstore_t(>
if(f_max==1>// 若上限温度为负,将上限温度转换成有符号数<最高1是负,0是正)max=max+0x80。
if(f_min==1 //若下限温度为负,将上限温度转换成有符号>min=min+0x80 。 数
ds18b20_init(>。 //DS18B20初始化
ds18b20_write(0xcc> //向DS18B20发跳过读ROM命令
ds18b20_write(0x4e>。。 //向DS18B20发写字节至暂存器2和3<TH和TL)命令
ds18b20_write(max> 。
ds18b20_write(min> 。
ds18b20_write(0xff>
//向暂存器TH<上限温度暂存器)写温度 //向暂存器TL<下限温度暂存器)写温度//向配置寄存器写命令,进行温度值分辨率设
。 ds18b20_init(> | 置 |
。
ds18b20_write(0xcc>
//DS18B20初始化
//向DS18B20发跳过读ROM命令
} | 。 ds18b20_write(0x48> | //向 DS18B20 发将 RAM 中 2、3 字节的内容写入 EEPROM |
。 | //DS18B20 上电后会自动将 EEPROM 中的上下限温度拷贝到 TH 、 TL 暂 |
存器
/******************* ******* if(f_max==0 if(f_min==0 | 温度超限报警函数 | ||
| //若上限值是正 | ||
| |||
if(f== | //若测量值是正 | ||
0> | 值 | ||
if((temp+temp_d*0.0625><=min||(temp+temp_d*0.0625>>=max> {w=1 。 //当测量值小于最小值或大于最大值时TR1=1 。} 报
if((temp+temp_d*0.0625><max&&(temp+temp_d*0.0625>>min>
值时不报警 | {w=0 。 | //当测量值大于最小值且小于最大 |
} |
} if(f==1>{w=1 。 TR1=1 。} //若测量值是负值时报警
if(f_min==1 | //若下限值是负 | ||
> | {if(f==0 | 值 | //若测量值是正 |
> | 值 | ||
报警
{w=1 。
TR1=1 。}
if((temp+temp_d*0.0625><max>// 当测量值小于最大值时不报
警{w=0。}
if(f==1> //若测量值是负
值
{if((temp+temp_d*0.0625>>=min>//当测量值大于最小值时报
警 | {w=1 。 TR1=1 。 } |
if((temp+temp_d*0.0625><min>//当测量值小于最小值时不报
警
{w=0。
}
if(f_max==1 //若下限值是负
> | 值 | ||
1> | {if(f== | 值 | //若测量值是负 |
1> | 值 | ||
if((temp+temp_d*0.0625><=max||(temp+temp_d*0.0625>>=min>
{w=1。 //当测量值小于最大值或大于最小值时
TR1=1。} 报
if((temp+temp_d*0.0625><min&&(temp+temp_d*0.0625>>max>
值时不报警 | {w=0 。 |
| //当测量值小于最小值且大于最大 |
} | |||
TR1=1 。} | |||
#endif
/********************************************************
**************
程序名。 __keyscan_H__
功能: ds18b20键盘头文件,通过键盘设定设定上下限报警温度
编程 zicreat
编程时间:2009/10/2
*********************************************************
*************/ #ifndef __keyscan_H__ | //定义头文件 | keyl 表示 P2.2 |
#define __keyscan_H__ | ||
sbit | //可位寻址变量定义,用 | |
key1=P2A2。sbit | //用 key2 表示 | 口 |
key2=P2A1 。 | P2.1 | |
sbit sbit key3=P2A0 。key4=P3A3 。 | //用 key3 表示 P2.0 | |
//用 key4 表示 P3.3 |
uchari=0。//定义全局变量i用于不同功能模式的选择,‘0'正常模式,‘1'上限调节模式,‘ 2'下限调节
模式
uchar a=0。 | //定义全局变量 a 用于不同模式下数码管显示的选择 | k4=1 时 |
bit k4=0。 | 〃K4 按键双功能选择位,k4=0 时K4 按键选择消按键音的功能, |
K4按键选择正负温度设定功能
bitv=0 。 //K2、K3按键双功能选择位,v=0时选择上下限查看功能,v=1时选择上下限温
度加减功能
bitv1=0 。 //v1=1时定时1250ms时间到自动关闭报警上下限查看功能
bitv2=0 。 //消按键音功能调整位,为‘0'时开按键音,为‘1'时关按键音
/*************************** 读键盘延时子函数**************************/
voidkeyscan_delay(uint z> //延时1ms左右
uinti,j 。
for(i=z。i>0。i-->
for(j=120。j>0。j-->。
/**************************** 温度调节函数******************************/
inttemp_change(int //上下限温度调整
count,bitf>
if(key2==0> //判断 K2 是否按下
keyscan_delay(10> 。 if(key2==0> { if(v2==0>beer=0 。
抖) //再次判断K2是否按下<实现按按键时
消
{
beer=1。 //K2按下关按键音
if(f==0> //若温度为正
{
count++。 //每按一下K2温度上调1
if(a==1>{if(count>125>count=125 。}//当温度值大于125时不上调
if(a==2>{if(count>125>count=125 。}
}
if(f!=0> //若温度为负
{
count++。 //每按一下K2温度下调1
if(a==1>{if(count>55>count=55 。}//当温度值小于-55时不再下调
if(a==2>{if(count>55>count=55 。}
}
while(key2==0>。
keyscan_delay(10>。//K2松开按键时消
抖
if(key3==0>
if(v2==0>beer=0。
keyscan_delay(10>。 //K3按按键时消抖
if(key3==0>
beer=1。
上调 1 | count- | //每按一下 K3 温度为正时下调 1,为负时 |
- 。 | 。}// 当温度值达到 0 时不 | |
if(a==1>{if(count<0> | ||
count=0 | 再调 | |
if(a==2>{if(count<0> | 。 | |
} | ||
count=0 | ||
//K3 松开按键时消 | ||
while(key3==0> 。 | ||
keyscan_delay(10>。 | 抖 |
return
count。
/********************* ******** | 读键盘函数 ******************************/ |
if(v2==0>beer=0。
keyscan_delay(10> 。 > | //K1 按按键时消 |
beer=1
。
TR1=1。//开定时器1,通过s标志位的变化,实现在上下限温度调整时温度显示时闪烁
的功能
k4=1 。 //在上下温度调节功能模式下选择v=1。 //在上下温度调节功能模式下选择
K4的调整上下限温度正负的功能K2、K3的温度加减功能
调下限模式 | i++ 。 //K1 按一下 i 加 | i= ‘ 0'进入正常模式,i= ‘1'进入调上限模式,i= ‘ 2 '进入 | |
1 , | //K1 按下三次后退出调节模 | ||
if(i> | |||
2> | 式 | ||
i=0 。 | //进入正常模式 | ||
TR1=0 。 | //关定时器 | 1 | |
k4=0 | |||
//在正常模式下选择 K4 的消按键音功能 | |||
。 v=0 | //在正常模式下选择 K2、K3 的查看上下限报警温度功能 | ||
。 store_t( | //存储调整后的上下限报警温度 | ||
| |||
> 。 | |||
switch( | //显示选 |
| |
i> | 择 | ||
case0:a=0。break。//a=0选择显示测得的温度
case1:a=1。break。//a=1选择显示上限温度
case2:a=2。break。//a=2选择显示下限温度default:break。
}
}while(key1==0>。//K1松按键时消抖keyscan_delay(10>。}
if(a==1&&v==1>//a=1 选择显示上限温度且v=1时选择上下限温度加功能{led=0。
max=temp_change(max,f_max>。}//显示上限温度
elseif(a==2&&v==1> //a=2 选择显示下限温度且v=1时选择上下限温度减功能{led=1。min=temp_change(min,f_min>。}else。
if(k4==1>//k4=1 时K4按键选择正负温度设定功能{
if(key4==0>
{if(v2==0>beer=0。keyscan_delay(5>。
if(key4==0>
{beer=1。
if(a==1>
{if(max>55>f_max=0 。elsef_max=~f_max 。}//当温度大于55度时,只能
正温度 正温度 | 设定为 | |
if(a==2> |
| |
| ||
}
}
if(v==0>//v=0 时选择上下限查看功能
{
if(key2==0>
{if(v2==0>beer=0。keyscan_delay(10>。
if(key2==0>
{
beer=1。
退出 | a=1 。 | //选择上限显示 |
TR1=1 。 | //开定时器 1 开始定时一分钟左右 | |
s1=1 。 | ||
//上限显示不闪烁,显示一分钟左右自 | ||
动 |
}
while(key2==0>。keyscan_delay(10>
。
}
if(key3==0>
{
if(v2==0>beer=0。keyscan_delay(10>。
if(key3==0>
{
beer=1。
a=2 。 TR1=1 。 s1=1 。 | //选择下限显示 |
示不闪烁,显示1s自动退出
}while(key3==0>。keyscan_delay(10>。
} |
{
if(key4==0>{
if(v2==0>beer=0。keyscan_delay(10>。
if(key4==0>
{
}
beer=1。v2=~v2。 //为‘0'时开按键音,为‘1'时关按键音
while(key4==0> 。
keyscan_delay(1 0> 。
}
}
}
}
#endif
程序名。 | __ds18b20_display_H__ | 0 延时实现数码管动态显示 |
功 能: | ds18b20 数码管动态显示头文件,通过定时器 |
编程者:zicreate
编程时间:2009/10/2
**********************************************************************/
#ifndef__ds18b20_display_H__ //定义头文件
#define__ds18b20_display_H__
#defineuint unsigned int //变量类型宏定义,用uint表示无符号整形<16位)
#defineuchar unsigned char //变量类型宏定义,用 uchar表示无符号字符 <8位)
sbitwei仁P2M。 wei1表示P2.4口
sbitwei2=P2A5。 //可位寻址变量定义,
sbitwei3=P2A6 。 //用wei2表示P2.5//用wei3表示P2.6
sbitwei4=P2A7 。 //用wei4表示P2.7
ucharnum=0 。 //定义num为全局无符号字符型变量,赋初值为‘ 0'
ucharcode temperature1[]={ 0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f}。//定义显示码表0~9
ucharcode temperature2[]={ 0xbf,0x86,0xdb,0xcf,0xe6,
0xed,0xfd,0x87,0xff,0xef} 。 | //带小数点的 | H' |
uchar code temperature3[]={ | 0.~9. | |
void display_delay(uint t> /***************************** 延时子函数 ******************************/ | ||
uinti,j 。
for(i=t。i>0。i-->
for(j=120。j>0。j
/**************************定时器1初始化函数***************************/
voidtimer1_init(bit t>
TMOD=0x10。 //设定定时器1工作在方式1,最大定时
65.53ms
TH0=0x3c 。 | //定时器赋初值,定时 | 50ms |
TL0=0xb0。
EA=1 。 | //开总中断 | 中断 |
ET1=1。 | //开定时器 1 | |
TR1=t 。 | // 局部变量 t 为 1 启动定时 | 1,为 0 关闭定时器 1 |
器
/**************************定时器1中断函数*****************************/
voidtimer1(> interrupt 3 {
TH0=0x3c。 //重新赋初值,定时50ms
TL0=0xb0。
num++。 | 〃每进入一次定时器中断 | num 加1<每50ms 加1 一次) |
if(num<5>
{s=1。if(w==1>{beer=1。led=1。}else{beer=1。led=1。}}
}
*******************
| 调整报警上下限显示选择函数 | ******************** |
|
Else//进入4次中断,定时200ms时若报警标志位w为‘1'则启动报警,不为‘1'不启动//实现间歇性报
警功能
{s=0。if(w==1>{beer=0。led=0。}else{beer=1。led=1。}}
if(num>20> | //进入 20 次中断,定时 1s |
r
{
num=0。 | //num 归 0,重新定开始定时 1s | |
示功能 | s1=0。 | 〃定时1s 时间到时自动关闭报警上下限 |
显 | ||
v1=1 。 | 〃定时1s 时间到时自动关闭报警上下限 | |
看功能 | 查 | |
void selsct_1(uchar f,uchar k> //消除百位的 0 显示,及正负温度的显示选择 | ||
if(k/100==0>P0=temperature3[0] 。elseP0=temperature1[k/100] 。
}
if(f==1 //若为负温度,若十位为0,百位不显示,否则百位显示
>
{if(k%100/10==0> P0=temperature3[0] 。elseP0=temperature3[2] 。
}
}
voidselsct_2(bit f,uchar k> //消除十位的0显示,及正负温度的显示选择
{
if(f==0> //若为正温度,百位十位均为0则不显示十位,否则显示十位
{if((k/100==0>&&(k%100/10==0>>P0=temperature3[0]。
elseP0=temperature1[k%100/10]。
}
if(f==1> | //若为负温度,若十位为 | 0,十位不显示,否则十位显示‘ | - ' |
elseP0=temperature1[k%100/10] 。
/**************************** 主显示函数
********************************/void display(uchar t,uchar t_d>
//用于实测温度、上限温度的显示
uchari 。
for(i=0。i<4。i++> //依次从左至右选通数码管显示,实现动态显示
switch(i>
{
case0: //选通第一个数码管
if(a==0>{selsct_1(f,t>。}//若a=0则在第一个数码管上显示测量温度的百位或’ if(a==1>
{
P0=temperature3[3]。//若a=1则在第一个数码管上显示‘H'
}
if(a==2>
{
P0=temperature3[4] 。 | //若 a=2 则在第一个数码管上显示‘ L' |
wei3=0 。 } wei2=0 。 | |
wei4=0 。 | //关第四个数码管 |
//开第一个数码管
wei1=1。break。
case 1: | //选通第二个数码管 | -' | |
if(a==0>{selsct_2( | 。 } //若 a=0 则在第二个数码管上显示测量温度的十位或‘ | ||
f,t> | //若 a=1 则在第二个数码管上显示上限报警温度的百位或‘ | -' | |
{ | if(a==1> | ||
if(s==0>selsct_1(f_max,max> 。//若s=0则显示第二个数码管,否则不显示
elseP0=temperature3[0]。 〃通过s标志位的变化实现调节上下限报警温度时数码管的闪烁 if(s1==1>selsct_1(f_max,max> 。//若s1=1则显示第二个数码管<s1标志位用于上下 限查
看时的显示)
}if(a==2>
{ //若a=2则在第二个数码管上显示下限报警温度的百位或‘
if(s==0>selsct_1(f_min,min> 。
elseP0=temperature3[0] 。
if(s1==1>selsct_1(f_min,min> 。
}
wei1=0。wei3=0。wei4=0。wei2=1。break。
case2: // 选通第三个数码管
if(a==0>{P0=temperature2[t%10]。}//若a=0则在第三个数码管上显示测量温度的
个位 if(a==1>
{
//若a=1则在第三个数码管上显示上限报警温度的十位或‘
if(s==0> selsct_2(f_max,max> 。 //若 s=0 则显示第三个数码管,否则不显示 else P0=temperature3[0] 。
if(s1==1> selsct_2(f_max,max> 。 // 若 s1=1 则显示第三个数码管 } if(a==2> // 若 a=2 则在第三个数码管上显示下限报警温度的十位或‘{
if(s==0> selsct_2(f_min,min> 。
else P0=temperature3[0] 。 if(s1==1> selsct_2(f_min,min> 。
}
wei1=0 。 wei2=0 。 wei4=0 。 wei3=1 。 break 。
case 3: // 选通第四个数码管
if(a==0>{P0=temperature1[t_d] 。 }// 若 a=0 则在第四个数码管上显示测量温度的小 数位 if(a==1> //若 a=1 则在第四个数码管上显示上限报警温度的个位
{
if(s==0> P0=temperature1[max%10] 。 // 若 s=0 则显示第四个数码管,否则不显示
if(a==2> if(s1==1> P0=temperature1[max%10] 。 //若 s1=1 则显示第四个数码管 } //若 a=2 则在第四个数码管上显示下限报警温度的个位
{
if(s==0> P0=temperature1[min%10] 。 else P0=temperature3[0] 。 if(s1==1> P0=temperature1[min%10] 。
}
wei1=0 。 wei2=0 。 wei3=0 。 wei4=1 。 break。
}
//每个数码管显示 3ms 左右
disp
lay_
dela
y(3>
。
}
}
/****************************开机显示函数 ******************************/
void display1(uint z> //用于开机动画的显示
{
uchari,j 。
bitf=0 。
for(i=0。i<z。i++>
{
for(j=0。j<4。 j++> { switch(j>
{
II‘ z'是显示遍数的设定
〃依次从左至右显示’-'
case 0:P0=temperature3[2]。 〃第一个数码管显示 wei2=0。 wei3=0。 wei4=0。 wei1=1。 break。
case 1:P0=temperature3[2]。 〃第二个数码管显示 wei1=0。 wei3=0。 wei4=0。 wei2=1 。 break。
case 2:P0=temperature3[2]。 〃第三个数码管显示 wei1=0。 wei2=0。 wei4=0。 wei3=1 。 break。
case 3:P0=temperature3[2]。 〃第四个数码管显示 wei1=0 。 wei2=0。wei3=0。 wei4=1 。 break。
}
}
display_delay(200>。II每个数码管显示200ms左右
} | } |
|
#endif | ||
|
附2系统原理图
Copyright © 2019- howto1234.net 版权所有
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务