基于51单片机的温度检测系统

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机C语言课题设计报告
设计题目:温度检测
指导老师:
设计人:
学号:
班级:
设计时间:
摘要
本课题以51单片机为核心实现智能化温度测量。

利用18B20温度传感器获取温度信号,将需要测量的温度信号自动转化为数字信号,利用单总线和单片机交换数据,最终单片机将信号转换成LCD可以识别的信息显示输出。

基于STC90C516RD+的单片机的智能温度检测系统,设计采用18B20温度传感器,其分辨率可编程设计。

本课题设计应用于温度变化缓慢的空间,综合考虑,以降低灵敏度来提高显示精度。

设计使用12位分辨率,因其最高4位代表温度极性,故实际使用为11位半,而温度测量范围为-55℃~+125℃,则其分辨力为0.0625℃。

设计使用LCD1602显示器,可显示16*2个英文字符,显示器显示实时温度和过温警告信息,传感器异常信息设。

计使用蜂鸣器做警报发生器,当温度超过设定值时播放《卡农》,当传感器异常时播放嘟嘟音。

目录
一、设计功能 (3)
二、系统设计 (3)
三、器件选择 (3)
3.1温度信号采集模块 (3)
3.1.1 DS18B20 数字式温度传感器 (4)
3.1.2 DS18B20特性 (4)
3.1.3 DS18B20结构 (5)
3.1.4 DS18B20测温原理 (6)
3.1.5 DS18B20的读写功能 (6)
3.2 液晶显示器1602LCD (9)
3.2.1引脚功能说明 (9)
3.2.2 1602LCD的指令说明及时序 (10)
3.2.3 1602LCD的一般初始化过程 (10)
四、软件设计 (11)
4.1 1602LCD程序设计流程图 (11)
4.2 DS18B20程序设计流程图 (12)
4.3 主程序设计流程图 (13)
五、设计总结 (14)
六、参考文献 (14)
七、硬件原理图及仿真 (15)
7.1系统硬件原理图 (15)
7.2开机滚动显示界面 (16)
7.3临界温度设置界面 (16)
7.4传感器异常警告界面 (16)
八、程序清单 (17)
温度
DS18B20 LCD 显示
过温函数功能模块
传感器异常函数功能模块
D 0
D 1D 2D 3D 4D 5D 6D 7R W
R S
E N
D0D1D2D3D4D5D6D7D 7D 6D 5D 4D 3D 2D 1D 0E N R W R S XT AL2
18
XT AL1
19
ALE 30EA
31
PSEN
29RST 9P0.0/AD039P0.1/AD138P0.2/AD237P0.3/AD336P0.4/AD435P0.5/AD534P0.6/AD633P0.7/AD732P2.7/A1528
P2.0/A821P2.1/A922P2.2/A1023P2.3/A1124P2.4/A1225P2.5/A1326P2.6/A1427P1.01P1.12P1.23P1.34P1.45P1.56P1.67P1.78
P3.0/RXD 10
P3.1/TXD 11P3.2/INT012P3.3/INT113P3.4/T014P3.7/RD
17
P3.6/WR 16P3.5/T115U1
80C51
X1
CRYST AL
C1
22pF
C2
22pF
GND
V C C
G N D
R1
10k
C3
1uF
V C C
VCC
GND
23456789
1
RP1
RESPACK-8
VCC
0.0
DQ 2VCC 3GND 1
U2
DS18B20
R2
4.7K D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S
1V D D 2V E E
3
LCD1
LM016L
LS2
SOUNDER
MUC
一、设计功能
·由单片机、温度传感器以及液晶显示器等构成高精度温度监测系统。

·温度显示精确到小数点后四位。

·按键设定过温值,过温在液晶屏提示并响铃卡农一次,直到温度正常。

·设计传感器状态检测函数,传感器工作不正常在液晶屏警告提示,响警告铃, 直到故障排除。

·proteus 做系统硬件电路设计并仿真。

二、系统设计
三、器件选择
3.1温度信号采集模块
传统的温度检测大多以热敏电阻为传感器,采用热敏电阻,可满足 40℃度 至 90℃测量范围,但热敏电阻可靠性差,测量温度准确率低,对于1℃的信号是不适用的,还得经过专门的接口电路转换成数字信号才能由微处理器进行处理。

目前常用的微机与外设之间进行的数据通信的串行总线主要有2I C总线,SPI 总线等。

其中2I C总线以同步串行 2 线方式进行通信(一条时钟线,一条数据线)。

SPI 总线则以同步串行 3 线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线)。

这些总线至少需要两条或两条以上的信号线。

而单总线( 1-wire bus ),采用单根信号线,既可传输数据,而且数据传输是双向的,CPU 只需一根端口线就能与诸多单总线器件通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。

单总线具有广阔的应用前景,是值得关注的一个发展领域。

单总线即只有一根数据线,系统中的数据交换,控制都由这根线完成。

主机或从机通过一个漏极开路或三态端口连接到数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线。

单总线通常要求外接一个约为 4.7K 的上拉电阻,这样,当总线闲置时其状态为高电平。

3.1.1 DS18B20 数字式温度传感器
DS18B20 数字式温度传感器使用集成芯片,采用单总线技术,其能够有效的减小外界的干扰,提高测量的精度,同时,它可以直接将被测温度转化成串行数字信号供微机处理,接口简单,使数据传输和处理简单化。

部分功能电路的集成,使总体硬件设计更简洁,能有效地降低成本,搭建电路和焊接电路时更快,调试也更方便简单化,大大缩短了开发的周期。

3.1.2 DS18B20特性
采用单总线的接口方式,与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。

单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。

(1)适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电。

(2)独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。

(3)DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温。

(4)DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内。

(5)温范围-55℃~+125℃。

(6)可编程的分辨率为9~12位,对应的分辨力分别为0.5℃、0.25℃、
0.125℃和0.0625℃,可实现高精度测温。

(7)在9位分辨率时最多在 93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快。

(8)测量结果直接输出数字温度信号,以" 1-wire bus "串行传送给CPU,可选择同时传送CRC校验码,具有极强的抗干扰纠错能力。

(9)负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。

3.1.3 DS18B20结构
DS18B20的内部结构
3.1.4 DS18B20测温原理
DS18B20测温原理框图
图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。

高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入.
计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。

图3中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。

3.1.5 DS18B20的读写功能
DS18B20温度值格式表
这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。

例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FE6FH,-55℃的数字输出为FC90H 。

DS18B20温度数据表
DS18B20温度传感器的存储器 DS18B20温度传感器的内部存储器包括一个高速暂存RAM和一个非易失性的可电擦除的EEPRAM,后者存放高温度和低温度触发器 TH、TL和结构寄存器。

TM R1 R0 1 1 1 1 1
配置寄存器结构
低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。

在DS18B20出厂时该位被设置为0,用户不要去改动。

R1和R0用来设置分辨率,如下表所示:(DS18B20出厂时被设置为12位)
R1 R0 分辨率温度最大转换时间
0 0 9位93.75ms
0 1 10位187.5ms
1 0 11位375ms
1 1 12位750ms
温度分辨率设置表
寄存器内容字节地址
温度值低位(LS Byte)0
温度值高位(MS Byte) 1
高温限值(TH) 2
低温限值(TL) 3
配置寄存器 4
保留 5
保留 6
保留7
CRC校验值8
DS18B20暂存寄存器分布
根据DS18B20的通讯协议,主机(单片机)控制DS18B20完成温度转换必须
经过三个步骤:每一次读写之前都要对DS18B20进行复位操作,复位成功后发
送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。


位要求主CPU将数据线下拉500微秒,然后释放,当DS18B20收到信号后等待16~60微秒左右,后发出60~240微秒的存在低脉冲,主CPU收到此信号表示
复位成功。

指令约定代码功能
读ROM 33H 读DS1820温度传感器ROM中的编码(即64位地址)
符合ROM 55H 发出此命令之后,接着发出64 位ROM 编码,访问单总线上与该编码相对应
的DS1820 使之作出响应,为下一步对该DS1820 的读写作准备。

搜索ROM 0FOH 用于确定挂接在同一总线上DS1820 的个数和识别64 位ROM 地址。

为操作
各器件作好准备。

跳过ROM 0CCH 忽略64 位ROM 地址,直接向DS1820 发温度变换命令。

适用于单片工作。

告警搜索命令0ECH 执行后只有温度超过设定值上限或下限的片子才做出响应。

温度变换44H 启动DS1820进行温度转换,12位转换时最长为750ms(9位为93.75ms)。


果存入内部9字节RAM中。

读暂存器0BEH 读内部RAM中9字节的内容
写暂存器4EH 发出向内部RAM的3、4字节写上、下限温度数据命令,紧跟该命令之后,是
传送两字节的数据。

复制暂存器48H 将RAM中第3 、4字节的内容复制到EEPROM中。

重调EEPRO
0B8H 将EEPROM中内容恢复到RAM中的第3 、4字节。

M
读供电方式0B4H 读DS1820的供电模式。

寄生供电时DS1820发送“ 0 ”,外接电源供电DS182
0发送“ 1 ”。

ROM指令表
3.2 液晶显示器1602LCD
显示容量:16×2个字符,芯片工作电压:4.5—5.5V ,工作电流:2.0mA(5.0V),模块最佳工作电压:5.0V ,字符尺寸:2.95×4.35(W ×H)mm 。

3.2.1引脚功能说明 1602LCD 采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如图 编号 符号 引脚说明 编号 符号 引脚说明 1 VSS 电源地 9 D2 数据 2 VDD 电源正极 10 D3
数据 3 VL 液晶显示偏压 11 D4 数据 4 RS 数据/命令选择 12 D5 数据 5 R/W 读/写选择 13 D6 数据 6 E 使能信号 14 D7 数据 7 D0 数据 15 BLA 背光源正极 8
D1
数据
16
BLK 背光源负极
D 0
D 1D 2D 3D 4D 5D 6D 7R W
R S E N D0D1D2D3D4D5D6D7D 7D 6D 5D 4D 3D 2D 1D 0E N R W R S XT AL218XT AL1
19
ALE 30EA 31PSEN 29RST 9P0.0/AD0
39
P0.1/AD1
38P0.2/AD2
37P0.3/AD336P0.4/AD435
P0.5/AD5
34P0.6/AD6
33
P0.7/AD732
P2.7/A1528
P2.0/A821P2.1/A9
22P2.2/A10
23
P2.3/A1124
P2.4/A1225
P2.5/A1326
P2.6/A14
27
P1.0
1P1.1
2
P1.23P1.34
P1.45P1.56
P1.67
P1.7
8
P3.0/RXD
10P3.1/TXD
11
P3.2/INT012P3.3/INT1
13P3.4/T014P3.7/RD 17P3.6/WR 16P3.5/T115U1
80C51X1CRYST AL C1
22pF
C222pF GND
V C C
R110k
C31uF V C C
VCC
GND
234567891RP1
RESPACK-8
VCC
43.0
DQ 2
VCC
3GND
1
U2DS18B20
R24.7K D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S 1V D D 2V E E
3
LCD1
LM016L
3.2.2 1602LCD 的指令说明及时序
1602液晶模块内部的控制器共有11条控制指令,如图
3.2.3 1602LCD 的一般初始化过程
延时15mS
写指令38H (不检测忙信号) 延时5mS
写指令38H (不检测忙信号) 延时5mS
写指令38H (不检测忙信号)
以后每次写指令、读/写数据操作均需要检测忙信号 写指令38H :显示模式设置 写指令08H :显示关闭 写指令01H :显示清屏 写指令06H :显示光标移动设置
写指令0CH :显示开及光标设置
序号 指令
RS R/W D7 D6 D5 D4 D3 D2 D1 D0
1 清显示 0 0 0 0 0 0 0 0 0 1
2 光标返回 0 0 0 0 0 0 0 0 1 *
3 置输入模式 0 0 0 0 0 0 0 1 I/D S
4 显示开/关控制 0 0 0 0 0 0
1
D C B 5 光标或字符移位 0 0 0 0 0
1 S/C R/L *
* 6 置功能
0 0 0 0
1 DL N
F
*
*
7 置字符发生存贮器地址 0 0 0
1 字符发生存贮器地址
8 置数据存贮器地址 0 0
1 显示数据存贮器地址
9
读忙标志或地址
1 BF 计数器地址 10 写数到CGRAM 或DDRAM ) 1 0 要写的数据内容 11 从CGRAM 或DDRAM 读数 1
1 读出的数据内容
四、软件设计
4.1 1602LCD程序设计流程图
4.2DS18B20程序设计流程图
4.3 主程序设计流程图
开始
调用滚动子函数
调用温度读取子函数
延时800ms
调用温度读取子函数
18B20初始化是
否完成
是否初始化完成
且不过温
是否初始化完成
且过温
N
N
Y Y 调用Error_Menu 调用Ok_Menu 警铃函数读取温度
18B20初始化是否通过
Y
N
读取温度显示温度
是否初始化完成且不过温
Y
N
Y 调用OVER_TEMP 调用卡农音乐读取温度
是否初始化完成且过温
Y
N
N
五、设计总结
在这课题设计中我学到了很多东西,获益匪浅。

本次课题以51单片机为核心实现了智能化温度测量,过温警告,传感器异常警报功能。

利用温度传感器获取被控对象指标,通过温度传感器将需要测量的温度信号转化为数字电信号,通过单总线与MCU进行传输,再经单片机转换成显示器可以识别的信息,最后显示输出。

在一开始,我制订了合理的规划,绘制了与课题相关的硬件原理图,分析了单片机的各I/O端口。

然后进行程序设计的分析,设计绘制流程图,并按照流程图,进行程序段的编写。

接下来把所有的程序段组合在一起综合分析,最后烧录到单片机上进行硬件调试。

在这整个过程当中,我遇到了重重困难。

(1)高位为零时消隐;(2)18B20上电温度误判;(3)LCD显示闪烁;(4)18B20修复温度误判;(5)LCD查表写坐标混合显示。

通过一次次的反复分析和调试,查阅互联网资料最终成功解决。

这其中的苦泪和欢笑只有自己知道。

通过程序的编写我收获了很多,并总结到大多数故障问题源于程序里括号及分号的错误。

通过这次课题设计,我深深意识到学习单片机不是只要学好怎样写程序就够了,还要对硬件有所了解,要把软件与硬件相结合才,期间还要经过多次的失败,需要相当的耐心和细致的思考来排除一切困难,一步一步地解决问题。

在此,我要特别施芸老师给提供给我这次自我锻炼,自我提升的机会。

我定会把这次课题设计积累的经验落实到以后的学习中去。

姓名:钟乾鹏
学号:201112020247
班级:2011级通信技术1班六、参考文献
【1】马忠梅等编著.单片机的C语言应用程序设计(第4版).北京[M]:北京航天航空大学出版社,2007
【2】樊明龙等编著.单片机原理与应用.北京[M]:北化学工业出版社,2005 【3】周志德. 单片机原理级应用. 北京[M]:高等教育出版社,2001 鸣谢/
七、硬件原理图及仿真
7.1系统硬件原理图
D 0
D 1D 2D 3D 4D 5D 6D 7R W R S
E N
D0D1D2D3D4D5D6D7
D 7D 6D 5D 4D 3D 2D 1D 0
E N R W R S K 1K 2K 3K1K2K3
XT AL2
18
XT AL1
19
ALE 30EA
31
PSEN 29RST
9
P0.0/AD039P0.1/AD138P0.2/AD237P0.3/AD336P0.4/AD435P0.5/AD534P0.6/AD633P0.7/AD732P2.7/A1528P2.0/A821P2.1/A922P2.2/A1023P2.3/A1124P2.4/A1225P2.5/A1326P2.6/A1427P1.01P1.12P1.23P1.34P1.45P1.56P1.67P1.78
P3.0/RXD 10P3.1/TXD 11P3.2/INT012P3.3/INT113P3.4/T014P3.7/RD
17
P3.6/WR 16P3.5/T115U1
80C51
X1
CRYST AL
C1
22pF
C2
22pF
GND
V C C
G N D
R1
10k
C3
1uF
V C C
VCC
GND
23456789
1
RP1
RESPACK-8
VCC
20.0
DQ 2VCC 3GND 1
U2
DS18B20
R2
4.7K D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S 1V D D 2V E E
3
LCD1
LM016L
LS2
SOUNDER
GND
7.2开机滚动显示界面
7.3临界温度设置界面
7.4传感器异常警告界面
D 7D 6D 5D 4D 3D 2D 1D 0
E N R W R S VCC
GND
D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S 1V D D 2V E E
3
LCD1
LM016L
D 7D 6D 5D 4D 3D 2D 1D 0
E N R W R S VCC
GND
D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S 1V D D 2V E E
3
LCD1
LM016L
D 7D 6D 5D 4D 3D 2D 1D 0
E N R W R S VCC
GND D 7
14
D 613D 512D 411D 310D 29D 18D 07E
6
R W 5R S 4V S S 1V D D 2V E E
3LM016L
八、程序清单
#include < reg51.h >
#include < intrins.h >
#include < song.h >
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P3^7 ; //定义DS18B20端口DQ
sbit K5=P2^3;
sbit K6=P2^2;
sbit K7=P2^1;
bit presence ; //初始化标志位
sbit lcdrs = P2^6 ; //加按键
sbit lcdrw = P2^5 ; //减按键
sbit lcden = P2^7 ; //确定
uint T,Temp; //T包含两个单元,用来存储16位温度信息
uchar code cdis1[ ] = {" WELCOM TO USE! "} ;//正常测温显示界面
uchar code cdis2[ ] = {"TEMP: . C"} ;
uchar code cdis3[ ] = {" DS18B20 ERR0R "} ;
uchar code cdis4[ ] = {" PLEASE CHECK "} ;
uchar code cdis5[ ] = {"Zhong Qian Peng"} ; //开始滚动界面
uchar code cdis6[ ] = {"Communication 1"} ;
uchar code cdis7[ ] = {"!!!!Warning!!!!"} ; //过温语句
uchar code cdis8[ ] = {"---OVER TEMP---"} ;
uchar code cdis9[ ] = {"Please set temp!"} ; //设定温度
uchar code cdis10[ ] = {"Max Temp C"} ;//可设两位
uchar
bai,shi,ge,xiaoshu1,xiaoshu2,xiaoshu3,xiaoshu4,fuhao,th_temp,tl_temp; char set=30;//set存有设定的温度,设初值为30
#define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
/*******************************************************************
* 两个延时函数 *
*******************************************************************/
//<----------1us----------->
void Delay(unsigned int num)
{
while( --num ) ;
}
//<----------1ms----------->
void delay1(int ms)
{
unsigned char y ;
while(ms--)
{
for(y = 0 ; y<250 ; y++)
{
_nop_() ;
_nop_() ;
_nop_() ;
_nop_() ;
}
}
}
void warning() //蜂鸣器发声
{speaker=1;delay1(1);speaker=0;delay1(1); }
/******************************************************************
* 检查LCD忙状态 * * lcd_busy为1时,忙,等待。

lcd-busy为0时,闲,可写指令与数据。

*
******************************************************************/
bit lcd_busy()
{
bit result ;
lcdrs = 0 ;
lcdrw = 1 ;
lcden = 1 ;
delayNOP() ;
result = (bit)(P0&0x80) ;
lcden = 0 ;
return(result) ;
}
/******************************************************************
* 写指令数据到LCD *
* RS=L,RW=L,E=高脉冲,D0-D7=指令码。

*
******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy()) ;
lcdrs = 0 ;
lcdrw = 0 ;
lcden = 0 ;
_nop_() ;
_nop_() ;
P0 = cmd ;
delayNOP() ;
lcden = 1 ;
delayNOP() ;
lcden = 0 ;
}
/******************************************************************* * 闪动子程序,闪动1次 * *******************************************************************/
void flash()
{
delay1(600); //控制停留时间
lcd_wcmd(0x08); //关闭显示
delay1(200); //延时
lcd_wcmd(0x0c); //开显示
delay1(200);
}
/*******************************************************************
* 写显示数据到LCD *
* RS=H,RW=L,E=高脉冲,D0-D7=数据。

*
*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy()) ;
lcdrs = 1 ;
lcdrw = 0 ;
lcden = 0 ;
P0 = dat ;
delayNOP() ;
lcden = 1 ;
delayNOP() ;
lcden = 0 ;
}
/*************************************
/* LCD初始化设定 *
/*************************************/
void lcd_init()
{
delay1(15) ;
lcd_wcmd(0x01) ; //清除LCD的显示内容
lcd_wcmd(0x38) ; //16*2显示,5*7点阵,8位数据 delay1(5) ;
lcd_wcmd(0x38) ;
delay1(5) ;
lcd_wcmd(0x38) ;
delay1(5) ;
lcd_wcmd(0x0c) ; //显示开,关光标
delay1(5) ;
lcd_wcmd(0x06) ; //移动光标
delay1(5) ;
lcd_wcmd(0x01) ; //清除LCD的显示内容
delay1(5) ;
}
/*********************
* 设定显示位置 *
*********************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80) ; //数据指针=80+地址变量
}
/******************************************
* 初始化ds1820 *
/******************************************/
Init_DS18B20()
{
DQ = 1 ; //DQ复位
Delay(8) ; //稍做延时
DQ = 0 ; //单片机将DQ拉低
Delay(90) ; //精确延时大于 480us
DQ = 1 ; //拉高总线
Delay(8) ;
presence = DQ ; //如果=0则初始化成功 =1则初始化失败 Delay(100) ;
DQ = 1 ;
return(presence) ; //返回信号,0=presence,1= no presence }
/****************************************************
/* 向DS18B20读和写一个字节 *
/****************************************************/
uchar ReadOneChar()
{
uchar i = 0 ;
uchar dat = 0 ;
for (i =8 ; i > 0 ; i--)
{
DQ = 0 ; // 给脉冲信号
dat >>= 1 ;
DQ = 1 ; // 给脉冲信号
if(DQ)
dat |= 0x80 ;
Delay(4) ;
}
return (dat) ;
}
void WriteOneChar(uchar dat)
{
unsigned char i = 0 ;
for (i = 8 ; i > 0 ; i--)
{
DQ = 0 ;
DQ = dat&0x01 ;
Delay(5) ;
DQ = 1 ;
dat>>=1 ;
}
}
/******************************************************************* * 读取温度 * *******************************************************************/
void Read_Temperature()
{
Init_DS18B20() ;
WriteOneChar(0xCC) ; // 跳过读序号列号的操作
WriteOneChar(0x44) ; // 启动温度转换
Init_DS18B20() ;
WriteOneChar(0xCC) ; //跳过读序号列号的操作
WriteOneChar(0xBE) ; //读取温度寄存器
tl_temp=ReadOneChar();//低八位
th_temp=ReadOneChar();//高八位
T=0xff*th_temp+tl_temp ;//转存
Temp=(0xff*th_temp+tl_temp)/16;
}
/******************************************************************* * 显示键值 * *******************************************************************/ void Disp_key()
{
lcd_pos(0x49) ;
lcd_wdat(set/10+0x30);
lcd_pos(0x4a) ;
lcd_wdat(set%10+0x30);
lcd_pos(0x4b) ; //0x4e写"°"的字码
lcd_wdat(0xDF) ;
}
/******************************************************************* * 读取键值 * *******************************************************************/ char Read_key()
{
bit flag=0;
while(!flag) //按下K3就退出循环套
{
Disp_key();//显示
if(!K7)
{
delay1(50);
if(K7)
{
flag=1;
}
}
if(!K5)
{
delay1(50);
if(K5)
{
set++;if(set==100){set=0;}
}
}
if(!K6)
{
delay1(50);
if(K6)
{
set--;if(set==-1){set=99;}
}
}
}
return set;
}
/******************************************************************* * 显示温度 * *******************************************************************/
void Disp_Temperature()
{
if(!(T&0xf000))//高八位中的高四位为符号信息全0为正号,全1为负号 {
fuhao=0x2b; //正数处理
T=T*0.0625;
bai=T/100;
shi=(T%100)/10;
ge=(T%100)%10;
xiaoshu1=(T&0x000f)*625/1000;
xiaoshu2=(T&0x000f)*625/1000/100;
xiaoshu3=(T&0x000f)*625%1000%100/10;
xiaoshu4=(T&0x000f)*625%1000/100%10;
}
else
{
fuhao=0x2d; //负数处理
T=((~T)+1)*0.0625;//T取反加1再乘0.0625即可得到实际温度的绝对值
bai=T/100;
shi=(T%100)/10;
ge=(T%100)%10;
xiaoshu1=(T&0x000f)*625/1000;
xiaoshu2=(T&0x000f)*625%1000/100;
xiaoshu3=(T&0x000f)*625%1000%100/10;
xiaoshu4=(T&0x000f)*625%1000/100%10;
}
//<-----为0高位消隐处理,技巧:0x50+0x30就为空白字码了
if(!bai)
{
bai=0x50;
if(!shi){shi=0x50;}
}
lcd_pos(0x45) ; //0x45写符号
lcd_wdat(fuhao);
lcd_pos(0x46) ; //0x46写百位
lcd_wdat(bai+0x30);
lcd_pos(0x47) ; //0x47写十位
lcd_wdat(shi+0x30);
lcd_pos(0x48) ; //0x48写个位
lcd_wdat(ge+0x30) ;
//0x48写小数点,在数表中
lcd_pos(0x4a) ;//0x4a写小数点后1位
lcd_wdat(xiaoshu1+0x30);
lcd_pos(0x4b) ; //0x4b写小数点后2位
lcd_wdat(xiaoshu2+0x30);
lcd_pos(0x4c) ; //0x4c写小数点后3位
lcd_wdat(xiaoshu3+0x30);
lcd_pos(0x4d) ; //0x4d写小数点后4位
lcd_wdat(xiaoshu4+0x30);
lcd_pos(0x4e) ; //0x4e写"°"的字码
lcd_wdat(0xDF) ;
}
/*******************************************************************
* 开机界面 *
*******************************************************************/
void gundong()
{
uchar i,j,k=1 ;
lcd_init() ; //初始化LCD while(k--) { lcd_wcmd(0x01); //清除LCD的显示内容
delay1(5);
lcd_pos(0x10); //设置显示位置为第一行第17

i = 0;
while(cdis5[i] != '\0') { //查表显示字符"
"
lcd_wdat(cdis5[i]);
i++;
}
lcd_pos(0x50); //设置显示位置为第二行第17列
i = 0;
while(cdis6[i] != '\0') {
lcd_wdat(cdis6[i]); //查表显示字符" "
i++;
}
for(j=0;j<16;j++) //向左移动16次
{
lcd_wcmd(0x18); //字符同时左移一格
delay1(100); //控制移动时间
} flash(); //闪动2次
}
}
/*******************************************************************
* 临界温度设定界面 *
*******************************************************************/
void Set_temp ()
{
uchar i = 0 ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
while(cdis9[i] != '\0')
{ //显示字符
lcd_wdat(cdis9[i]) ;
i++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
i = 0 ;
while(cdis10[i] != '\0')
{
lcd_wdat(cdis10[i]) ; //显示字符
i++ ;
}
}
/*******************************************************************
* WELCOM TO USE! 显示菜单 *
*******************************************************************/
void Ok_Menu ()
{
uchar i = 0 ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
while(cdis1[i] != '\0')
{ //显示字符
lcd_wdat(cdis1[i]) ;
i++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
i = 0 ;
while(cdis2[i] != '\0')
{
lcd_wdat(cdis2[i]) ; //显示字符
i++ ;
}
}
/******************************************************************** * DS18B20 ERROR 显示菜单 *
********************************************************************/ void Error_Menu ()
{
uchar m ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //设置显示位置为第一行的第1个字符 m = 0 ;
while(cdis3[m] != '\0')
{ //显示字符
lcd_wdat(cdis3[m]) ;
m++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
m = 0 ;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]) ; //显示字符
m++ ;
}
}
/********************************************************************
* OVER TEMP 显示菜单 *
********************************************************************/
void OVER_TEMP ()
{
uchar i ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //设置显示位置为第一行的第1个字符 i = 0 ;
while(cdis7[i] != '\0')
{ //显示字符
lcd_wdat(cdis7[i]) ;
i++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
i = 0 ;
while(cdis8[i] != '\0')
{
lcd_wdat(cdis8[i]) ; //显示字符
i++ ;
}
}
/*******************************************************
* 主函数上电温度误判怎么办?* *
*因为ds18b20内部ad转换时间大约750mS(12位ad), *
*所以上电后750ms后才能将温度存在寄存器里待读, *
*解决方法,进入主程序先转换采集一次DS18B20, *
*先不送显示,然后延时约1秒,然后再进入大循环进行采集,*
*送显示就可以了 *
*******************************************************/
void main()
{
gundong();
Set_temp();Read_key();//设定温度(设定中就包含显示)
Read_Temperature() ; delay1(800);//上电误判解决方案
while(1)
{
Read_Temperature() ;
if( presence)
{
Error_Menu ();
while(presence)
{ warning();Init_DS18B20(); }
/*被判插上温度传感器后*/
Read_Temperature();
delay1(800);
Read_Temperature();//修复误判解决方案
delay1(800);
Read_Temperature();
delay1(800);
Read_Temperature();
}
else if(Temp<set&&!presence)
{
Ok_Menu ();
while(Temp<set&&!presence)
{ Read_Temperature() ;Disp_Temperature();} }
else if(Temp>=set&&!presence)
{
OVER_TEMP ();canong(); //音乐在此只响一次
while(Temp>=set&&!presence)
{ Read_Temperature() ;}
}
}
}。

相关文档
最新文档