1、DS18B20温度传感器实验 TEMP1 EQU 5AH ;符号位和百位公用的存放单元 TEMP2 EQU 5BH ;十位存放单元 TEMP3 EQU 5CH ;个位存放单元 TEMP4 EQU 5DH ; TEMP5 EQU 5EH TEMP6 EQU 5FH ;数据临时存放单元 TEMP7 EQU 60H TEMP8 EQU 61H ORG 0000HAJMP MAINORG 0020HMAIN: MOV SP,#70H LCALL INT ;调用DS18B20初始化函数MAIN1: LCALL GET_TEMP ;调用温度转换函数 LCALL CHULI ;调用温度计算函数LCALL D
2、ISP ;调用温度显示函数AJMP MAIN1 ;循环INT: L0: SETB P3.7 ;先释放DQ总线 MOV R2,#250 ;给R2赋延时初值,同时可让DQ保持高电平2us L1: CLR P3.7 ;给DQ一个复位低电平DJNZ R2,L1 ;保持低电平的时间至少为480usSETB P3.7 ;再次拉高DQ释放总线MOV R2,#25 L2:DJNZ R2,L2 ;保持15us60us CLR C ORL C,P3.7 ;判断是否收到低脉冲 JC L0 MOV R6,#100 L3:ORL C,P3.7 DJNZ R6,L3 ;存在低脉冲保持保持60us240us;JC L0 ;
3、否则继续从头开始,继续判断SETB P3.7 RET ;调用温度转换函数GET_TEMP: CLR PSW.4SETB PSW.3 ;设置工作寄存器当前所在的区域CLR EA ;使用DS18B20前一定要禁止任何中断LCALL INT ;初始化DS18B20MOV A,#0CCH ;送入跳过ROM命令LCALL WRITEMOV A,#44H ;送入温度转换命令LCALL WRITELCALL INT ;温度转换完成,再次初始化18b20MOV A,#0CCH ;送入跳过ROM命令LCALL WRITEMOV A,#0BEH ;送入读温度暂存器命令LCALL WRITELCALL READ M
4、OV TEMP4,A ;读出温度的低字节存在TEMP4LCALL READMOV TEMP5,A ;读出温度的高字节存在TEMP5SETB EARETCHULI : MOV A,TEMP5 ;将温度的高字节取出 JNB ACC.7,ZHENG ;判断最高位是否为0,为0则表示温度为正,则转到ZHENG MOV A,TEMP4 ;否则温度为负,将温度的低字节取出 CPL A ;求反 INC A ;加1 MOV TEMP8,A ;存到TEMP8中 ANL A,#0FH ;保留低四位 LCALL MULD ;调用乘以625子程序 LCALL HB2 ;调用双字节16进制数转换成BCD码子程序 MOV
5、 A,R4 ;将结果的千位百位取出 ANL A,#0F0H ;保留千位 SWAP A ; MOV TEMP7,A ;把小数结果保存在TEMP7中 MOV A,TEMP4 ;再次取出温度的低字节 ANL A,#0FFH ;判断是否为0 JZ XX ;为0则转到XX执行 MOV A,TEMP5 ; CPL A ;不为0则直接将温度的高字节取反 SJMP YY ; XX: MOV A,TEMP5 ;为0则求补码 CPL A ; INC A ; YY: ANL A,#0FH ;保留高字节的低四位 SWAP A ;将其换到高4位 MOV R5,A ;暂时保存于R5中 MOV A,TEMP8 ;取出求反后
6、的低位字节 ANL A,#0F0H ;取其高4位 SWAP A ;将其换到低4位 ORL A,R5 ;合并成温度的整数部分 MOV TEMP6,A ;将整数部分存到TEMP6中 LCALL HBCD ;调用一字节的16进制数转换BCD数的子程序 MOV TEMP1,#0BH ;将-号的段选值存到符号位MOV A,TEMP2 ;取出十位 CJNE A,#00H,NEXT MOV TEMP2,#0CH ;十位为0不显示 RET ZHENG: MOV A,TEMP4 ;将温度的低字节取出 ANL A,#0FH ;保留低四位 LCALL MULD ;调用乘以625子程序 LCALL HB2 ;调用双字
7、节16进制数转换成BCD码子程序 MOV A,R4 ;将结果的千位百位取出 ANL A,#0F0H ;保留千位 SWAP A ; MOV TEMP7,A ;把小数结果保存在TEMP7中 MOV A,TEMP4 ;再次取出温度的低字节 ANL A,#0F0H ;保留高4位 SWAP A ;换到低4位 MOV R5,A ;暂时保存于R5中 MOV A,TEMP5 ;取出温度的高字节 ANL A,#0FH ;保留低4位 SWAP A ;换到高4位 ORL A,R5 ;合并成温度的整数部分 MOV TEMP6,A ;整数部分存到TEMP6中 LCALL HBCD ;单字节的16进制数转换成BCD码 M
8、OV A,TEMP1 ;取出百位 CJNE A,#00H,NEXT ;百位不为0则转NEXT MOV TEMP1,#0CH ;为0则不显 MOV A,TEMP2 ;取出十位 CJNE A,#00H,NEXT MOV TEMP2,#0CH ;十位为0也不显 NEXT: RET ;小数部分乘以625转换子程序MULD: MOV B,#71H MUL AB MOV R7,A MOV R6,B MOV B,#02H MUL AB ADD A,R6 MOV R6,A RET ;写字节到18b20子程序 WRITE: MOV R3,#8 ;一个字节共8位WR1: SETB P3.7 ;先释放总线 MOV
9、R4,#8 RRC A ;把要写的字节的最低位右环移到C中 CLR P3.7 ;写开始WR3: DJNZ R4,WR3 ;保持低电平015us,等待 MOV P3.7,C ;将C中的位写到DQ总线上 MOV R4,#20 DJNZ R4,$ ;18b20在15us60us期间对DQ总线进行采样 DJNZ R3,WR1 ;判断8位是否写完,没完则继续写下一位 SETB P3.7 ;写完了一个字节,则释放总线 RET;从18b20里读取一个字节子程序READ: MOV R6,#8 ;一个字节有8位 RE1: SETB P3.7 ;先释放总线 NOP CLR P3.7 ;拉低总线,读前总线保持为低
10、NOP ;保持12us MOV R4,#4 ;设置读时间隙 SETB P3.7 ;读开始 RE2: DJNZ R4,RE2 ;产生读时间隙 MOV C,P3.7 ;将总线上的位读到C MOV R5,#30 ; DJNZ R5,$ ;持续60us RRC A ;将C里的位右环移到A里 DJNZ R6,RE1 ;读下一位 SETB P3.7 RET;单字节16进制数转换成BCD码子程序HBCD:MOV A,TEMP6 MOV B,#10 DIV AB MOV TEMP3,B ;将个位存到TEMP3 MOV B,#10 DIV AB MOV TEMP2,B ;将十位存到TEMP2 MOV TEMP1
11、,A ;将百位存到TEMP1 RET;双字节的16进制数转换成BCD码子程序HB2: CLR A MOV R3,A MOV R4,A MOV R5,A MOV R2,#10HHB3: MOV A,R7 RLC A MOV R7,A MOV A,R6 RLC A MOV R6,A MOV A,R5 ADDC A,R5 DA A MOV R5,A MOV A,R4 ADDC A,R4 DA A MOV R4,A MOV A,R3 ADDC A,R3 MOV R3,A DJNZ R2,HB3 RET;显示子程序DISP: MOV DPTR,#DISPTAB MOV R0,#4 DP1: MOV R1
12、,#140LOOP: MOV A,TEMP7 ;取出小数部分 MOVC A,A+DPTR ;取出相应的字型码 MOV P1,A ;显示在数码管上 SETB P3.0 ;数码管位选 ACALL DELAY100 ;延时 CLR P3.0 ;清数码管位选 MOV A,TEMP3 ;取个位 MOVC A,A+DPTR ANL A,#7FH ;显示小数点 MOV P1,A SETB P3.1 ACALL DELAY100 CLR P3.1 MOV A,TEMP2 ;取十位 MOVC A,A+DPTR MOV P1,A SETB P3.2 ACALL DELAY100 CLR P3.2 MOV A,TEMP1 ;取符号位或百位 MOVC A,A+DPTR MOV P1,A SETB P3.3 ACALL DELAY100 CLR P3.3 DJNZ R1,LOOP ;循环显示 DJNZ R0,DP1 RETDELAY100: MOV R7,#180 ;延时 DJNZ R7,$ RETDISPTAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0BFH,0FFHEND