📄 18b20(1).asm
字号:
FLAG1 BIT F0 ;DS18B20存在标志位
DQ BIT P3.7 ;DS18B20接口地址
TEMPER_L EQU 29H ;用于保存读出温度的低8位
TEMPER_H EQU 28H ;用于保存读出温度的高8位
A_BIT EQU 35H ;数码管个位数存放内存位置
B_BIT EQU 37H ;数码管十位数存放内存位置
;************程序起始********************
ORG 0000H
AJMP MAIN
ORG 0100H
;**************主程序开始************
MAIN:
mov p0 ,#0ffh
LCALL INIT_18B20 ;调用DS18B20复位初始化子程序
LCALL GET_TEMPER ;调用读温度子程序
AJMP CHANGE ;调用读出的温度进行数据转换子程序
;**********DS18B20复位初始化子程序*****************
INIT_18B20: SETB DQ ;拉高数据线,释放ds1820总线,口线改为输入
NOP ;延时一个时钟周期2ms
CLR DQ ;然后拉低数据线,口线改为输出
;主机发出延时537微秒的复位低脉冲
MOV R0,#0FBH
TSR1: DJNZ R0,TSR1 ;延时
SETB DQ ;然后拉高数据线,口线改为输入
MOV R0,#25H
TSR2: JNB DQ ,TSR3 ;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ; 延时
TSR3: SETB FLAG1 ;置标志位,表明DS18B20存在
CLR P1.3 ;检查到DS18B20就点亮P1.1LED
AJMP TSR5 ; 延时
TSR4: CLR FLAG1 ;清标志位,表示DS1820不存在
LJMP TSR7 ;不存在则跳转到TSR7,拉高数据线
TSR5: MOV R0,#06BH
TSR6: DJNZ R0,TSR6 ;复位成功!时序要求延时一段时间
TSR7:SETB DQ ;表明不存在
RET ;返回主程序,继续执行下一个环节
;*****************读出转换后的温度值****************
GET_TEMPER:
SETB DQ ;拉高数据线,释放ds1820总线,口线改为输入
LCALL INIT_18B20 ;先复位DS18B20
JB FLAG1,TSS2
RET ;判断DS1820是否存在?若DS18B20不存在则返回
TSS2: MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_18B20 ;调用写DS18B20的子程序
MOV A,#44H ;发出温度转换命令
LCALL WRITE_18B20 ;调用写DS18B20的子程序
MOV R0,#50 ;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
LCALL DISPLAY
LCALL INIT_18B20 ;准备读温度前先复位
MOV A,#0CCH ;跳过ROM
LCALL WRITE_18B20 ;调用写DS18B20的子程序
MOV A,#0BEH ;发出读温度命令
LCALL WRITE_18B20 ;调用写DS18B20的子程序
LCALL READ2_18B20 ;读两个字节的温度,将读出的温度数据保存到29H/28H
RET ;返回主程序,执行下一步
;***************写DS18B20程序(有具体的时序要求)************
WRITE_18B20:
MOV R2,#8 ;一共8位数据
CLR C ;清存在信号(存在C=0,不存在C=1)
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
;***********读18B20程序,从DS18B20中读出两个字节的温度数据*********
READ2_18B20:
MOV R4,#2 ;将温度高位和低位从DS18B20中读出,低位存在29 H,高位存在28H
MOV R1,#29H ;低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00: MOV R2,#8 ;数据一共有8位
RE01: CLR C
SETB C
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R3,#7
DJNZ R3,$
MOV C,DQ ;C和DQ同时为高电平
MOV R3,#23
DJNZ R3,$
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;************读出的温度进行数据转换********************************
CHANGE: MOV A,29H ;将29H中的最高位移入A累加器
MOV C,28H.0 ;将28H中的最低4位移入C
RRC A ;经过进位位的累加器A循环右移
MOV C,28H.1 ;..................
RRC A ;...................
MOV C,28H.2 ;...............
RRC A ;...........
MOV C,28H.3 ;............
RRC A ;.................
MOV 29H,A ;将A累加器中转换出的2进制温度换成的BCD码移入29H
LCALL DISPLAY ;调用数码管显示子程序
LJMP MAIN ;跳转到主程序
;*******************DISPLAY显示子程序,此程序要注意的是P2.3口的DS18B20数据采集,不能影响此口 ******************************
DISPLAY: SETB p2.0
clr p2.1
mov a,29H;将29H中的十六进制数转换成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 p0,a ;送出个位的7段代码
clr p1.3;开个位显示
acall d1ms ;显示1ms
setb p1.3 ;关个位显示,防止鬼影
mov a,b_bit ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
mov p0,a ;送出十位的7段代码
clr p1.2;开十位显示
acall d1ms ;显示1ms
setb p1.2 ;关十位显示,防止鬼影
djnz r1,dplop ;100次没完循环
djnz r0,dpl1 ;4个100次没完循环
ret
;*******************1MS延时(按12MHZ算)*************************************
;为保证DS18B20的严格I/O时序,需要做较精确的延时
D1MS: mov r5,#0afh ;351us
time350us_1: djnz r5,time350us_1
ret
;***************************************************************************
TAB:;7段数码管0~9数字的共阳显示代码
DB 0C0H ;"0"
DB 0F9H ;"1"
DB 0A4H ;"2"
DB 0B0H ;"3"
DB 99H ;"4"
DB 92H ;"5"
DB 82H ;"6"
DB 0F8H ;"7"
DB 80H ;"8"
DB 90H ;"9"
DB 88H ;"A"
DB 83H ;"B"
DB 0C6H ;"C"
DB 0A1H ;"D"
DB 86H ;"E"
DB 8EH ;"F"
DB 89H ;"H"
DB 0C7H ;"L"
DB 0C8H ;"n"
DB 0C1H ;"u"
DB 8CH ;"P"
DB 0A3H ;"o"
DB 0BFH ;"-"
DB 0FFH ;"熄灭"
DB 0FFH ;"自定义"
ret
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -