这时一个由汇编语言编写的ds18b20测温程序。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- TEMP_ZH EQU 24H ;实时温度值存放单元,用来和报警值进行比较
- TEMPL EQU 25H ;低温度值存放单元
- TEMPH EQU 26H ;高温度值存放单元
- TEMP_TH EQU 27H ;高温报警值存放单元
- TEMP_TL EQU 28H ;低温报警值存放单元
- FLAG BIT 20H.0 ;DS18B20是否存在标记
- DQ BIT P1.7 ;DS18B20数据脚定义
- TEMPHC EQU 32H ;温度转换低8位缓冲区
- TEMPLC EQU 33H ;温度转换高8位缓冲区
- DISP_BUF EQU 34H ; DISP_BUF为显示缓冲区小数位,DISP_BUF+1为显示缓冲区个数位
- ;DISP_BUF+2为显示缓冲区十位,DISP_BUF +3为显示缓冲区百位
- DOT BIT P0.7 ;小数点控制
- ORG 0000H ;主程序入口地址
- AJMP MAIN ;转主程序MAIN
- ORG 0030H ;主程序从0030H开始
- ;以下是主程序
- MAIN: MOV SP, #50H ;堆栈初始化
- MOV P0, #0FFH ;P0口置1
- START: LCALL GET_TEMP ;调用读温度子程序
- LCALL TEMP_PROC ;调温度BCD处理子程序
- LCALL BCD_REFUR ;调BCD码温度值刷新子程序
- LCALL DISPLAY ;调用数码管显示子程序
- AJMP START ;跳转到START
- ;以下是读出转换后的温度值
- GET_TEMP: SETB DQ ;拉高数据线
- LCALL RESET_1820 ;先复位DS18B20(在驱动程序软件包中)
- JB FLAG, GET_NEXT ;若FLAG=1说明DS18B20存在,跳转到GET_NEXT
- AJMP GET_RET ;若FLAG=0,说明DS18B20不存在,跳转到GET_RET返回
- GET_NEXT: MOV A,#0CCH ;跳过ROM匹配
- LCALL WRITE_1820 ;调写DS18B20子程序(在驱动程序软件包中)
- MOV A,#44H ;发出温度转换命令
- LCALL WRITE_1820 ;调写DS18B20子程序(在驱动程序软件包中)
- LCALL DISPLAY ;调用显示子程序延时,等待A/D转换结束,分辨率为12位时需延时750ms
- ;此语句也可以不加
- LCALL RESET_1820 ;准备读温度前先复位(在驱动程序软件包中)
- MOV A,#0CCH ;跳过ROM匹配
- LCALL WRITE_1820 ;调写DS18B20子程序(在驱动程序软件包中)
- MOV A,#0BEH ;发出读温度命令
- LCALL WRITE_1820 ;调写DS18B20子程序(在驱动程序软件包中)
- LCALL READ_1820 ;调读DS18B20子程序(在驱动程序软件包中)
- GET_RET: RET
- ;以下是温度BCD码处理子程序
- ;以下是温度BCD码处理子程序
- TEMP_PROC: MOV A,TEMPH ;判温度是否零下
- ANL A,#80H ;取出最高位
- JZ TC1 ;若A为0,说明温度为零上,转TC1
- CLR C ;若A为1,说明温度为零下,C清0
- MOV A,TEMPL ;温度值低位TEMPL送A
- CPL A ; TEMPL取反
- ADD A,#01H ; TEMPL取反加1
- MOV TEMPL,A ;取反加1后再送回TEMPL
- MOV A,TEMPH ; TEMPH送A
- CPL A ; TEMPH取反
- ADDC A,#00H ; TEMPH加上进位位
- MOV TEMPH,A ;A的值送回TEMPH
- SJMP TC2 ;跳转到TC2
- TC1: MOV TEMPHC,#0AH ;将0AH送TEMPHC
- TC2: MOV A,TEMPHC ; TEMPHC送A
- SWAP A ;A高低半字节交换
- MOV TEMPHC,A ;交换后送TEMPHC
- MOV A,TEMPL ;温度值低字节TEMPL送A
- ANL A,#0FH ;取出低4位的小数
- MOV DPTR,#DOTTAB ;小数表DOTTAB地址送DPTR
- MOVC A,@A+DPTR ;查出小数
- MOV TEMPLC,A ;小数部分送TEMPLC
- MOV A,TEMPL ; 温度值低字节TEMPL送A
- ANL A,#0F0H ;取出高四位整位部分
- SWAP A ;高低半字节交换
- MOV TEMPL,A ;交换后送TEMPL
- MOV A,TEMPH ;温度值高字节TEMPH送A
- ANL A,#0FH ;取出TEMPH低4位
- SWAP A ;高低半字节交换
- ORL A,TEMPL ;将TEMPH低4位与TEMPL高4位整数部分重新组合
- MOV TEMP_ZH,A ;将组合后的值送TEMP_ZH(实际温度)
- LCALL HEX_BCD ;调十六进制转BCD码子程序
- MOV TEMPL,A ;转换后A送TEMPL
- ANL A,#0F0H ;取高4位
- SWAP A ;高低4位交换
- ORL A,TEMPHC ;与TEMPHC进行或运算
- MOV TEMPHC,A ;送回TEMPHC
- MOV A,TEMPL ; TEMPL送A
- ANL A,#0FH ;取出低4位
- SWAP A ;高低4位交换
- ORL A,TEMPLC ;与TEMPLC进行或运算
- MOV TEMPLC,A ;送回TEMPLC
- MOV A,R4 ;R4送A
- JZ TC3 ;若A为0,退出
- ANL A,#0FH ;若不为0,取出低4位
- SWAP A ;高低4位交换
- MOV R4,A ;送R4
- MOV A,TEMPHC ;TEMPHC送A
- ANL A,#0FH ;取出低4位
- ORL A,R4 ;与R4进行或运算
- MOV TEMPHC,A ;送回TEMPHC
- TC3: RET
- ;以下是单字节十六进制转BCD子程序
- HEX_BCD: MOV B,#100 ;B为100
- DIV AB ; A除以B
- MOV R7,A ; 百位数送R7
- MOV A,#10 ;A为10
- XCH A,B ;A、B值交换
- DIV AB ; A除以B
- SWAP A ;高低半字节交换
- ORL A,B ;或运算
- RET
- ;以下是小数部分码表
- DOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H
- DB 05H,05H,06H,06H,07H,08H,08H,09H
- ;以下是BCD 码温度值刷新子程序
- BCD_REFUR: MOV A,TEMPLC ;取低8位温度值
- ANL A,#0FH ;取出低4位(小数部分)
- MOV DISP_BUF,A ;小数部分送显示缓冲DISP_BUF
- MOV A,TEMPLC ;取低8位温度值
- SWAP A ;高低4位交换
- ANL A,#0FH ;取A低4位,即取出TEMPLC的高4位(个位部分)
- MOV DISP_BUF+1,A ;个位部分送DISP_BUF+1
- MOV A,TEMPHC ;取高8位温度值
- ANL A,#0FH ;取低4位(十位部分)
- MOV DISP_BUF+2,A ;十位部分送DISP_BUF+2
- MOV A,TEMPHC ;取高8位温度值
- SWAP A ;送A
- ANL A,#0FH ;取出低4位,相当于取出TEMPHC的高4位(百位)
- MOV DISP_BUF+3,A ;百位送DISP_BUF+3
- MOV A,TEMPHC ; TEMPHC送A
- ANL A,#0F0H ;取出高4位
- CJNE A,#10H,BCD0 ;百位数是0?
- SJMP BCD_RET ;退出
- BCD0: MOV A, TEMPHC ; TEMPHC送A
- ANL A, #0FH ;取出低4位
- JNZ BCD_RET ; 十位数是0?
- MOV A,TEMPHC ; TEMPHC送A
- SWAP A ;高低4位交换
- ANL A,#0FH ;取出低4位
- MOV DISP_BUF+3,0AH ; 符号位不显示
- MOV DISP_BUF+2,A ;十位数显示符号
- BCD_RET: RET
-
- ;以下是显示子程序
- DISPLAY: MOV DPTR,#TAB ; 指定查表启始地址
- MOV R1,#250 ; 显示250次
- DPLP: SETB DOT ;小数点位为高,不显示小数点
- ;-----------------------------------------------------------------------------
- MOV A,DISP_BUF ; 取小位数
- MOVC A,@A+DPTR ; 查小位数的7段代码
- MOV P0,A ; 送出小位的段码
- SETB P2.3;CLR P2.3 ; 开小位显示
- ACALL DELAY_1ms ; 显示1ms,延时时间不可过长,否则会出现闪烁现象
- CLR P2.3 ;SETB P2.3 ;关小数位
- ;------------------------------------------------------------------------------
- MOV A,DISP_BUF+1 ;取个位数
- MOVC A,@A+DPTR ; 查个位数的7段代码
- MOV P0,A ; 送出个位的段码
- CLR DOT ;显示小数点
- SETB P2.2;CLR P2.2 ;开个位显示
- ACALL DELAY_1ms ; 显示1ms
- CLR P2.2;SETB P2.2 ;关个位
- SETB DOT ;关小数点
- ;--------------------------------------------------------------------------
- MOV A,DISP_BUF+2 ;取十位数
- MOVC A,@A+DPTR ;查十位数的段码
- MOV P0,A ; 送出十位的段码
- SETB P2.1;CLR P2.1 ; 开十位显示
- ACALL DELAY_1ms ; 显示1ms
- CLR P2.1 ;SETB P2.1 ;关十位
- SETB DOT ;关小数点
- ;-------------------------------------------------------------------------------;
- MOV A,DISP_BUF+3 ; 取百位数
- MOVC A,@A+DPTR ; 查百位数的段码
- MOV P0,A ; 送出百位的段码
- SETB P2.0;CLR P2.0 ; 开百位显示
- ACALL DELAY_1ms ; 显示1ms
- CLR P2.0;SETB P2.0 ;关百位
- DJNZ R1,DPLP ; 250次没完循环
- RET
- ;-------------------------------------------------------------------------------------
- ;以下是1ms延时子程序
- DELAY_1ms: MOV R7,#5
- LOOP2: MOV R6,#100
- LOOP1: DJNZ R6,LOOP1
- DJNZ R7,LOOP2
- RET
- ;以下是数码管显示代码
- TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H ;0-9显示码
- DB 0FFH,0BFH ;"熄灭"、 "-"显示码
- ;以下是 DS18B20复位初始化子程序
- RESET_1820: SETB DQ
- NOP
- CLR DQ
- MOV R1,#3 ;主机发出延时500us的复位低脉冲
- DLY: MOV R0,#107
- DJNZ R0,$
- DJNZ R1,DLY
- SETB DQ ;拉高数据线
- NOP
- NOP
- NOP
- MOV R0,#25H
- RST2: JNB DQ , RST3 ;等待DS18B20回应
- DJNZ R0, RST2
- JMP RST4
- RST3: SETB FLAG ;置标志位,表示DS18B20存在
- JMP RST5
- RST4: CLR FLAG ;清标志位,表示DS18B20不存在
- JMP RST7
- RST5: MOV R0,#117
- RST6: DJNZ R0, RST6 ;时序要求延时一段时间
- RST7: SETB DQ
- RET
- ;以下是写DS18B20子程序
- WRITE_1820: MOV R2,#8 ;共8位数据
- CLR C
- WR1: CLR DQ ;总线低位,开始写入
- MOV R3,#6
- DJNZ R3,$ ;保持16微秒以上
- RRC A ;把字节DATA分成8个BIT环移给C
- MOV DQ, C ;写入一个BIT
- MOV R3,#23
- DJNZ R3,$ ;等待
- SETB DQ ;重新释放总线
- NOP
- DJNZ R2,WR1 ;写入下一个BIT
- SETB DQ
- RET ;写入子程序
- ;以下是读DS18B20子程序(将温度低位、高位、报警高位TH、报警低位TL从DS18B20中读出)
- READ_1820: MOV R4,#4 ;读取4字节
- MOV R1,#TEMPL ;存入TEMPL (25H)、TEMPLH(26H)、TEMP_TH (27H)、TEMP_TL(28H)
- READ0: MOV R2,#8 ;数据一共有8位
- READ1: CLR C
- SETB DQ
- NOP
- NOP
- CLR DQ ;读前总线保持为低
- NOP
- NOP
- NOP
- SETB DQ ;开始读总线释放
- MOV R3,#9
- DJNZ R3,$ ;延时18微妙
- MOV C, DQ ;从总线读到一个BIT
- MOV R3,#23 ;
- DJNZ R3,$ ;等待50us
- RRC A ;把读得的位价值环移给A
- DJNZ R2,READ1 ;读下一个BIT
- MOV @R1,A
- INC R1 ; R1内数据递增
- DJNZ R4,READ0
- RET
- END
复制代码
所有资料51hei提供下载:
18b20单支.rar
(41.51 KB, 下载次数: 31)
|