基于DS18B20数字温度传感器的温度计设计
基于DS18B20数字温度传感器的温度计设计
本报告为哈尔滨工业大学电子与信息工程学院大二学期微机原理课程的课设报告。请注意,本文所述代码均在Quartus II 13.0程序内使用汇编语言运行。
一、课程设计任务要求
利用数字温度传感器DS18B20与AT89C51单片机结合来测量温度,并在LED数码管上显示相应的温度值。温度测量范围为-55~125℃,精确至0.5℃。测量的温度采用数字显示,用三位共阳极LED数码管来实现温度显示。
二、工作原理
DS18B20数字温度传感器是美国DALLAS半导体公司推出的一种改进型具有单总线接口的智能温度传感器。与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字读数方式。DS18B20的基本性能及详细资料请参考相关资料。
三、单片机应用系统设计及原理图
DS18B20数字温度传感器数据端口DQ接于P1.7,单片机接电源和晶振,八位共阳数码管位选接于P1.2~P1.6,断码接于P0.0~P0.7并连接排阻。
四、实现方法及扩展创新
-
基本功能实现方法
利用 DS18B20 数字温度传感器的数据传输机制编写程序,将温度数值从温度传感器中取回到 AT89C51 之中,再根据数据的转换形式,在单片机中对数据进行处理变换成十进制,并动态显示在数码管中。 -
扩展创新设计
根据实验要求:精度在 0.5℃范围内,则不必四舍五入,取出整数部分直接处理,只需考查数据的小数第一位,来决定小数点显示位置显示 0 或者 5,便可保证精度;并且在个位位置附加上小数点;最后补充符号位,负温度时显示负号。
五、实现步骤
首先需要了解 DS18B20 的数据传输方式,因为这一芯片只有一个数据通信口,需要遵守严格的时序,脉冲的规则,介绍如下。
首先设定 DQ 为总线数据位,连接于 P1.7。
DQ BIT P1.7
1.复位功能
主机首先发出一个 480~960us 的低电平脉冲,然后释放总线变为高电平,并在随后的480us 时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。
作为从器件的 DS18B20 在一上电后就一直在检测总线上是否有 480-960 us 的低电平出现,如果有,在总线转为高电平后等待 15-60us 后将总线电平拉低60~240us 做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。
这一段程序设计加入 FLAG 位变量作为传感器是否相应,正常工作的标志:
FLAG BIT F0
INIT_1:SETB DQ
NOP
CLR DQ
MOV R0,#0FBH
TSR1: DJNZ R0,TSR1
SETB DQ
MOV R0,#25H
TSR2: JNB DQ,TSR3
DJNZ R0,TSR2
TSR3: SETB FLAG
MOV R0,#06BH
TSR4: DJNZ R0,TSR4
SETB DQ
RET
2.写入操作
写周期最少为 60us,最长不超过 120us。写周期一开始做为主机先把总线拉低1us 表示写周期开始。随后若主机想写 0,则继续拉低电平最少 60us 直至写周期结束,然后释放总线为高电平。若主机想写 1,在一开始拉低总线电平 1us 后就释放总线为高电平,一直到写周期结束。而做为从机的 DS18B20 则在检测到总线被拉底后等待 15 us 然后从 15us 到 45us 开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为 0。
写入要遵守规则,需要先复位,跳过 ROM,才能进行读写,更改初值等操作。
WRITE:MOV R2,#8
CLR C
WR1: CLR DQ
MOV R3,#6
DJNZ R3,$
RRC A
MOV DQ,C
MOV R3,#23
DJNZ R3,$
SETB DQ
NOP
DJNZ R2,WR1
SETB DQ
RET
3.读数操作
对于读数据操作时序也分为读 0 时序和读 1 时序两个过程。读时隙是从主机把单总线拉低之后,在 1us 之后就得释放单总线为高电平,以让 DS18B20 把数据传输到单总线上。DS18B20 在检测到总线被拉低 1us 后,便开始送出数据,若是要送出0 就把总线拉为低电平直到读周期结束。若要送出 1 则释放总线为高电平。主机在一开始拉低总线 1us 后释放总线,然后在包括前面的拉低总线电平 1us在内的 15us 时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。采样期内总线为高电平则确认为 1。完成一个读时序过程,至少需要 60us 才能完成。
读数代码如下,在读数的时候要同样要复位,跳 ROM,写入操作码再读写。
READ: MOV R4,#2
MOV R1,#29H
REE0: MOV R2,#8
REE1: CLR C
SETB C
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R3,#7
DJNZ R3,$
MOV C,DQ
MOV R3,#23
DJNZ R3,$
RRC A
DJNZ R2,REE1
MOV @R1,A
DEC R1
DJNZ R4,REE0
RET
4.设定温度分辨率
由于温度传感器的温度精度为 0.0625℃,对于要求的精度太高,可以适当减少精度,使小数点后四位仅余一位有效,在符合条件的情况下理想化后三位。
FBLCHANGE:
LCALL INIT_1
MOV A,#0CCH
LCALL WRITE
MOV A,#1FH
LCALL WRITE
RET
5.主程序编写
主程序应完全按照通信规则进行。
DS18B20 单线通信功能是分时完成的,他有严格的时隙概念,如果出现序列混乱,1-WIRE 器件将不响应主机,因此读写时序很重要。系统对 DS18B20 的各种操作必须按协议进行。根据 DS18B20 的协议规定,微控制器控制 DS18B20 完成温度的转换必须经过以下三个步骤 :
- 每次读写前对 DS18B20 进行复位初始化;
- 发送一条 ROM 指令;
- 发送存储器指令。
现在我们做的是让DS18B20进行一次温度转换,那具体操作如下:
- 主机先作复位操作;
- 主机再写跳过ROM的操作(CCH)命令;
- 然后主机接着写个转换温度的操作命令,后面释放总线至少 1s,让DS18B20 完成转换的操作。在这里要注意的是每个命令字节在写的时候都是低字节先写,例如 CCH 的二进制为 11001100,在写到总线上时要从低位开始写,写的顺序是“1、1、0、0、1、1、0、0”。
读取 RAM 内的温度数据同样也要接照三个步骤:
- 主机发出复位操作并接收 DS18B20 的应答(存在)脉冲。
- 主机发出跳过对 ROM 操作的命令(CCH)。
- 主机发出读取 RAM 的命令(BEH),随后主机依次读取 DS18B20 发出的从第0 到第 8,共九个字节的数据。如果只想读取温度数据,那在读完第 0 和第 1 个数据后就不再理会后面 DS18B20 发出的数据即可。同样读取数据也是低位在前的。
故主函数设置如下:
MAIN: LCALL INIT_1
LCALL FBLCHANGE
LCALL GET_TEMP
AJMP CHANGE
GET_TEMP:
SETB DQ
LCALL INIT_1
JB FLAG,TSS2
RET
TSS2: MOV A,#0CCH
LCALL WRITE
MOV A,#44H
LCALL WRITE
LCALL DISPLAY
LCALL INIT_1
MOV A,#0CCH
LCALL WRITE
MOV A,#0BEH
LCALL WRITE
LCALL READ
RET
6.数据处理与显示
对于传回的数据,DS18B20 的数据格式如下:
温度 | 二进制表示 | 十六进制表示 |
---|---|---|
+125 | 00000111 11010000 | 07D0H |
+25.0625 | 00000001 10010001 | 0191H |
+10.125 | 00000000 10100010 | 00A2H |
+0.5 | 00000000 00001000 | 0008H |
0 | 00000000 00000000 | 0000H |
-0.5 | 11111111 11111000 | FFF8H |
-10.125 | 11111111 01011110 | FF5EH |
-25.0625 | 11111110 01101111 | FE6FH |
-55 | 11111100 10010000 | FC90H |
故我们可以由如下步骤分析:
- 判断温度的正负。首先可知,取回原始数据的最后四位无效,这就保证了数据在取回绝对值时不会溢出。此时检查数据的最高位,如果是正数,则正常执行;如果是负数,则进行取反加一的操作,得到绝对值,并保留原数,为判断是否显示负号做准备。
- 取出绝对值放入地址中作为二进制整数。利用进位标志位 C,将八高位的后四位传入低八位的前四位,得到绝对值。
- 判断小数后第一位是 0 还是 1,得到小数位显示为 0 或 5。这时需要在新地址存储00H,05H,为显示做准备。 此时我们可以发现对于绝对值小数位为.0~.4 的,则显示的十分位置 0,绝对值小数位为.5~.9 的,则显示的十分位置 5,且不影响去掉小数位的整数值,整数值依旧存在。由此可知,显示数字和真实数字的关系并不符合四舍五入,但在精度范围之内,这样做减少了数据处理的复杂度,增加了数码管显示数量,是本实验的创新之处。
- 整数部分转为十进制。DIV 指令提供了方便,我们只需执行两次除以10 的操作,便可以得到个,十,百位。
- 显示:显示采用共阳八位数码管。首先由数据的正负,判断是否输出负号(g 亮,即 BFH),否则输出全灭状态(即 FFH)。再依次输出个十百位,注意个位为表达准确,需要加上小数点,故要对正常的数码表最高位置零(即最高位减 8),故个位要查最高位置零后的表以显示小数点。再根据小数位提前存储的00H,05H,判断小数第一位的状态,输出相应的 0 和 5。延时函数不必多说。
实际代码如下:
CHANGE:
MOV A,29H
MOV 26H,29H
MOV 25H,28H
MOV 24H,28H
MOV C,25H.7
JNC SN1
MOV A,25H
CPL A
MOV 25H,A
MOV A,26H
CPL A
INC A
MOV 26H,A
MOV 29H,26H
MOV 28H,25H
SN1: MOV C,28H.0
RRC A
MOV C,28H.1
RRC A MOV C,28H.2
RRC A MOV C,28H.3
RRC A
JC SL0
MOV 27H,#00H
AJMP SL5
SL0: MOV 27H,#05H
SL5: MOV 29H,A
LCALL DISPLAY
LJMP MAIN
DISPLAY:
MOV A,29H
MOV B,#10
DIV AB
MOV ABIT,B
MOV B,#10
DIV AB
MOV BBIT,B
MOV CBIT,A
MOV R0,#4
DPL1: MOV R1,#250
DPL2: MOV C,24H.7
JNC DPL3
MOV P0,#0BFH
SETB P1.2
LCALL DELAY
CLR P1.2
AJMP DPL4
DPL3: MOV P0,#0FFH
SETB P1.2
LCALL DELAY
CLR P1.2
DPL4: MOV DPTR,#TAB
MOV A,27H
MOVC A,@A+DPTR
MOV P0,A
SETB P1.6
LCALL DELAY
CLR P1.6
MOV A,ABIT
MOV DPTR,#TAB1
MOVC A,@A+DPTR
MOV P0,A
SETB P1.5
LCALL DELAY
CLR P1.5
MOV A,BBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P1.4
LCALL DELAY
CLR P1.4
MOV A,CBIT
MOVC A,@A+DPTR
MOV P0,A
SETB P1.3
LCALL DELAY
CLR P1.3
DJNZ R1,DPL2
DJNZ R0,DPL1
RET
DELAY:MOV R5,#10
DEL0: MOV R6,#1
DEL1: MOV R7,#20
DEL2: DJNZ R7,DEL2
DJNZ R6,DEL1
DJNZ R5,DEL0
RET
TAB:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
TAB1:
DB 40H,79H,24H,30H,19H,12H,02H,78H,00H,10H
至此,课程设计原理全部介绍完毕。
六、数据记录与结果分析
经过试验得到如下仿真结果:
-32.3℃显示结果
49.6℃显示结果
113.2℃显示结果
七、实验程序
完整程序代码:
;===================================================================================
; Main.asm file generated by New Project wizard
;
; Created: 周四 6 月 7 2018
; Processor: 80C51
; Compiler: ASEM-51 (Proteus)
;===================================================================================
$NOMOD51
$INCLUDE (8051.MCU)
;===================================================================================
; DEFINITIONS
;===================================================================================
;===================================================================================
; VARIABLES
;===================================================================================
;===================================================================================
; RESET and INTERRUPT VECTORS
;===================================================================================
FLAG BIT F0 ; 声明传感器复位返回的标志位
DQ BIT P1.7 ; 定义DQ 作为数据传输端口名
ABIT EQU 35H
BBIT EQU 36H
CBIT EQU 37H ; 固定个,十,百位的存储位置,名称
ORG 0000H
AJMP MAIN
ORG 0100H
;主程序
MAIN: LCALL INIT_1 ; 复位
LCALL FBLCHANGE ; 改变温度的初始分辨率为9位
LCALL GET_TEMP ; 得到温度
AJMP CHANGE ; 跳转到数据处理子程序
;复位程序
INIT_1:SETB DQ ; 总线释放
NOP ; 保持高电平,延时
CLR DQ ; 总线置 0,请求响应
MOV R0,#0FBH
TSR1: DJNZ R0,TSR1 ; 延时
SETB DQ ; 再释放
MOV R0,#25H
TSR2: JNB DQ,TSR3 ; 改变为 0,则代表得到对应
DJNZ R0,TSR2 ; 未得到则继续等待,判断
TSR3: SETB FLAG ; 得到相应则标志位置 1,代表传感器正常存在
MOV R0,#06BH
TSR4: DJNZ R0,TSR4 ; 延时
SETB DQ ; 释放总线,完成复位
RET
;改变温度分辨率
FBLCHANGE:
LCALL INIT_1 ; 复位
MOV A,#0CCH ; 跳过ROM
LCALL WRITE ; 把A写入传感器
MOV A,#1FH ; 改变温度分辨率为9
LCALL WRITE ; 把A写入传感器
RET
:得到温度并转换
GET_TEMP:
SETB DQ ; 释放总线
LACALL INIT_1 ; 复位
JB FLAG,TSS1 ; 若传感器不存在,则直接返回主程序
RET
TSS2: MOV A,#0CCH
LCALL WRITE ; 执行跳过ROM指令
MOV A,#44H
LCALL WRITE ; 执行测温指令
LCALL DISPLAY ; 不仅延时,还让程序完全生效前数码管置零
LCALL INIT_1 ; 复位
MOV A,#0CCH
LCALL WRITE ; 执行跳过ROM置零
MOV A,#0BEH
LCALL WRITE ; 执行读取温度数据指令
LCALL READ ; 跳转至通信子程序
RET
;写入数据 ; 注:不可超过120us,否则无法写入
WRITE:MOV R2,#8 ; 写入八位二进制码,即循环次数
CLR C ; 进位标志位初始置零
WR1: CLR DQ ; 拉低总线为写入做准备
MOV R3,#6
DJNZ R3,$ ; 快速延时
RRC A
MOV DQ,C ; 将A又循环写入C,写入总线以输入到传感器
MOV R3,#23
DJNZ R3,$ ; 快速延时
SETB DQ ; 释放,表示此位写入完毕
NOP
DJNZ R2,WR1 ; 循环八次,一次写入八位
SETB DQ ; 释放总线
RET
;读入数据
READ: MOV R4,#2 ; 读取两个八位数据,是外层循环次数
MOV R1,#29H ; 立即数寻址给定存储位置
REE0: MOV R2,#8 ; 给定数据位数,是内层循环次数
REE1: CLR C ; 进位标志位初始置零
SETB C
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ ; 输入脉冲并持续2-3个机器周期
MOV R3,#7
DJNZ R3,$ ; 快速延时,等待传感器响应
MOV C,DQ ; 按位读出
MOV R3,#23
DJNZ R3,$ ; 快速延时
RRC A ; 把C存入A内
DJNZ R2,REE1 ; 循环8次
MOV @R1,A ; 存储A
DEC R1 ; 更换地址
DJNZ R4,REE0 ; 循环2次
RET
;数据处理函数
CHANGE:
MOV A,29H
MOV 26H,29H
MOV 25H,28H
MOV 24H,28H ; 在24H存储原始数据防止丢失
MOV C,25H.7 ; 存储符号位进C
JNC SN1 ; 判断温度的正负,正数则跳过转补码程序
MOV A,25H
CPL A ; 取补码,由于无效位置1,25H不必担心数据溢出
MOV 25H,A
MOV A,26H
CPL A
INC A ; 由于是末位,需要加一
MOV 26H,A
MOV 29H,26H
MOV 28H,25H ; 在26H,25H中操作后放回29H,28H
SN1: MOV C,28H.0 ; 正负温度到此均得到整数部分绝对值
RRC A
MOV C,28H.1
RRC A
MOV C,28H.2
RRC A
MOV C,28H.3 ; 分别循环,存入A内,连续4次滤掉小数部分
RRC A ; 可分析A内八位恰为整数部分(最高位为0)
JC SL0
MOV 27H,#00H
AJMP SL5
SL0: MOV 27H,#05H
SL5: MOV 29H,A ; 为小数部分显示0和5做准备
LCALL DISPLAY ; 转入显示函数
LJMP MAIN ; 返回主函数,程序执行完毕
;显示函数
DISPLAY:
MOV A,29H
MOV B,#10
DIV AB
MOV ABIT,B
MOV B,#10
DIV AB
MOV BBIT,B
MOV CBIT,A ; 此时可知CBA即为百十个位
MOV R0,#4 ; 循环显示
DPL1: MOV R1,#250 ; 长时间延时循环
DPL2: MOV C,24H.7
JNC DPL3
MOV P0,#0BFH
SETB P1.2
LCALL DELAY
CLR P1.2
AJMP DPL4
DPL3: MOV P0,#0FFH
SETB P1.2
LCALL DELAY
CLR P1.2 ; 符号位判断显示
DPL4: MOV DPTR,#TAB
MOV A,27H
MOVC A,@A+DPTR
MOV P0,A
SETB P1.6
LCALL DELAY
CLR P1.6 ; 小数位判断显示
MOV A,ABIT
MOV DPTR,#TAB1
MOVC A,@A+DPTR
MOV P0,A
SETB P1.5
LCALL DELAY
CLR P1.5
MOV A,BBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB P1.4
LCALL DELAY ; 个十百位显示
CLR P1.4
MOV A,CBIT
MOVC A,@A+DPTR
MOV P0,A
SETB P1.3
LCALL DELAY
CLR P1.3
DJNZ R1,DPL2
DJNZ R0,DPL1
RET
;延迟函数
DELAY:MOV R5,#10
DEL0: MOV R6,#1
DEL1: MOV R7,#20
DEL2: DJNZ R7,DEL2
DJNZ R6,DEL1
DJNZ R5,DEL0
RET
TAB: ; 正常阳极数码0-9
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
TAB1: ; 带小数点的个位显示数码0-9
DB 40H,79H,24H,30H,19H,12H,02H,78H,00H,10H
LOOP:
JMP LOOP ;====================================================================
END