;********************************************************
;************************显视温度************************
;********************************************************
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
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