50分跪求一18B20测温计程序

在线等~
2024-12-03 16:18:13
推荐回答(2个)
回答1:

;********************************************************
;************************显视温度************************
;********************************************************
COUNT DATA 30H ;地址计数常数
WENDU DATA 32H ;实际温度地址
WENDUD DATA 33H ;温度低位地址
WENDUG DATA 34H ;温度高位地址
SDWDG DATA 35H ;设定高温度地址
SDWDD DATA 36H ;设定低温度地址
;----------------------------------------------------------------
RS EQU P2.0 ;
RW EQU P2.1 ;
E EQU P2.2 ;
PSB EQU P2.3 ;
RST EQU P2.5 ;
SHUJU EQU P3.3 ;
K1 EQU P1.4 ;按键1,设定温度值减1
K2 EQU P1.5 ;按键2,设定温度值加1
K3 EQU P1.6 ;按键3,确定修改和确定退出
;============================================================
ORG 0000H
JMP MAIN
ORG 0040H
;============================================================
MAIN: CLR P3.7
LCALL SET_LCD ;初始化 LCD 12864
LCALL W18B20 ;初始化18B20
LCALL CWD
;********************************************************
WANG: LCALL W18B20 ;初始化18B20
LCALL DU18B20 ;读18B20温度
LCALL S18B20 ;送温度显视
LCALL ANJIAN ;按键程序
LJMP WANG
;==============================================================
;对 LCD12864 做初始化设置
;==============================================================
SET_LCD:
SETB PSB ;通讯方式为8位数据并口
MOV A,#34H ;34H--扩充指令操作
LCALL SEND_I
MOV A,#30H ;30H--8bit控制界面,基本指令操作
LCALL SEND_I
MOV A,#01H ;清除显示
LCALL SEND_I
MOV A,#06H ;指定在资料写入或读取时,光标的移动方向
LCALL SEND_I ;DDRAM 的地址计数器(AC)加1
MOV A,#0CH ;开显示,关光标,不闪烁
LCALL SEND_I
RET
;==============================================================
;写指令子程序
;RS=0,RW=0,E=高脉冲,D0-D7=指令码
;==============================================================
SEND_I: LCALL CHK_BUSY
CLR RS
CLR RW
MOV P0,A
SETB E
NOP
NOP
CLR E
RET
;==============================================================
;测忙碌子程序
;RS=0,RW=1,E=H,D0-D7=状态字
;==============================================================
CHK_BUSY:
MOV P0,#0FFH ;测忙碌子程序
CLR RS
SETB RW
SETB E
JB P0.7,$
CLR E
RET
;==============================================================
;把 DS18B20 EEROM 里的温度报警值拷贝回暂存器(暂时用不到)
;==============================================================
CWD: LCALL W18B20
MOV A,#0CCH ;跳过ROM匹配
LCALL XIEB20
MOV A,#0B8H ;把EEROM里的温度报警值拷贝回暂存器
LCALL XIEB20
RET

;***************************************************
;DS18B20 复位与检测子程序
;SHUJU=1 OK, SHUJU=0 ERROR
;****************************************************
W18B20: SETB SHUJU
NOP
CLR SHUJU
MOV R0,#64H ; 主机发出延时600微秒的复位低脉冲
MOV R1,#03H
W11: DJNZ R0,$
MOV R0,#64H
DJNZ R1,W11
SETB SHUJU ; 然后拉高数据线
NOP
MOV R0,#25H
WW2: JNB SHUJU,WW3 ; 等待DS18B20回应
DJNZ R0,WW2
JMP WW4 ; 延时
WW3: SETB 20H.0 ; 置标志位,表示DS1820存在
JMP WW5
WW4: CLR 20H.0 ; 清标志位,表示DS1820不存在
JMP WW6
WW5: MOV R0,#064H
DJNZ R0,$ ; 时序要求延时一段时间
WW6: SETB SHUJU
JNB 20H.0,AAAA ;DS18B20出错
RET
;==============================================================
;DS18B20错误时LCD显示子程序
;==============================================================
AAAA: MOV DPTR,#M_ERROR1 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#80H ;第一行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERROR2 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#90H ;第二行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERROR3 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#88H ;第三行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERROR4 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#98H ;第四行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
LCALL MING1
RET
;--------------------------------------------------------------
; 读18B20温度
;***********************************************************
DU18B20:
MOV A,#0CCH ;
LCALL XIEB20
MOV A,#44H ;发出温度转换命令
LCALL XIEB20 ;
LCALL W18B20 ;
MOV A,#0CCH ;
LCALL XIEB20 ;写18B20指令
MOV A,#0BEH ;发出读温度命令
LCALL XIEB20 ;
LCALL WDSJ ;温度数据
RET
;===========================================================
;写入18B20指令
;===========================================================
XIEB20: MOV R2,#8 ;一共8位数据
CLR CY
XIE: CLR SHUJU ;开始写入DS18B20总线要处于复位(低)状态
MOV R3,#09
DJNZ R3,$ ;总线复位保持18微妙以上
RRC A ;把一个字节DATA 分成8个BIT环移给C
MOV SHUJU,C ;写入一个BIT
MOV R3,#23
DJNZ R3,$ ;等待46微妙
SETB SHUJU ;重新释放总线
NOP
DJNZ R2,XIE ;写入下一个BIT
SETB SHUJU
RET
;******************************************************
;读温度子程序
;从DS18B20中读出温度低位、高位,
;存入33H,34H,35H,36H
;****************************************************
WDSJ: MOV R4,#04H
MOV R1,#33H ; 存入33H,34H
RE00: MOV R2,#8
RE01: CLR C
SETB SHUJU
NOP
NOP
CLR SHUJU ;读前总线保持为低
NOP
NOP
NOP
SETB SHUJU ;开始读总线释放
MOV R3,#07 ;延时15微妙
DJNZ R3,$
MOV C,SHUJU ;从DS18B20总线读得一个BIT
MOV R3,#23
DJNZ R3,$ ;等待46微妙
RRC A ;把读得的位值环移给A
DJNZ R2,RE01 ;读下一个BIT
MOV @R1,A
INC R1
DJNZ R4,RE00
LCALL WDCZ
RET
;==============================================================
;处理入水口实际水温度 BCD 码子程序(未考虑百位和负温度值)
;整数部分:取出 WENDUD 高四位和 WENDUG 低四位进行重新组合
;小数部分:取出 TEMPL1 低四位,查小数码表
;小数部分:73H;个位:74H;十位:75H
;==============================================================
WDCZ:
MOV A,WENDUD
ANL A,#0FH ;取出小数部分
MOV B,#10 ;将TEMP_L的低四位X10/16得小数后一位数.
MUL AB
MOV B,#16
DIV AB
MOV 73H,A ;小数部分 BCD

MOV A,WENDUD ;整数部分
ANL A,#0F0H ;取出高四位
SWAP A
MOV WENDUD,A
MOV A,WENDUG ;取出低四位
ANL A,#0FH
SWAP A
ORL A,WENDUD ;重新组合温度数据
MOV WENDU,A ;重新组合的温度数据存入WENDU
LCALL HEX2BCD1

MOV WENDUD,A ;(A)=十位数和个位数
ANL A,#0F0H
SWAP A
MOV 75H,A ;十位数 BCD
MOV A,WENDUD
ANL A,#0FH
MOV 74H,A ;个位数 BCD
RET
;==============================================================
;单字节十六进制转BCD
;入口:(A)=单字节十六进制的温度值
;出口:(A)=十位数和个位数
;==============================================================
HEX2BCD1:
MOV B,#0AH
DIV AB
SWAP A
ORL A,B ;(A)=个位数和十位数
RET
;**********************************************************
;**********************送显示******************************
;**********************************************************
S18B20:
MOV DPTR,#M_OK2 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#80H ;第一行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
LCALL SHOW_D ;显示设定的恒温水温度值

MOV DPTR,#M_OK1 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#90H ;第二行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
LCALL SHOW_G ;显示设定的恒温水温度值

MOV DPTR,#M_OK3 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#88H ;第三行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
LCALL SHOW_S ;显示实际温度值

MOV DPTR,#M_OK4 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#98H ;第四行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
RET
;==============================================================
;显示恒温水温度值子程序
;==============================================================
SHOW_G: MOV A,#86H ;设置显示位置
LCALL SEND_I
MOV A,SDWDG
MOV B,#0AH
DIV AB
ADD A,#30H ;十位数转换为 ASCII 码
LCALL SEND_D ;送显示
MOV A,B ;个位数
ADD A,#30H ;个位数转换为 ASCII 码
LCALL SEND_D ;送显示 ;显示恒温水温度值子程序
MOV A,#87H ;设置显示位置
LCALL SEND_I
MOV A,#0A1H ;显示温度标记℃
LCALL SEND_D
MOV A,#0E6H
LCALL SEND_D
SHOW_D: MOV A,#96H ;设置显示位置
LCALL SEND_I
MOV A,SDWDD
MOV B,#0AH
DIV AB
ADD A,#30H ;十位数转换为 ASCII 码
LCALL SEND_D ;送显示
MOV A,B ;个位数
ADD A,#30H ;个位数转换为 ASCII 码
LCALL SEND_D ;送显示 ;显示恒温水温度值子程序
MOV A,#97H ;设置显示位置
LCALL SEND_I
MOV A,#0A1H ;显示温度标记℃
LCALL SEND_D
MOV A,#0E6H
LCALL SEND_D
RET
;==============================================================
; LCD12864 显示实际温度值子程序
;==============================================================
SHOW_S: MOV A,#8DH ;设置显示位置
LCALL SEND_I
MOV A,75H ;加载十位数据
CJNE A,#00H,CONV2
CONV1: MOV A,#" " ;十位数等于0显示空格
LCALL SEND_D ;送显示
JMP CONV3
CONV2: ADD A,#30H ;十位数转换成ASCII码
LCALL SEND_D ;显示数据
CONV3: MOV A,74H ;个位
ADD A,#30H ;个位数转换成ASCII码
CALL SEND_D ;送显示
MOV A,#'.'
CALL SEND_D ;送显示
MOV A,73H ;加载小数位
ADD A,#30H ;小数位转换成ASCII码
CALL SEND_D ;送显示
MOV A,#8FH ;显示温度标记℃
CALL SEND_I
MOV A,#0A1H
CALL SEND_D
MOV A,#0E6H
CALL SEND_D
RET
;==============================================================
;取数子程序
;==============================================================
QUSHU: CLR A
MOVC A,@A+DPTR ;查表取数据
LCALL SEND_D ;送显示
INC DPTR
DJNZ COUNT,QUSHU
RET
;==============================================================
;写数据子程序
;RS=1,RW=0,E=高脉冲,D0-D7=数据
;==============================================================
SEND_D: LCALL CHK_BUSY ;写数据子程序
SETB RS
CLR RW
MOV P0,A
SETB E
NOP
NOP
CLR E
RET
;--------------------------------------------------------------
MING1: SETB P3.7
LCALL YS
CLR P3.7
RET
YS: MOV R5,#8FH
YS1: MOV R6,#0FFH
YS2: DJNZ R6,$
DJNZ R5,YS1
RET
;************************按键程序***********************
ANJIAN: JB K3,ANJIAN_0 ;按键K3确定修改
LCALL YS ;防抖动
JB K3,ANJIAN_0
LCALL MING1
LCALL BBBB
JNB K3,$
ANJI_1: JB K2,JIAN_2 ;按键K2设定值加1
LCALL YS ;防抖动
JB K2,JIAN_2
LCALL MING1
MOV A,SDWDG
INC A
MOV SDWDG,A
CLR C
CJNE A,#63H,JIAN_01
JMP JIAN_02
JIAN_01:JC JIAN_02
MOV SDWDG,#00H
JIAN_02:
LCALL BBBB
JNB K2,$
JIAN_2: JB K1,ANJI_3 ;按键K1设定值减1
LCALL YS ;防抖动
JB K1,ANJI_3
LCALL MING1
MOV A,SDWDG
DEC A
MOV SDWDG,A
CLR C
CJNE A,#63H,JIAN_21
JIAN_21:JC JIAN_22
MOV SDWDG,#63H
JIAN_22:JNB K1,$
LCALL BBBB
ANJI_3: JB K3,ANJI_1 ;按键K3确定退出
LCALL YS ;防抖动
JB K3,ANJI_1
LCALL MING1
LCALL CCCC
JNB K3,$
LJMP ANJI_4
ANJIAN_0:LJMP ANJIAN_9
ANJI_4: JB K2,JIAN_5 ;按键K2设定值加1
LCALL YS ;防抖动
JB K2,JIAN_5
LCALL MING1
MOV A,SDWDD
INC A
MOV SDWDD,A
CLR C
CJNE A,#63H,JIAN_31
JMP JIAN_32
JIAN_31:JC JIAN_32
MOV SDWDD,#00H
JIAN_32:LCALL CCCC
JNB K2,$
JIAN_5: JB K1,ANJI_6 ;按键K1设定值减1
LCALL YS ;防抖动
JB K1,ANJI_6
LCALL MING1
MOV A,SDWDD
DEC A
MOV SDWDD,A
CLR C
CJNE A,#63H,JIAN_41
JIAN_41:JC JIAN_42
MOV SDWDD,#63H
JIAN_42:JNB K1,$
LCALL CCCC
ANJI_6: JB K3,ANJI_4 ;按键K3确定退出
LCALL YS ;防抖动
JB K3,ANJI_4
LCALL MING1
JNB K3,$
ANJIAN_9:LCALL CUN
RET
;==============================================================
;重新对 DS18B20 初始化
;将设定的温度报警值写入 DS18B20
;==============================================================
CUN: LCALL W18b20
MOV A,#0CCH ;跳过ROM匹配
LCALL XIEB20
MOV A,#4EH ;写暂存寄存器
LCALL XIEB20
MOV A,SDWDG
LCALL XIEB20
MOV A,SDWDD
LCALL XIEB20
; MOV A,#7FH ;12位精确度
; LCALL XIEB20
LCALL W18B20 ;把 DS18B20 暂存器里的温度报警值拷贝到EEROM
MOV A,#0CCH ;跳过ROM匹配
LCALL XIEB20
MOV A,#48H ;把暂存器里的温度报警值拷贝到EEROM
LCALL XIEB20
RET
;--------------------------------------------------------------
show_g1:MOV A,#93H ;设置显示位置
LCALL SEND_I
MOV A,SDWDG
MOV B,#0AH
DIV AB
ADD A,#30H ;十位数转换为 ASCII 码
LCALL SEND_D ;送显示
MOV A,B ;个位数
ADD A,#30H ;个位数转换为 ASCII 码
LCALL SEND_D ;送显示 ;显示恒温水温度值子程序
MOV A,#94H ;设置显示位置
LCALL SEND_I
MOV A,#0A1H ;显示温度标记℃
LCALL SEND_D
MOV A,#0E6H
LCALL SEND_D
RET
BBBB:
MOV DPTR,#M_ERRORA ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#80H ;第一行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERRORB ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#90H ;第二行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
lcall show_g1
LJMP DDDD
CCCC:
MOV DPTR,#M_ERRORC ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#80H ;第一行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERRORD ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#90H ;第二行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
lcall show_d
DDDD: MOV DPTR,#M_ERROR3 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#88H ;第三行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU

MOV DPTR,#M_ERROR4 ;指针指到显示信息区
MOV COUNT,#10H ;地址计数器设为16
MOV A,#98H ;第四行起始地址
LCALL SEND_I ;调用写指令子程序
LCALL QUSHU
RET
;--------------------------------------------------------------
M_OK1: DB '设定低温度: ' ;显示在第一行
M_OK2: DB '设定高温度: ' ;显示在第二行
M_OK3: DB '实际温度: ' ;显示在第三行
M_OK4: DB ' QQ:80908900 ' ;显示在第四行
M_ERRORA: DB ' 设定高温度! ' ;显示在第一行
M_ERRORB: DB ' ' ;显示在第二行
M_ERRORC: DB ' 设定低温度! ' ;显示在第一行
M_ERRORD: DB ' ' ;显示在第二行
M_ERROR1: DB ' 温度探头错误!' ;显示在第一行
M_ERROR2: DB ' 请检查! ' ;显示在第二行
M_ERROR3: DB ' 风也有情 ' ;显示在第三行
M_ERROR4: DB ' QQ:80908900 ' ;显示在第四行
;*************************************************************
END

回答2:

TEMPER_L EQU 36H

TEMPER_H EQU 35H

TEMPER_NUM EQU 60H

jishu EQU 37H

FLAG1 BIT 00H

DQ BIT P3.5

AAA:SETB P2.0

CLR P2.1

MOV SP,#70H

LCALL GET_TEMPER

LCALL TEMPER_COV

loop4:mov r5,#20

loop3:mov 38H,#0ffh

LOOP2:mov A,TEMPER_NUM

MOV B,#10

;MOV B,R5

DIV AB

SETB P2.2

CLR P2.3

MOV DPTR,#TABLE1

MOVC A,@A+DPTR

MOV P0,A

LCALL DELy

SETB P2.3

CLR P2.2

MOV A,B

MOV DPTR,#TABLE2

MOVC A,@A+DPTR

MOV P0,A

LCALL DELy

djnz 38H,loop2

djnz r5, loop3

sjmp aaa

NOP

;------------------读出转换后的温度值

GET_TEMPER:

SETB DQ ; 定时入口

BCD:LCALL INIT_1820

JB FLAG1,S22

LJMP BCD ; 若DS18B20不存在则返回

S22:LCALL DELAY1

MOV A,#0CCH ; 跳过ROM匹配------0CC

LCALL WRITE_1820

MOV A,#44H ; 发出温度转换命令

LCALL WRITE_1820

NOP

LCALL DELAY

LCALL DELAY

CBA:LCALL INIT_1820

JB FLAG1,ABC

LJMP CBA

ABC:LCALL DELAY1

MOV A,#0CCH ; 跳过ROM匹配

LCALL WRITE_1820

MOV A,#0BEH ; 发出读温度命令

LCALL WRITE_1820

LCALL READ_18200 ;READ_1820

RET

;------------------读DS18B20的程序,从DS18B20中读出一个字节的数据

READ_1820:

MOV R2,#8

RE1:

CLR C

SETB DQ

NOP

NOP

CLR DQ

NOP

NOP

NOP

SETB DQ

MOV R3,#7

DJNZ R3,$

MOV C,DQ

MOV R3,#23

DJNZ R3,$

RRC A

DJNZ R2,RE1

RET

;-------------------写DS18B20的程序

WRITE_1820:

MOV R2,#8

CLR C

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

;-------------------读DS18B20的程序,从DS18B20中读出两个字节的温度数据

READ_18200:

MOV R4,#2 ; 将温度高位和低位从DS18B20中读出

MOV R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_H)

RE00:

MOV R2,#8

RE01:

CLR C

SETB DQ

NOP

NOP

CLR DQ

NOP

NOP

NOP

SETB DQ

MOV R3,#7

DJNZ R3,$

MOV C,DQ

MOV R3,#23

DJNZ R3,$

RRC A

DJNZ R2,RE01

MOV @R1,A

DEC R1

DJNZ R4,RE00

RET

;-------------------将从DS18B20中读出的温度数据进行转换

TEMPER_COV:

MOV A,#0F0H

ANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值

SWAP A

MOV TEMPER_NUM,A

MOV A,TEMPER_L

JNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值

INC TEMPER_NUM

TEMPER_COV1:

MOV A,TEMPER_H

ANL A,#07H

SWAP A

ORL A,TEMPER_NUM

MOV TEMPER_NUM,A ; 保存变换后的温度数据

RET

;-------------------将16进制的温度数据转换成压缩BCD码

;-------------------DS18B20初始化程序

INIT_1820:

SETB DQ

NOP

CLR DQ

MOV R0,#80H

TSR1:

DJNZ R0,TSR1 ; 延时

SETB DQ

MOV R0,#25H ;96US-25H

TSR2:

DJNZ R0,TSR2

JNB DQ,TSR3

LJMP TSR4 ; 延时

TSR3:

SETB FLAG1 ; 置标志位,表示DS1820存在

LJMP TSR5

TSR4:

CLR FLAG1 ; 清标志位,表示DS1820不存在

LJMP TSR7

TSR5:

MOV R0,#06BH ;200US

TSR6:

DJNZ R0,TSR6 ; 延时

TSR7:

SETB DQ

RET

;------------------重新写DS18B20暂存存储器设定值

RE_CONFIG:

JB FLAG1,RE_CONFIG1 ; 若DS18B20存在,转RE_CONFIG1

RET

RE_CONFIG1:

MOV A,#0CCH ; 发SKIP ROM命令

LCALL WRITE_1820

MOV A,#4EH ; 发写暂存存储器命令

LCALL WRITE_1820

MOV A,#00H ; TH(报警上限)中写入00H

LCALL WRITE_1820

MOV A,#00H ; TL(报警下限)中写入00H

LCALL WRITE_1820

MOV A,#7FH ; 选择12位温度分辨率

LCALL WRITE_1820

RET

;------------------延时子程序

DELAY:MOV R7,#00H

MIN:DJNZ R7,YS500

RET

YS500:LCALL YS500US

LJMP MIN

YS500US:MOV R6,#00H

DJNZ R6,$

RET

DELAY1:MOV R7,#20H

DJNZ R7,$

RET

dely: mov r3,#100

djnz r3,$

ret

TABLE1: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H

TABLE2: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H