本帖最后由 51黑黑黑 于 2016-3-3 00:58 编辑
(一) 数字温度传感器DSl8B20介绍
以下为 DS1820 的详细特性 l 独特的单线接口仅需一个端口引脚进行通讯 l 简单的多点分布应用 l 无需外部器件 l 可通过数据线供电 l 零待机功耗 l 测温范围-55~+125℃,以0.5℃递增。华氏器件-67~+2570F,以0.90F 递增 l 温度以 9 位数字量读出 l 温度数字量转换时间 200ms(典型值) l 用户可定义的非易失性温度报警设置 l 报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件 l 应用包括温度控制、工业系统、消费品、温度计或任何热感测系统
由上表可见DS18B20适用电压为3V~5V,有更宽的电压适用范围,DS18B20可以程序设定9~12 位的分辨率,精度为±0.5°C。可选更小的封装方式。用户设的分辨率和报警温度可以存储在EEPROM 中,掉电后依然保存。DS18B20的性能是新一代产品中最好的。 DS1822与DS18B20 软件兼容,是DS18B20的简化版本。省略了存储用户定义报警温度、分辨率参数的EEPROM,精度降低为±2°C,适用于对性能要求不高,成本控制严格的应用,是经济型产品。 每只D51820都可以设置成两种供电方式即数据总线供电方式和外部供电方式,采取数据总线供电方式可以节省一根导线但完成温度测量的时间较长。采取外部供电方式则多用一根导线但测量速度较快。 每只DSl8B20包括一个唯一的64位长的序号,该序号值存放在DSl8B20内部的ROM(只读存贮器)中。开始8位是产品类型编码,接着的48位是每个器件唯一的序号,最后8位是前面56位的CRC(循环冗余校验)码。因为每一个DSl8B20在出厂时已经给定了唯一的序号,因此在同一条单线总线上可以连接多个DSl8B20。 DSl8B20的存储器由9个字节组成,存储器结构示于下图。存储器有一个暂存SRAM和一个存储高低报警触发值TH和TL的非易失性电可擦除EEPROM组成。注意当报警功能不使用时,TH和TL寄存器可以被当作普通寄存器使用。 DSl8B20的引脚如下图l所示: (二)DSl8B20工作过程及时序
主机控制DS18B20完成温度转换必须经过三个步骤:初始化、ROM操作指令、存储器操作指令。必须先启动DS18B20开始转换,再读出温度转换值。 1、初始化
单总线上的所有处理均从初始化开始。
2、ROM操作命令
总线主机检测到DSl8B20的存在便可以发出ROM操作命令。

3、存储器操作命令

4、时序
1)复位:对DS18B20操作之前,首先要将它复位。复位时序为:
(1)主机将信号线置为低电平,时间为400~960μS。
(2)主机将信号线置为高电平,时间为15~60μS。
(3)DS18B20发出60~240μS 的低电平作为应答信号。主机收到此信号后,才能对DS18B20作其它操作。

2)写操作:主机将信号线从高电平拉至低电平,产生写起始信号。从信号线的下降沿开始,在15~60μS的时间内,DS18B20对信号线检测,如信号线为高电平,则写1,如信号线为O,则写0,从而完成了一个写周期。在开始另一个写周期前,必须有1μ S以上的 高电平恢复期。

3)读操作:主机将信号线从高电平拉低至低电平1μ S以上,再使数据线升为高电平,产生读起始信号。从主机将信号线从高电平拉低至低电平起15~60μS的时间内,DS18B20将数据放到信号线上,供主机读取。从而完成了一个读周期。在开始另一个读周期前,必须有1μ S以上的高电平恢复期。

(三)温度与数据关系
DS18B20在出厂时配置为12位温度数据,读取温度时共读取16位,16位数字摆放是从低位到高位,存储在18B20的两个8比特的RAM中,二进制数中的前面5位是符号位,如果测得的温度大于0,这5位为0,此时把温度高字节的低3位与温度低字节的高4位合并成一个字节再转成十进制数是温度的整数部分。温度低字节的低4位乘以0.0625或除以16所测的温度的小数部分。如果温度小于0,这5位为1,测到的数值需要取反加1,然后再把温度高字节的低3位与温度低字节的高4位合并成一个字节再转成十进制数就是温度的整数部分。温度低字节的低4位乘以0.0625或除以16所测的温度的小数部分。 (四)DS18B20中的低温触发器TL、高温触发器TH,用于设置低温、高温的报警数值。DS18B20完成一个周期的温度测量后,将测得的温度值和TL、TH相比较,如果小于TL,或大于TH,则表示温度越限,将该器件内的告警标志位置位,并对主机发出的告警搜索命令作出响应。需要修改上、下限温度值时,只需使用一个功能命令即可对TL、TH写入,十分方便。 (五)具体操作举例: 现在我们要做的是让DS18B20进行一次温度的转换,那具体的操作就是: 1、主机先作个复位操作, 2、主机再写跳过ROM的操作(CCH)命令, 3、然后主机接着写个转换温度的操作命令,后面释放总线至少一秒,让DS18B20完成转换的操作。在这里要注意的是每个命令字节在写的时候都是低字节先写,例如CCH的二进制为11001100,在写到总线上时要从低位开始写,写的顺序是“零、零、壹、壹、零、零、壹、壹”。整个操作的总线状态如下图。 
读取RAM内的温度数据。同样,这个操作也要接照三个步骤。 1、主机发出复位操作并接收DS18B20的应答(存在)脉冲。 2、主机发出跳过对ROM操作的命令(CCH)。 3、主机发出读取RAM的命令(BEH),随后主机依次读取DS18B20发出的从第0一第8,共九个字节的数据。如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可。同样读取数据也是低位在前的。整个操作的总线状态如下图: (六)单片机程序代码 ;采用stc11f04e单片机,晶振3.6864MHZ,通讯速率9600,30H,32H存放温度值的高字节,31H,33H存放温度值的低字节
;34H用于保存温度的小数部分;35H用于保存整数部分;36H用于保存温度;38H39H用于保存小数部分,20H.1保存正负温度标志
ORG 0000H
AJMP MAIN;转入主程序
ORG 0003H ;外部中断P3.2脚INT0入口地址
RETI
ORG 000BH;中断陷阱
;LJMP CT
RETI
ORG 0013H;中断陷阱
RETI
ORG 0023H
;LJMP S
TPH DATA30H ;存放温度值的高字节
TPL DATA31H ;存放温度值的低字节
XS EQU 34H;用于保存温度的小数部分
ZS EQU 35H;用于保存整数部分
P1M0 DATA 92H
P1M1 DATA 91H
DQ EQU P3.5;DS18B20的数据口位
WDT_CONTR EQU 0C1H
AUX EQU 0A2H ;P3.0RXD-P3.1TXD TO P1.6RXD-P1.7TXD
FLAG_1 EQU 20H.1 ;接收到下行串口发来数据标志p1.6
MAIN: MOV SCon,#50h; 方式1,REN=1.SM0,SM1,SM2,REN,TB8,RB8,TI,RI
MOV TMOD,#21H;波特率发生器T1工作在模式2上
MOV TH1,#0FFH;预置初值(按照波特率9600BPS预置初值) 24M=9600=F3 3.6864=FF=9600, 1200=f8
MOV TL1,#0FFH;预置初值(按照波特率9600BPS预置初值) 13.56=9600倍频=F9
MOV TH0,#88H ;8800=12t,7000=stc1t
MOV TL0, #00H
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETBPS ;串口中断优先
SETBTR1 ;启动定时器1
MOVP1M0,#01000000b ; P1M0=0 P1M1=0双向口 P1M0=1 P1M1=0输入口 P1M0=0 P1M1=1推挽输出20ma
MOV P1M1,#10000000b
MOV WDT_CONTR ,#27H;;;;;;看门狗设置使能
CPL P3.2
QL: MOV A,#00H
MOV R2,#58 ;清数据区;;
MOV R0,#20H
QRAM: MOV @R0, A
INC R0
DJNZ R2, QRAM
; MOV WDT_CONTR ,#17H;喂狗
QW: CALL DELAY1
CALL DELAY1
CALL DELAY1
CALL DELAY1
;JNB FLAG_1,QQ
LCALL DS18B20
CALL FZJ
CLR FLAG_1
QQ: CPL P3.2
CALL DELAY1
CALL DELAY1
CALLDELAY1
CALL DELAY1
AJMP QL
DS18B20: ;CLR EA;
CALLDS18B20_Reset ;设备复位
MOVA,#0CCH ;跳过ROM命令
CALL DS18B20_WriteByte ;送出命令
MOVA,#044H ;开始转换 温度转换 44H启动DS18B20进行温度转换
CALL DS18B20_WriteByte ;送出命令
DELAY: ; MOV WDT_CONTR ,#17H;喂狗
JNBDQ,DELAY ;等待转换完成
CALLDS18B20_Reset ;设备复位
MOVA,#0CCH ;跳过ROM命令
CALL DS18B20_WriteByte ;送出命令
MOVA,#0BEH ;读暂存存储器读暂存器BEH读暂存器9个字节内容
CALLDS18B20_WriteByte ;送出命令
CALL DS18B20_ReadByte ;读温度低字节
MOVTPL,A ;存储数据
CALL DS18B20_ReadByte ;读温度高字节
MOVTPH,A ;存储数据
MOV A,TPH;30H
RLC A
MOV20H.1,c ;保存正负温度标志
JNCZH ;最高位是0为零上温度转ZH
;最高位是1为零下温度取反加1
MOVA,TPH;30H ;例如温度是-54.875度,源码=11001001 001XXXXX 例如温度72.75,30h=48h,31h=40h,加在一起是01001000(=30H)010xxxxx=(31H)
CPLA ;00110110=(30H)
MOV32H,A ;高位取反
MOVA,TPL;31H ;低位取反110XXXXX
CPLA ;110XXXXXX=(31H)
MOV33H,A ;保存高2位到(32h)=01H,最后转换成242H=578d,578*0.125=72.75
MOVA,#01H ;10110111=B7
ADD A,33H
MOV 33H,A
CLR A
ADDCA,32H ;例如温度是-54.875度=-439*.125,补码649h,-649h=1110 0100 1001
MOV32H,A ;结果是32h=01,33h=b7,合并成1b7h取反=00110110110,加1=00110110111为正码1b7h=439,39*.125=54.875
AJMP LS
ZH: MOV A,TPH;30H
MOV32H,A ;保存高2位到(32h)=02H,最后转换成242H=578d,578*0.125=72.75
MOV A,TPL
MOV33H,A ;保存到33h=01000010=42H
LS: MOV A,TPL
ANL A,#0FH ;存放温度的低字节的低四位决定小数部分
MOV XS,A ;获得小数部分34H
MOV A,TPL
ANL A,#0F0H
SWAP A
MOVZS,A ;35H存放温度的低字节的高四位
MOV A,TPH ;获取存放温度的高字节的低三位
ANL A,#07H
SWAPA
ORLA,ZS ;存放温度的低字节的高四位合并存放温度的高字节的低三位决定整数部分
MOV ZS,A
MOV B,#100;分离出百位,存放在R3中
DIV AB
MOV R3,A
MOV A,#10 ;余数继续分离十位和个位
XCH A,B
DIV AB
SWAP A
ORL A,B ;十位和个位拼装成BCD码
MOV 36H,A
MOV A,XS
MOV R0,#37H
MOVR2,#4
D0: MOV B,#10
MUL AB
MOV B,#16
DIV AB
MOV @R0,A
INC R0
MOV A,B
DJNZ R2,D0
MOV R0,#37H
MOV A,@R0
INC R0
SWAP A
ORL A,@R0
MOV 37H,A
INC R0
MOV A,@R0
INC R0
SWAP A
ORL A,@R0
MOV 38H,A
MOV 39H,#0AAH
RET ;20H.1保存正负温度标志
;**************************************
;延时X微秒(STC11f04e@3.6864M)
;不同的工作环境,需要调整此函数
;入口参数:R7
;出口参数:无DS18B20在出厂时以配置为12位,读取温度时共读取16位,所以把温度高字节的低3位与温度低字节的高4位合并成一个字节再转成十进制数是温度的整数部分。
;温度低字节的低4位乘以0.0625或除以16所测的温度的小数部分。
;还需要判断正负。前5个数字为符号位,当前5位为1时,读取的温度为负数;当前5位为0时,读取的温度为正数。
;**************************************
DelayXus: ;6 此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
NOP ;1
DJNZR7,DelayXus ;4
RET ;4
;DelayXus1: MOVR6,#255 ;6 此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同 6.7584=22/3.255
;DelayXus2: CALL DelayXus
; DJNZR6,DelayXus2 ;4
; RET ;4
;**************************************
;复位DS18B20,并检测设备是否存在
;入口参数:无
;出口参数:无
;**************************************
DS18B20_Reset:MOV WDT_CONTR,#37H;喂狗
CLRDQ ;送出低电平复位信号
MOVR7,#240 ;延时至少480us
CALL DelayXus
MOV R7,#240
CALL DelayXus
SETBDQ ;释放数据线
MOVR7,#60 ;等待60us
CALL DelayXus
MOV C,DQ ;检测存在脉冲
MOVR7,#240 ;等待设备释放数据线
CALL DelayXus
MOV R7,#180
CALL DelayXus
JCDS18B20_Reset ;如果设备不存在,则继续等待
RET
;**************************************
;从DS18B20读1字节数据
;入口参数:无
;出口参数:ACC
;**************************************
DS18B20_ReadByte:
CLR A
PUSH 0
MOV0,#8 ;8位计数器
ReadNext:
CLRDQ ;开始时间片
MOVR7,#1 ;延时等待
CALL DelayXus
SETBDQ ;准备接收
MOV R7,#1
CALL DelayXus
MOVC,DQ ;读取数据
RRC A
MOVR7,#60 ;等待时间片结束
CALL DelayXus
DJNZ 0,ReadNext
POP 0
RET
;**************************************
;向DS18B20写1字节数据
;入口参数:ACC
;出口参数:无
;**************************************
DS18B20_WriteByte:
PUSH 0
MOV0,#8 ;8位计数器
WriteNext:
CLRDQ ;开始时间片
MOVR7,#1 ;延时等待
CALL DelayXus
RRCA ;输出数据
MOV DQ,C
MOVR7,#60 ;等待时间片结束
CALL DelayXus
SETBDQ ;准备送出下一位数据
MOV R7,#1
CALL DelayXus
DJNZ 0,WriteNext
POP 0
RET
FZJ: MOVR0,#30H ;向主机发送35h单元开始的8个定时器时钟数据子程序 1B60000000600000
FZJ0: MOV R2,#0AH
FZJ1: CLR EA
ANLAUX,#07FH ;p3.0p3.1当串口
FZL1: MOV A, @R0
MOV SBUF, A
JNB TI, $
CLR TI
INC R0
DJNZ R2,FZL1
SETB EA
RET
DELAY2: MOV R5, #0FFH
DEL: MOV WDT_CONTR ,#17H;喂狗
DJNZ R5, DEL
RET
DELAY1: MOV R6, #0FFH
DELA: ACALL DELAY2
DJNZ R6, DELA
RET
END
带温度显示的LED电子表
下面的例子是利用18B20制作一个简单的带温度显示的LED电子表,电路原理图和显示结果如下图所示,晶体振荡器采用7.3128Mhz,如果用其它频率的晶体,需要改变延迟子程序DelayXus,其它程序结构不变,利用单片机的定时器0定时功能构成电子表,每天有9秒的误差,可以通过调整达到每月误差不到1秒,因为本机非常省电,可以长期带电运行,如遇停电,需要重新调整时钟,有2个按键分别调整时和分,调整比较方便,所以就不加时钟模块了,实验证明与鱼缸温度计比较18B20数字温度计还是比较准确的。下面给出了源程序代码,因为注释的比较详细,很容易看的懂。程序主要由初始化模块、定时器模块、温度采集模块组成。内存使用情况是2FH,2EH温度整数位显示区,2DH,2CH是温度小数位显示区,36H,35H是小时显示区,34H,33H分钟显示区,每隔5秒钟左右交替显示时钟和温度。25H单元是10毫秒存储区,够100毫秒30H加1,31H是秒个位存储,32H是秒十位存储。P1.4是米字型数码管控制端,当p1.4=0为低电平(反相后为高)时,p1.6=1,(反相后为低)中间横条显示,P1.6 是米字型数码管共阴极com选通控制端,P1.7数码管小数点选通控制。


;程序源代码如下:
ORG0000H
AJMP L00 ;电子表程序20151215通过 ORG 000BH ; AJMP CT RETI
ORG 001BH
RETI
ORG 0023H
TPH DATA28H ;存放温度值的高字节
TPL DATA29H ;存放温度值的低字节
XS EQU26H ;用于保存温度的小数部分
ZS EQU27H ;用于保存整数部分
XT EQUP3.6 ;MC14513选通
DQ EQUP3.7 ;DS18B20的数据口位
FLAG1 EQU 20H.0
ORG 0030H;初始化子程序
L00: MOV SP,#68H ;设堆栈指针
MOV SCon,#50h; 方式1,REN=1.SM0,SM1,SM2,REN,TB8,RB8,TI,RI
MOV TMOD,#21H;波特率发生器T1工作在模式2上
MOV TH1,#0FFH;预置初值(按照波特率9600BPS预置初值)
MOV TL1,#0FFH;预置初值(按照波特率9600BPS预置初值)
MOV TH0,#0E6H ;7.3128= 11F4H ,方式1,16位定时
MOV TL0, #3EH
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETBPS ;串口中断优先
QL0: MOV A,#00H
MOV R0,#10H
MOV R2,#60H ;10-ABH清零
CLEAR: MOV @R0,A
INC R0
DJNZ R2,CLEAR
MOV 36H,#01H
MOV 35H,#02H
MOV 34H,#03H
MOV 33H,#00H
CLR FLAG1
;显示子程序和时钟调整子程序
DIS:SETB EA ;开AT89C51中断
SETB ET0 ;允许AT89C51的TIME0中断
SETB TR0 ;T0开始计数
MOVA,31H ;31H十秒加1?30h是每秒加1
XRL A,#09h
JNZ DIS0
CALL DS18B20;
DIS0: JNB P3.5,DIS4 ;为低再看秒十位单元是否为0
CLR TR0 ;校验表程序,调整分
MOVA,30H ;31H十秒加1?30h是每秒加1
JNZDIS6 ;秒位=0,自动小时加1
JB FLAG1,DIS6
DIS5: MOV R0,#35H ;校验表程序,调整小时
SETB FLAG1
ACALL GIA2
MOV R0, #36H
MOV A, @R0
DEC R0
SWAP A
ADD A, @R0
MOV 2DH, A
CJNE A, #24H, DIS6
CLR A
MOV 35H, A
MOV 36H, A
AJMP DIS6
DIS4: JNBP3.1 ,DIS6
CLR TR0 ;校验表程序调整分
MOVA,30H ;31H十秒加1?30h是每秒加1
JNZDIS6 ;秒位=0,自动小时加1
MOV 31H, #00H
MOV 32H, #00H
DIS7: MOV R0, #33H
JBFLAG1,DIS6 ;
SETB FLAG1
ACALL GIA2
MOV R0, #34H
MOV A, @R0
DEC R0
SWAP A
ADD A, @R0
MOV 2DH, A
CJNE A, #60H, DIS6
CLR A
MOV 33H, A
MOV 34H, A
DIS6: MOV R2,#01H ;R2是位选信号01-04移位 显示子程序显示33h-36h单元数值
MOV A,31H
SUBBA,#05H ;6789秒显示时间,012345秒显示温度
JC DIS9
MOV R1,#33H ;显示时间的起始地址33h-36h
AJMP DIS8
DIS9: MOV R1,#2CH ;显示温度的起始地址2ch-2fh
DIS8: SETB TR0
DIS1: MOVA,@R1
MOVP0,A ;送数据
SETB XT ;控制MC14513LE ,当BI,LT为1 ,LE上升沿锁存输出,高电平时不变
MOVA,R2 ;
MOV P1,A ;P0.0-P0.3控制4段数码管共阴极导通,为1反相后为0,数码管导通
INC R1
MOV A,R2
RL A
MOV R2,A
MOV A,R2 ;第2位小数点闪动
JNB 0E3H,DIS3 ;第2位小数点闪动E3
MOV A,30H
JNZ DIS3
CPLP1.7 ;每秒小数点闪动一次,(CPLP1.7)
DIS10: MOV C,20H.7
SETBp1.6 ;SETBP1.6;经2003反相后变成低电平,米字型数码管选通
JC DIS2
SETBP1.4 ;十字不亮
AJMP DIS3
DIS2: CLRp1.4 ;竖线不亮,其它一秒一闪
DIS3: LCALLDELAY ;位扫描
CLRXT ;
JB 0E4H, J6
AJMP DIS1
J6: AJMP DIS
;定时器中断子程序
CT: MOV TH0,#0E8H ;7.3128= 11F4H ,方式1,16位定时E832=10MS E63E)
MOV TL0,#08H ;0FFC慢,1000快E810快 E7F0慢 E807慢
PUSH 0D0H
PUSH 0E0H
PUSH 82H
PUSH 83H
MOV A,25H ;
INC A
MOV 25H, A
CJNE A, #0AH,DONE ;0fff=0a,e63e=64
MOV 25H, #00H
MOV A,30H ;
INC A
MOV 30H, A
CJNE A, #0AH,DONE ;
MOV 30H, #00H
MOV A, 31H;5H
INC A ;秒个位加1
CLRFLAG1 ;31H十秒加1?30h是每秒加1
MOV 31H,A ;5
CJNE A, #0AH, DONE
; CPLFLAG2 ;31H十秒加1?30h是每秒加1
MOV 31H, #00H ;5
MOV A, 32H;4H
INC A ;秒十位加1
MOV 32H,A ;4
CJNE A, #06H,DONE
MOV 32H, #00H ;4
MOV A, 33H
INC A ;分位加1
MOV 33H, A
CJNE A, #0AH,DONE
MOV 33H, #00H
MOV A, 34H;2H
INC A ;分十位加1
MOV 34H, A ;4
CJNE A, #06H,DONE
MOV 34H, #00H ;4
MOV R0,#35H ;1
ACALL GIA1
MOV R0, #36H
MOV A, @R0
DEC R0
SWAP A
ADD A, @R0
MOV 2DH, A
CJNE A, #24H, DONE
CLR A
MOV 35H, A
MOV 36H, A
MOVA,30H ; 1/10秒单元加7,补偿慢9秒
ADD A,#07H
MOV 30H,A
MOVA,31H ;秒单元加9,补偿慢9秒
ADD A,#09H
MOV 31H,A
; AJMP X
DONE: NOP
POP 83H
POP 82H
POP 0E0H
POP 0D0H
RETI
GIA1: MOV R1, #04H
GIA2: MOV A, @R0
GIA: INC A
MOV @R0, A
CJNE A, #0AH, GIA3
CLR A
MOV @R0, A
INC R0
DJNZ R1, GIA2
GIA3: RET
ORG 0712H
DELAY: MOV R5, #66H;88H
DEL: NOP
DJNZ R5, DEL
RET
;温度采集子程序
DS18B20: ;CLR EA;
CALLDS18B20_Reset ;设备复位
MOVA,#0CCH ;跳过ROM命令
CALL DS18B20_WriteByte ;送出命令
MOVA,#044H ;开始转换 温度转换 44H 启动DS18B20进行温度转换
CALL DS18B20_WriteByte ;送出命令
JNBDQ,DELAY ;等待转换完成
CALLDS18B20_Reset ;设备复位
MOVA,#0CCH ;跳过ROM命令
CALL DS18B20_WriteByte ;送出命令
MOVA,#0BEH ;读暂存存储器读暂存器 BEH 读暂存器9个字节内容
CALL DS18B20_WriteByte ;送出命令
CALL DS18B20_ReadByte ;读温度低字节
MOVTPL,A ;存储数据
CALL DS18B20_ReadByte ;读温度高字节
MOVTPH,A ;存储数据
MOV A,TPH;30H
RLC A
MOV20H.7,c ;保存正负温度标志
JNCZH ;最高位是0为零上温度转ZH
;最高位是1为零下温度取反加1
MOVA,TPH;28H ;例如温度是-54.875度,源码=1100 1001 001XXXXX 例如温度72.75,30h=48h,31h=40h,加在一起是01001000(=30H) 010xxxxx=(31H)
CPLA ;00110110=(30H)
MOV2AH,A ;高位取反
MOVA,TPL;29H ;低位取反110XXXXX
CPLA ;110XXXXXX=(31H)
MOV2BH,A ;保存高2位到(32h)=01H ,最后转换成242H=578d,578*0.125=72.75
MOVA,#01H ;10110111=B7
ADD A,2BH
MOV 2BH,A
CLR A
ADDCA,2AH ;例如温度是-54.875度=-439*.125,补码649h,-649h=1 110 0100 1001
MOV2AH,A ;结果是32h=01,33h=b7,合并成1b7h 取反=00110110110,加1=00110110111为正码1b7h=439,39*.125=54.875
AJMP LS
ZH: MOV A,TPH;30H
MOV2AH,A ;保存高2位到(32h)=02H ,最后转换成242H=578d,578*0.125=72.75
MOV A,TPL
MOV2BH,A ;保存到33h=01000010=42H
LS: MOV A,2BH;TPL
ANL A,#0FH ;存放温度的低字节的低四位决定小数部分
MOV XS,A ;获得小数部分34H
MOV A,2BH;TPL
ANL A,#0F0H
SWAP A
MOVZS,A ;35H存放温度的低字节的高四位
MOV A,2AH;TPH ;获取存放温度的高字节的低三位
ANL A,#07H
SWAPA
ORLA,ZS ;存放温度的低字节的高四位合并存放温度的高字节的低三位决定整数部分
MOV ZS,A
MOV B,#100;分离出百位,存放在R3中
DIV AB
MOV R3,A
MOVA,#10 ;余数继续分离十位和个位
XCH A,B
DIV AB
; SWAP A
; ORL A,B ;十位和个位拼装成BCD码
MOV 2FH,A
MOV A,B
MOV 2EH,A
MOV A,XS
MOV R0,#37H
MOV R2,#4
D0: MOV B,#10
MUL AB
MOV B,#16
DIV AB
MOV @R0,A
INC R0
MOV A,B
DJNZ R2,D0
MOV 2DH,37H
MOV 2CH,38H
RET ;20H.7保存正负温度标志
DelayXus: NOP ;6微秒
DJNZR7,DelayXus ;
RET ;
;**************************************
;复位DS18B20,并检测设备是否存在
;入口参数:无
;出口参数:无
;**************************************
DS18B20_Reset:;MOV WDT_CONTR ,#37H;喂狗
CLRDQ ;送出低电平复位信号
MOVR7,#40;240 ;延时至少480us
CALL DelayXus
MOV R7,#40;240
CALL DelayXus
SETB DQ ;释放数据线
MOVR7,#10;60 ;等待60us
CALL DelayXus
MOVC,DQ ;检测存在脉冲
MOVR7,#40;240 ;等待设备释放数据线
CALL DelayXus
MOVR7,#30;180
CALL DelayXus
JCDS18B20_Reset ;如果设备不存在,则继续等待
RET
;**************************************
;从DS18B20读1字节数据
;入口参数:无
;出口参数:ACC
;**************************************
DS18B20_ReadByte:
CLR A
PUSH 0
MOV0,#8 ;8位计数器
ReadNext:
CLRDQ ;开始时间片
MOVR7,#1 ;延时等待
NOP;CALL DelayXus
SETBDQ ;准备接收
MOV R7,#1
NOP; CALL DelayXus
MOVC,DQ ;读取数据
RRC A
MOVR7,#10;60 ;等待时间片结束
CALL DelayXus
DJNZ0,ReadNext
POP 0
RET
;**************************************
;向DS18B20写1字节数据
;入口参数:ACC
;出口参数:无
;**************************************
DS18B20_WriteByte:
PUSH 0
MOV 0,#8 ;8位计数器
WriteNext:
CLRDQ ;开始时间片
MOVR7,#1 ;延时等待
NOP;CALL DelayXus
RRCA ;输出数据
MOV DQ,C
MOVR7,#10;60 ;等待时间片结束
CALL DelayXus
SETBDQ ;准备送出下一位数据
MOV R7,#1
NOP; CALL DelayXus
DJNZ 0,WriteNext
POP 0
RET
END
|