/* 程序效果:通过DS18B20读取温度值,显示对应的温度值 程序重在理解时序,及延时时间 */ DS18DQ EQU P1.3 //P1.3与DS18DQ等同,便于理解 SPEAKER EQU P2.0 //驱动蜂鸣器 TEMPH EQU 29H //保存读出温度的低8位 TEMPL EQU 28H //保存读出温度的高8位 DS18FLAG EQU 40H //设置标志 ORG 0000H LJMP START ORG 0030H START: MOV 30H,#00 //设置初始值 MOV 31H,#00 MOV 32H,#00 START1: LCALL DS18_GF //设置DS18B20的工作方式 LCALL CONVERT_TEMPERATURE //输出转换温度命令 LCALL DELAY750MS //延时750ms LCALL GET_TEMPERATURE //获?温度数据 LCALL CAL_TEMPERATURE //计算温度数值 LCALL DISPLAY //调用显示,防止掉显 LJMP START1 //无限循环 //初始化子程序 DS18_START: PUSH 07H //保存R7的值,防止改变R7的数值 SETB DS18DQ //将数据线拉高 NOP //延时1us CLR DS18DQ //将数据线拉低 MOV R7,#0 //延时大约512us DJNZ R7,$ SETB DS18DQ //将数据线拉高 MOV R7,#40 DS18_START1: //延时大约160us JNB DS18DQ,DS18_START2 //检查DS18B20是否工作正常 DJNZ R7,DS18_START1 SETB DS18FLAG //工作不正常 CLR SPEAKER //驱动蜂鸣器,报警 DS18_START2: CLR DS18FLAG MOV R7,#100 //延时月200us DJNZ R7,$ POP 07H //恢复R7的值 RET //设置DS18B20工作方式 DS18_GF:CLR DS18FLAG //清除标志 LCALL DS18_START //调用初始化子程序 MOV A,#0CCH //跳跃ROM指令 LCALL DS18_SEND // MOV A,#4EH //向RAM写数据 LCALL DS18_SEND MOV A,#75 LCALL DS18_SEND MOV A,#0 LCALL DS18_SEND MOV A,#7FH //设置工作方式 LCALL DS18_SEND CLR DS18DQ //释放总线 LCALL DELAY500US //延时500us LOOP: LCALL CONVERT_TEMPERATURE //调用转子程序 MOV R5,#80 LOOP1: LCALL DISPLAY //调用显示防止掉显,同时等待转换完成 DJNZ R5,LOOP1 LCALL GET_TEMPERATURE //获?转换值 LCALL CAL_TEMPERATURE //计算温度值 LJMP LOOP RET //输出转换温度命令 CONVERT_TEMPERATURE: LCALL DS18_START //调用初始化子程序 MOV A,#0CCH //跳跃ROM指令 LCALL DS18_SEND MOV A,#44H //温度转换 LCALL DS18_SEND RET //读?温度数据 GET_TEMPERATURE: LCALL DS18_START //调用初始化子程序 MOV A,#0CCH //跳跃ROM指令 LCALL DS18_SEND MOV A,#0BEH //从RAM中的数据 LCALL DS18_SEND LCALL DELAY60US LCALL DS18_READ MOV TEMPL,A //将获得数据的低八位存到TEMPL LCALL DS18_READ MOV TEMPH,A //将获得数据的高八位存到TEMPH CLR DS18DQ //即复位。否则会一直读到 LCALL DELAY501US //暂存第九字节 RET //计算获得温度值,便于现实 CAL_TEMPERATURE: PUSH 07H //暂存,防止改变R7的数据 CLR C //进位标志清零 MOV R7,#04H //循环次数 EX2: MOV A,TEMPH // 这些语句的作用是: RRC A // 整数位在:TEMPL中 MOV TEMPH,A //?数位在:TEMPH中的高半 MOV A,TEMPL RRC A MOV TEMPL,A DJNZ R7,EX2 // MOV A,TEMPH // RLC A //这些语句的作用是: RLC A //把TEMPH得高半移到低四位中 RLC A RLC A // ANL A,#0FH //屏蔽高四位,保留低四位 MOV DPTR,#TAB_TEMP //赋带?数点的数值表的表首地址 MOVC A,@A+DPTR MOV 30H,A //暂存该值,用于显示 MOV A,TEMPL CLR C MOV B,#0AH DIV AB //分离整数位的高低四位 MOV 32H,A //暂存十位 MOV A,B ADD A,#10H MOV 31H,A //暂存个位 POP 07H //恢复R7的值 RET //写数据子程序 DS18_SEND: PUSH 06H //保护Rn的值 PUSH 07H //以下语句是"写 笔毙虻脑? SETB DS18DQ //写时序是有DS18DQ的下降沿决定 NOP //延时1us MOV R6,#08H //循环次数,一个字节 DS18_SEND1: CLR DS18DQ //拉低,产生下降沿 MOV R7,#07 //延时大约15us DJNZ R7,$ RRC A //把要写入得数据的高位移到C中 MOV DS18DQ,C //再把C的值赋给DS18DQ MOV R7,#30 //延时时间约为60us,只要大约45us即可 DJNZ R7,$ SETB DS18DQ //拉高准备,下次产生下降沿 DJNZ R6,DS18_SEND1 //判断循环次数够了没 POP 07H //恢复Rn的数据 POP 06H RET //读数据子程序 DS18_READ: PUSH 06H // 保护Rn的值 PUSH 07H //以下为 岸?钡氖毙? SETB DS18DQ //拉高,准备产生下降沿 MOV R6,#08H //循环次数 CLR A //A清零,准备装值 DS18_READ1: CLR DS18DQ //拉低,产生下降沿 NOP //延时2us,其实有没有都没有什么关系 NOP SETB DS18DQ //释放总线 MOV R7,#07H //等待15us DJNZ R7,$ MOV C,DS18DQ //获?数据 RRC A //将获得数据存到A中 MOV R7,#30 //延时60us DJNZ R7,$ SETB DS18DQ //拉高,准备下次产生下降沿 DJNZ R6,DS18_READ1 POP 07H //恢复Rn的 POP 06H RET //显示子程序 DISPLAY:PUSH 00 //保护R0的值 MOV DPTR,#TAB //赋表首地址 MOV A, #0FBH //点亮最左边的数码管 MOV P2, A XCH A,R0 //保护A的值 MOV A,32H MOVC A,@A+DPTR //显示对应的数值 MOV P0,A LCALL DELAY2MS //延时2ms XCH A,R0 RL A MOV P2,A XCH A,R0 MOV A,31H MOVC A,@A+DPTR MOV P0,A LCALL DELAY2MS XCH A,R0 RL A MOV P2,A //显示带?数点的数值 MOV P0,30H LCALL DELAY2MS RL A MOV P2,A //显示C 拔露确?? MOV P0,#39H LCALL DELAY2MS POP 00 //恢复R0的值 RET DELAY750MS: //延时750ms PUSH 07 //保护Rn的值 PUSH 06 PUSH 05 MOV R7,#10 DEL3: MOV R6,#150 DEL2: MOV R5,#250 DEL1: DJNZ R5,DEL1 DJNZ R6,DEL2 DJNZ R7,DEL3 POP 05 //恢复Rn的值 POP 06 POP 07 RET DELAY2MS: PUSH 06 PUSH 05 MOV R6,#10 DE2: MOV R5,#100 DE1: DJNZ R5,DE1 DJNZ R6,DE2 POP 05 POP 06 RET DELAY500US: PUSH 05 MOV R5,#255 DEL500: DJNZ R5,DEL500 POP 05 RET DELAY60US: PUSH 05 MOV R5,#30 DEL60: DJNZ R5,DEL60 POP 05 RET DELAY501US: PUSH 05 MOV R5,#255 DEL501: DJNZ R5,DEL501 POP 05 RET TAB: DB 3FH,06H,5BH,4FH,66H //数码管显示的数值 DB 6DH,7DH,07H,7FH,6FH TAB_TEMP: DB 03FH,06H,06H,5BH,4FH//显示?数值 DB 4FH,66H,66H,6DH,7DH DB 7DH,07H,7FH,7FH,6FH,6FH END END