MAIN:
;clr p3.0
;clr p3.1
LCALL GET_TEMPER;调用读温度子程序
;进行温度显示,这里我们考虑用网站提供的两位数码管来显示温度
;显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数所以可以抛弃29H的低4位
;将28H中的低4位移入29H中的高4位,这样获得一个新字节,这个字节就是实际测量获得的温度
;这个转化温度的方法可是我想出来的哦~~非常简洁无需乘于0.0625系数
MOV A,29H
MOV C,40h ;将28H中的最低位移入C
RRC A ;带进位循环右移
MOV C,41h
RRC A
MOV C,42h
RRC A
MOV C,43h
RRC A
MOV 29H,A
LCALL DISPLAY;调用数码管显示子程序
AJMP MAIN
; 这是DS18B20复位初始化子程序--------------------
INIT_1820:
SETB data_line ;初始化程序的时序要求
NOP
CLR data_line
MOV R1,#3
TSR1:MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1 ;主机发出延时537微秒的复位低脉冲(我计算为660US)
SETB data_line ;然后拉高数据线
NOP
NOP
NOP
MOV R0,#25H
TSR2:
JNB data_line,TSR3 ;等待DS18B20回应 BIT=0 转移
DJNZ R0,TSR2
LJMP TSR4 ; 延时
TSR3:
SETB FLAG1 ; 置标志位,表示DS1820存在
;CLR P3.5 ;检查到DS18B20就点亮P3.5LED
LJMP TSR5
TSR4:
CLR FLAG1 ; 清标志位,表示DS1820不存在
LJMP TSR7
TSR5:
MOV R0,#117
TSR6:
DJNZ R0,TSR6 ; 时序要求延时一段时间
TSR7:
SETB data_line
RET
; 读出转换后的温度值
GET_TEMPER:
SETB data_line
LCALL INIT_1820 ;先复位DS18B20
JB FLAG1,TSS2
RET ; 判断DS1820是否存在?若DS18B20不存在则返回
TSS2: ;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!;*****先实现温度转换
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#44H ; 发出温度转换命令
LCALL WRITE_1820
;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
LCALL DISPLAY
LCALL DISPLAY ;有人说是等待时间短了,我就在这里多加了几个等待
LCALL DISPLAY
LCALL DISPLAY
LCALL DISPLAY
LCALL DISPLAY
LCALL INIT_1820 ;准备读温度前先复位,;*****再读温度
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ; 发出读温度命令
LCALL WRITE_1820
LCALL READ_18200 ; 将读出的温度数据保存到35H/36H
RET
;写DS18B20的子程序(有具体的时序要求)------------------------
WRITE_1820:
MOV R2,#8;一共8位数据
CLR C
WR1:
CLR data_line ;先将总线置低电平
MOV R3,#8
DJNZ R3,$ ;DS18B20也开始工作,对数据进行采样
RRC A
MOV data_line,C
MOV R3,#32 ;采样时间要求持续60us~120us
DJNZ R3,$
SETB data_line ;两次写入数据的时间间隔大于1us
NOP
DJNZ R2,WR1
SETB data_line
RET
; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据
READ_18200:
MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV R2,#8;数据一共有8位
RE01:
CLR C
SETB data_line
NOP
NOP
CLR data_line
NOP
NOP
NOP
SETB data_line
MOV R3,#8
RE10:
DJNZ R3,RE10 ;在这段时间内,数据线从高电平变为低电平。
MOV C,data_line ;1820送数据
MOV R3,#30
RE20:
DJNZ R3,RE20 ;在这段时间内,主机从总线读数据
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;显示子程序
display:
mov a,29H ;29中已是10进制
mov b,#10 ;10进制/10=10进制
div ab ;?????
mov b_bit,a ;十位在a
mov a_bit,b ;个位在b
mov dptr,#tab ;指定查表启始地址
mov r0,#4
dpl1:
mov r1,#250 ;显示1000次
dplop:
mov a,a_bit ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
mov p1,a ;送出个位的7段代码
clr p3.0 ;开个位显示
acall d1ms ;显示1ms
setb p3.0
mov a,b_bit ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
mov p1,a ;送出十位的7段代码
clr p3.1 ;开十位显示
acall d1ms ;显示1ms
setb p3.1
djnz r1,dplop ;100次没完循环
djnz r0,dpl1 ;4个100次没完循环
ret
;1MS延时(按12MHZ算)
D1MS: MOV R7,#90
DJNZ R7,$
RET
tab: db 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h
end