📄 ds18b20.asm
字号:
N EQU 8 ;读出ROM的位数
DQ EQU P3.2 ;单总线的数据线
TH EQU 40 ;最高极限温度
TL EQU 10 ;最低极限温度
SROMC EQU 0F0H ;搜索ROM命令
MROMC EQU 55H ;匹配ROM命令
LROMC EQU 0CCH ;跳过读ROM命令
RROMC EQU 33H ;读ROM命令
CTC EQU 44H ;转换温度命令
WREGC EQU 4EH ;写暂存器命令
RREGC EQU 0BEH ;读暂存器命令
CONFIG EQU 1FH ;配置寄存器的值,9位温度值
DSEG AT 30H
DAT: DS 1 ;温度值存储单元
POINT: DS 1 ;小数点后温度值的存储单元
ROMA: DS 8 ;器件A的ROM存储单元
BUF: DS 9 ;暂存器中数据存储单元
BUFT: DS 4 ;数码管动态显示的4个数据缓冲单元
BTH: DS 1 ;显示ROM中某一字节高四位
BTL: DS 1 ;显示ROM中某一字节低四位
CSEG AT 0000H
LJMP MAIN
ORG 0100H
MAIN: mov p0,#0
MOV SP,#70H
MOV PSW,#00H
LCALL Initial
MOV A,#LROMC ;写跳过ROM命令
LCALL W8BIT
MOV A,#WREGC ;写暂存器命令,可写入TH,TL,Configuration
LCALL W8BIT
MOV A,#TH ;写18B20的TH寄存器
LCALL W8BIT
MOV A,#TL ;写18B20的TL寄存器
LCALL W8BIT
MOV A,#CONFIG ;写18B20的配置寄存器,9位温度值
LCALL W8BIT
RETN: LCALL Initial ;18B20初始化
MOV A,#LROMC ;写跳过ROM命令
LCALL W8BIT
MOV A,#CTC ;写转换温度命令
LCALL W8BIT
BUSY: LCALL Disply ;显示温度
CLR DQ ;读18B20的忙位
NOP
SETB DQ
NOP
MOV C,DQ
LCALL DLY70 ;延时70微秒
JNC BUSY ;如果18B20忙,转BUSY
LCALL Initial ;初始化
MOV A,#LROMC ;写跳过ROM命令
LCALL W8BIT
MOV A,#RREGC ;写读18B20暂存器命令
LCALL W8BIT
MOV R3,#2 ;设置计数器R3=2,从18B20读2个字节的温度值
MOV R1,#BUF ;置R1温度值缓冲区
RER: LCALL R8BIT ;读温度值
MOV @R1,A ;将温度值存入缓冲区
INC R1 ;温度值缓冲区地址加1
DJNZ R3,RER ;如2个字节温度值没读完,转RER
LCALL STORE ;温度转换并存储子程序
LCALL Disply ;温度显示子程序,只所以调用2次该子程序
;是为了增强数码管的亮度
SJMP RETN
;18B20初始化子程序,使用R7
Initial:CLR DQ ;数据线为低700微秒
LCALL DLY700
SETB DQ ;置数据线为高,以便接收18B20信号
I1: MOV C,DQ ;等待数据线为低
JC I1
LCALL DLY700 ;延时700微秒
RET
;向18B20写8位子程序,被写的数在ACC中
;使用R2、R7
W8BIT: MOV R2,#8 ;设置计数器R2为8
W1: CLR DQ ;使数据线为低
RRC A ;右移将被写位移如进位C
JNC W2 ;被写位为0,转W2
SETB DQ ;被写位为1,使数据线为高
W2: LCALL DLY70 ;延时70微秒
SETB DQ ;使数据线为高
DJNZ R2,W1 ;如果8位数据没写完,转W1
RET
;读8位子程序,读的数在ACC中
;使用R2、R7
R8BIT: MOV R2,#8 ;设置计数器R2为8
RR1: CLR DQ ;使数据线为低,启动读过程
NOP ;等待4微秒
SETB DQ ;使数据线为高,以便从18B20读数据
NOP ;等待4微秒
MOV C,DQ ;将数据读入进位C
RRC A ;通过右移将进位C送入ACC
LCALL DLY70 ;延时70微秒
DJNZ R2,RR1 ;如果8位数据没读完,转RR1
RET
;温度值存储子程序,使用R0
STORE: MOV R0,#BUF ;将温度缓冲区首址送R0
MOV A,@R0
MOV B,A
ANL A,#08H ;保留小数位
MOV POINT,A
MOV A,B
ANL A,#0F0H ;保留高4位
MOV B,A
INC R0
MOV A,@R0
ANL A,#0FH ;保留低4位
ORL A,B ;组成1个字节
SWAP A
MOV R0,#BUFT
JB ACC.7,NEG ;如果温度为负,转NEG
MOV DAT,A ;温度为正值,直接存到DAT里
MOV A,#00H ;正号显示
MOV @R0,A
JMP NST
NEG: CPL A ;将相应的负值转换为其绝对值
MOV B,A
MOV A,POINT
CPL A
CLR ACC.4
ADD A,#08H
MOV C,ACC.4
XCH A,B
ADDC A,#0
MOV DAT,A ;把负温度值1-8位变正存储
MOV POINT,B ;把负温度值第9位变正存储
MOV A,#40H ;负号显示
MOV @R0,A
NST: INC R0
MOV A,DAT ;取温度值
MOV B,#10 ;十位数在ACC中,个位数在B中
DIV AB
MOV DPTR,#TAB ;将十位数转换为数码管字形码值存入BUFT中
MOVC A,@A+DPTR
MOV @R0,A
INC R0 ;字形码缓冲区地址加1
MOV A,B
MOVC A,@A+DPTR ;将个位数字形码连同小数点存入BUFT中
SETB ACC.7
MOV @R0,A
INC R0 ;字形码缓冲区地址加1
MOV A,POINT ;取小数点后的值字形码存入缓冲区BUFT中
JB ACC.3,FLOAT
MOV A,#3FH
MOV @R0,A
JMP E
FLOAT: MOV A,#6DH
MOV @R0,A
E: RET
;显示温度子程序,使用了DPTR、R0、R5。
;BUFT中存放的是温度值的字形码
Disply: MOV R0,#BUFT
MOV A,@R0
MOV P1,A ;送出正负位的7段代码
SETB P3.4 ;开个位显示
CALL DISP
CLR P3.4
MOV A,@R0
MOV P1,A ;送出十位的7段代码
SETB P3.5 ;开十位显示
CALL DISP
CLR P3.5
MOV A,@R0
MOV P1,A ;送出个位的7段代码
SETB P3.6 ;开个位显示
CALL DISP
CLR P3.6
MOV A,@R0
MOV P1,A ;送出小数位的7段代码
SETB P3.7 ;开小数位显示
CALL DISP
CLR P3.7
RET
;显示一个数字子程序
DISP: MOV R5,#250 ;等待600微秒
DJNZ R5,$
INC R0 ;BUFT字形码缓冲区地址加1,准备显示下一个数字
RET
DLY700: MOV R7,#157 ;延时700微秒子程序,使用R7
DJNZ R7,$
DLY70: MOV R7,#17 ;延时70微秒子程序,使用R7
DJNZ R7,$
RET
;延时1分钟子程序,使用R5、R6、R7
DLY1M: MOV R5,#240
LOOP1: MOV R6,#250
LOOP2: MOV R7,#250
DJNZ R7,$
DJNZ R6,LOOP2
DJNZ R5,LOOP1
RET
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
;DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H ;a~f字形码
DB 7FH,6FH,77H,7CH,58H,5EH,79H,71H
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -