TEMP_ZH EQU 24H ;实测温度值存放单元
TEMPL EQU 25H
TEMPH EQU 26H
TEMP_TH EQU 27H ;高温报警值存放单元
TEMP_TL EQU 28H ;低温报警值存放单元
TEMPHC EQU 29H ;正、负温度值标记
TEMPLC EQU 2AH
TEMPFC EQU 2BH
K1 EQU P1.4 ;查询按键
K2 EQU P1.5 ;设置/调整键
K3 EQU P1.6 ;调整键
K4 EQU P1.7 ;确定键
BEEP EQU P3.7 ;蜂鸣器
RELAY EQU P1.3 ;指示灯
LCD_X EQU 2FH ;LCD字符显示位置
LCD_RS EQU P2.0 ;LCD寄存器选择信号
LCD_RW EQU P2.1 ;LCD读/写信号
LCD_EN EQU P2.2 ;LCD 允许信号
FLAG1 EQU 20H.0 ;DS18B20是否存在标志
KEY_UD EQU 20H.1 ;设定按键的增、减标志
DQ EQU P3.3 ;DS18B20数据信号
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:MOV SP, #60H
MOV A, #00H
MOV R0, #20H ;将20H~2FH单元清零
MOV R1,#10H
CLEAR:MOV @R0,A
INC R0
DJNZ R1,CLEAR
LCALL SET_LCD ;调用LCD初始化,测试子程序
LCALL RE_18B20
START:LCALL RST
JNB FLAG1,START1 ;DS1820不存在
LCALL MENU_OK ;DS1820存在,调用显示正确信息子程序
MOV TEMP_TH, #055H ;设置TH初值85度
MOV TEMP_TL, #019H ;设置TL初值25度
LCALL RE_18B20A ;调用暂存器操作子程序
LCALL WRITE_E2 ;写入DS18B20
LCALL TEMP_BJ ;显示温度标记
JMP START2
START1:LCALL MENU_ERROR ;调用显示出错信息子程序
LCALL TEMP_BJ ;显示温度标记
SJMP $
START2:LCALL RST ;调用DS18B20复位子程序
JNB FLAG1,START1 ;DS18B20不存在
MOV A,#0CCH ;跳过ROM匹配命令
LCALL WRITE
MOV A,#44H ;温度转换命令
LCAll WRITE
LCALL RST
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE
MOV A,#0BEH ;读温度命令
LCALL WRITE
LCAlL READ ;调用DS18B20数据读取操作子程序
LCAll CONVTEMP ;调用温度数据BCD码处理子程序
LCALL DISPBCD ;调用温度数据显示子程序
LCALL CONV ;调用LCD显示处理子程序
LCALL TEMP_COMP ;调用实测温度值与设定温度值比较子程序
LCALL PROC_KEY ;调用键扫描子程序
SJMP START2 ;循环
; *******键扫描子程序
PROC_KEY:JB K1,PROC_K1
LCALL BEEP_BL;
JNB K1,$
MOV DPTR,#M_ALAX1
MOV A,#1
LCALL LCD_PRINT
LCALL LOOK_ALARM
JB K3,$
LCALL BEEP_BL
JMP PROC_K2
PROC_K1: JB K2,PROC_END
LCALL BEEP_BL
JNB K2,$
MOV DPTR,#RST_Al
MOV A,#1
LCALL LCD_PRINT
LCALL SET_ALARM
LCALL RE_18B20 ;将设定的TH, tl值写入D18B20
LCALL WRITE_E2
PROC_K2:LCALL MENU_OK
LCALL TEMP_BJ
PROC_END:RET
;**********************************************设定温度报警值TH,TL
SET_ALARM:LCALL LOOK_ALARM
AS0:JB K1,AS00
LCALL BEEP_BL
JNB K1,$
CPL 20H.1 ;UP/DOWN标记
AS00:JB 20H.1,ASZ01 ;20H.1=1,增加
JMP ASJ01 ;20H.1=0,减小
ASZ01:
JB K2,ASZ02 ;TH值调整(增加)
LCALL BEEP_BL
INC TEMP_TH
MOV A,TEMP_TH
CJNE A,#120,ASZ011
MOV TEMP_TH,#0
ASZ011:LCALL LOOK_ALARM
MOV R5,#10
LCALL DELAY
JMP ASZ01
ASZ02:JB K3,ASZ03 ;TL值调整(增加)
LCALL BEEP_BL
INC TEMP_TL
MOV A,TEMP_TL
CJNE A,#99,ASZ021
MOV TEMP_TL,#00H
ASZ021:LCAlL LOOK_ALARM
MOV R5,#10
LCALL DELAY
JMP ASZ02
ASZ03:JB K4,AS0 ;确定调整
LCALL BEEP_BL
JNB K4,$
RET
ASJ01:JB K2,ASJ02 ;TH值调整(减少)
LCALL BEEP_BL
DEC TEMP_TH
MOV A,TEMP_TH
CJNE A,#0FH,ASJ011
JMP ASJ022
ASJ011: LCALL LOOK_ALARM
MOV R5,#10
LCAll DELAY
JMP AS0
ASJ02:JB K3,ASJ03
LCALL BEEP_BL ;TL值调整(减少)
DEC TEMP_TL
MOV A,TEMP_TL
CJNE A,#0FFH,ASJ021
JMP ASJ022
ASJ021: LCALL LOOK_ALARM
MOV R5,#10
LCALL DELAY
JMP AS0
ASJ022: CPL 20H.1
JMP ASZ01
ASJ03:JMP ASZ03
RET
RST_Al:DB "SET ALERT CODE ",0
;**********************************************实测温度值与设定温度值比较子程序********.*
TEMP_COMP:MOV A,TEMP_TH
SUBB A,TEMP_ZH ;减数>被减数
JC CHULI1 ;借位标志位C=1,跳转
MOV A,TEMPFC
CJNE A,#0BH,COMP
SJMP CHULI2
COMP: MOV A, TEMP_ZH
SUBB A, TEMP_TL ;减数>被减数
JC CHULI2 ;借位标志位C=1,跳转
MOV DPTR,#BJ5
LCALL TEMP_BJ3
CLR RELAY ;点亮指示灯
RET
CHULI1: MOV DPTR,#BJ3
LCALL TEMP_BJ3
SETB RELAY ;熄灭指示灯
LCALL BEEP_BL ;蜂鸣器响
RET
CHULI2: MOV DPTR,#BJ4
LCAlL TEMP_BJ3
SETB RELAY ;熄灭指示灯
LCALL BEEP_BL ;蜂鸣器响
RET
;**********************************************
TEMP_BJ3: MOV A,#0CEH
LCALL WCOM
MOV R1,#0
MOV R0,#2
BBJJ3:
MOV A, R1
MOVC A,@A+DPTR
LCALL WDATA
INC R1
DJNZ R0,BBJJ3
RET
BJ3:DB ">H"
BJ4:DB "<L"
BJ5:DB "!"
;**********************************************p308显示温度标记子程序
TEMP_BJ: MOV A,#0CBH
LCALL WCOM
MOV DPTR,#BJ1 ;指针指到显示消息
MOV R1,#0
MOV R0,#2
BBJJ1:MOV A,R1
MOVC A,@A+DPTR
LCALL WDATA
INC R1
DJNZ R0,BBJJ1
RET
BJ1:DB 00H,"C"
;**********************************************显示正确信息子程序
MENU_OK:MOV DPTR,#M_OK1 ;指针指到显示消息
MOV A,#1 ;显示在第一行
LCALL LCD_PRINT
MOV DPTR, #M_OK2 ;指针指到显示消息
MOV A,#2 ;显示在第一~行
LCAlL LCD_PRINT
RET
M_OK1:DB "DS18B20 OK",0
M_OK2:DB "TEMP: ",0
;**********************************************显示出错信息子程序
MENU_ERROR:MOV DPTR,#M_ERROR1;指针指到显示消息
MOV A,#1 ;显示在第一行
LCALL LCD_PRINT
MOV DPTR, #M_OK2 ;指针指到显示消息
MOV A,#2 ;显示在第一行
LCAlL LCD_PRINT
RET
M_ERROR1:DB "DS18B20 ERROR",0
M_ERROR2:DB "TEMP:---- ",0
;**********************************************DS18B20复位子程序
RST: SETB DQ
NOP
CLR DQ
MOV R0,#6BH ;主机发出延时复位低脉冲
MOV R1,#04H
TSR1:DJNZ R0,$
MOV R0,#6BH
DJNZ R1,TSR1
SETB DQ ;拉高数据线
NOP
NOP
NOP
MOV R0,#32H
TSR2:
JNB DQ,TSR3 ;停待DS18B20回应
DJNZ R0,TSR2
JMP TSR4 ;延时
TSR3:SETB FLAG1 ;置1标志位,表示DS1820存在
JMP TSR5;
TSR4:CLR FLAG1 ;清0标志位,表示DS1820不存在
JMP TSR7
TSR5:MOV R0,#06BH
TSR6:DJNZ R0,$ ;时序要求延时一段时间
TSR7:SETB DQ
RET
;**********************************************DS18B20暂存器操作子程序
RE_18B20:JB FLAG1,RE_18B20A
RET
RE_18B20A:LCAlL RST
MOV A, #0CCH ;跳过ROM匹配
LCALL WRITE
WR_SCRAPD:
MOV A, #4EH ;写暂存器
LCALL WRITE
MOV A, TEMP_TH ;TH (报警上限)
LCALL WRITE
MOV A, TEMP_TL ;TL (报警下限)
LCAlL WRITE
MOV A,#7FH ;12位精度
LCALL WRITE
RET
;**********************************************复制暂存器子程序
WRITE_E2:LCALL RST
MOV A, #0CCH ;跳过ROM匹配
LCALL WRITE
MOV A, #48H ;把暂存器里的温度报警值复制到EROI
LCALL WRITE
RET
;**********************************************重读BEROM子程序
READ_E2:LCALL RST
MOV A, #0CCH ;跳过ROM匹配
LCALL WRITE
MOV A, #0B8H ;把BBROM里的温度报警值复制回暂
LCALL WRITE
RET
;**********************************************将自定义字符写入LCD的CGRAM中
STORE_DATA:
MOV A,#40H
LCALL WCOM
MOV R2,#08H
MOV DPTR,#D_DATA
MOV R3,#00H
S_DATA:MOV A,R3
MOVC A,@A+DPTR
LCALL WDATA ;写入数据
INC R3
DJNZ R2,S_DATA
RET
D_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00H
;**********************************************DS18B20数据写入操作子程序
WRITE: MOV R2,#8 ;一共8位数据
CLR C
WR1:CLR DQ ;开始写入D18B20总线要处于复位(低)状态
MOV R3,#07
DJNZ R3,$ ;总线复位保持16uS以上
RRC A ;把一个字节DATA分成8个BIT环移给C
MOV DQ,C ;写入一位
MOV R3,#3CH
DJNZ R3,$ ;等待100us
SETB DQ ;重新释放总线
NOP
DJNZ R2,WR1 ;写入下一位
SETB DQ
RET
;**********************************************DS18B20数据读取操作子程序
READ:MOV R4,#4 ;将温度低位、高位、TH、 TL从DS18B20中读
MOV R1,#TEMPL ;存入 25H、 26H、27H、28H单元
RE00:MOV R2,#8
RE01:CLR CY
SETB DQ
NOP
NOP
CLR DQ ;读前总线保持为低
NOP
NOP
NOP
SETB DQ ;开始读总线释放
MOV R3,#09 ;延时18us
DJNZ R3,$
MOV C,DQ
MOV R3,#3CH ;从DS18B20总线读得一位
DJNZ R3,$ ;等待100us
RRC A ;把读得的位值环移给A
DJNZ R2,RE01 ;读下一位
MOV @R1,A
DJNZ R4,RE00
RET
;;**********************************************温度值BCD码处理子程序
CONVTEMP:MOV A,TEMPH ;判温度是否零下
ANL A,#08H
JZ TEMPC1 ;温度为零上则跳转
CLR C
MOV A,TEMPL ;二进制数求补(双字节)
CPL A ;取反加1
ADD A,#01H
MOV TEMPL,A
MOV A,TEMPH
CPL A
ADDC A,#00H
MOV TEMPH,A
MOV TEMPHC,#0BH ;负温度标志
MOV TEMPFC,#0BH
SJMP TEMPC11
TEMPC1: MOV TEMPHC,#0AH;正温度标志
MOV TEMPFC,#0AH
TEMPC11 :MOV A,TEMPHC
SWAP A
MOV TEMPHC,A
MOV A,TEMPL
ANL A,#0FH ;乘0.0625
MOV DPTR,#TEMPDOTTAB
MOVC A,@A+DPTR ;TEMPLC Low=小数部分BCD
MOV TEMPLC,A
MOV A,TEMPL ;整数部分
ANL A,#0F0H ;取出高四位
SWAP A
MOV TEMPL,A
MOV A,TEMPH ;取出低四位
ANL A,#0FH
SWAP A ;重新组合
ORL A, TEMPL
MOV TEMP_ZH,A
LCALL HEX2BCD1
MOV TEMPL,A
ANL A,#0F0H
SWAP A
ORL A,TEMPHC ;TEMP HC LOW-十位数BCD
MOV TEMPHC,A
MOV A, TEMPL
ANL A,#0FH
SWAP A ;TEMPLC HI=个位数BCD
ORL A, TEMPLC
MOV TEMPLC,A
MOV A,R4
JZ TEMPC12
ANL A,#0FH
SWAP A
MOV R4,A;TEMPHC HI
MOV A, TEMPHC ;TEMPHC HI=百位数BCD
ANL A,#0FH
ORL A,R4
MOV TEMPHC,A
TEMPC12:RET
;**********************************************二-十迸制转換子程序
HEX2BCD1 :MOV B, #064H
DIV AB
MOV R4,A
MoV A,#0AH
XCH A,B
DIV AB
SWAP A
ORL A,B
RET
TEMPDOTTAB:
DB 00H, 00H, 01H, 01H, 02H, 03H, 03H,04H ;小数部分碼表
DB 05H, 05H, 06H, 06H, 07H, 08H, 08H,09H
;**********************************************査洵温度扱警値子程序
LOOK_ALARM:MOV DPTR, #M_ALAX2;指針指到昆示信息区
MOV A,#2 ;湿示在第二行
LCALL LCD_PRINT
MOV A, #0C6H
LCALL TEMP_BJ1
MOV A,TEMP_TH ;加載TH数据
Mov LCD_X,#3 ;没置晁示位置
LCALL SHOW_DIG2H ;晁示数据
MOV A, #0CEH
LCALL TEMP_BJ1
MOV A,TEMP_TL ;加載TL数据
MoV LCD_X,#12 ;没置晁示位置
LCALL SHOW_DIG2L ;湿示数据
RET
M_ALAX1:DB "L00K ALERT CODE",0
M_ALAX2:DB "TH: TL: ",0
TEMP_BJ1:LCALL WCOM
MOV DPTR, #BJ2 ;指针指到显示信息区
MOV R1,#0
MOV R0,#2
BBJJ2: MOV A,R1
MOVC A, @A+DPTR
LCALL WDATA
INC R1
DJNZ R0, BBJJ2
RET
BJ2:DB 00H,"C"
;**********************************************LCD显示子程序
SHOW_DIG2H:MOV B,#100
DIV AB
ADD A, #30H
PUSH B
MOV B,LCD_X
LCALL LCDP2
POP B
MOV A, #0AH
XCH A,B
DIV AB
ADD A,#30H
INC LCD_X
PUSH B
MOV B,LCD_X
LCALL LCDP2
POP B
INC LCD_X
MOV A,B
MOV B,LCD_X
ADD A,#30H
LCALL LCDP2
RET
SHOW_DIG2L:
MOV B,#100
DIV AB
MOV A,#0AH
XCH A,B
DIV AB
ADD A,#30H
PUSH B
MOV B,LCD_X
LCALL LCDP2
POP B
INC LCD_X
MOV A,B
MOV B,LCD_X
ADD A,#30H
LCALL LCDP2
RET
;**********************************************显示区BCD码温度值刷新子程序
DISPBCD:MOV A,TEMPLC
ANL A,#0FH
MOV 70H,A ;小数位
MOV A,TEMPLC
SWAP A
ANL A, #0FH
MOV 71H,A ;个位
MOV A, TEMPHC
ANL A, #0FH
MOV 72H,A ;十位
MOV A, TEMPHC
SWAP A
ANL A, #0FH
MOV 73H,A ;百位
DISPBCD2 :RET
;**********************************************LCD显示数据处理子程序***
CONV: MOV A,73H ;加载百位数据
MOV LCD_X,#6 ;设置位置
CJNE A,#1,CONV1
JMP CONV2
CONV1: CJNE A, #0BH, CONV11
MOV A,#"-" ;“_”号显示
JMP CONV111
CONV11: MOV A,#" " ;“+”号不显示
CONV111 :MOV B,LCD_X
LCALL LCDP2
JMP CONV3
CONV2: LCALL SHOW_DIG2 ;显示数据
CONV3:INC LCD_X
MOV A, 72H
LCALL SHOW_DIG2
INC LCD_X
MOV A,71H;个位
LCALL SHOW_DIG2
INC LCD_X
MOV A,#'.'
MOV B,LCD_X
LCALL LCDP2
MOV A, 70H ;加载小数点位
INC LCD_X ;设置显示位置
LCALL SHOW_DIG2 ;显示数据
RET
;**********************************************第二行显示数字子程序
SHOW_DIG2:ADD A,#30H
MOV B,LCD_X
LCALL LCDP2
RET
;**********************************************第二行显示数字子程序**
LCDP2: PUSH ACC
MOV A,B ;设置显示地址
ADD A, #0C0H ;设置LCD的第二行地址
LCAlL WCOM ;写入命令
POP ACC ;由堆栈取出A
LCAlL WDATA ;写入数据
RET
;**********************************************对LCD初始化设置及测试
SET_LCD:CLR LCD_EN
LCALL INIT_LCD ;初始化LCD
lCAll STORE_DATA ;将自定义字符存入LCD的CGRAM
RET
;**********************************************LCD初始化
INIT_LCD: MOV A, #38H ;2行显示,字形5*7点阵
LCALL WCOM
LCALL DELAY1
MOV A,#38H
LCAll WCOM
LCALL DELAY1
MOV A, #38H
LCALL WCOM
LCALL DELAY1
MOV A, #0CH ;开显示,显示光标,光标不闪烁
LCAlL WCOM
LCALL DELAY1
MOV A,#01H ;清除LCD显示屏
LCALL WCOM
LCALL DELAY1
RET
;**********************************************清除LCD的第一行字符
CLR_LINE1 :MOV A,#80H ;设置LCD的第一行地址
LCALL WCOM
MOV R0,#24 ;设置计数值
C1: MOV A,#' ' ;载入空格符至LCD
LCALL WDATA ;输出字符至LCD
DJNZ R0,C1 ;计数结束
RET
;**********************************************LCD的第一行或第二行显示一行
LCD_PRINT:CJNE A,#1,LINE2;判断是否为第一行
LINE1 : MOV A, #80H ;设置LCD的第一行地址
LCALL WCOM ;写入命令
LCALL CLR_LINE ;清除该行字符数据
MOV A, #80H ;设置LCD的第一行地址
LCALL WCOM ;写入命令
JMP FILL
LINE2:MOV A, #0C0H ;设置LCD的第二行地址
LCALL WCOM ;写入命令
lCAll CLR_LINE ;清除该行字符数据
MOV A, #0C0H ;设置LCD的第二行地址
LCALL WCOM
FILL: CLR A ;填入字符
MOVC A, @A+DPTR ;由消息区取出字符
CJNE A,#0,LC1 ;判断是否为结束码
RET
LC1: LCAlL WDATA ;写入数据
INC DPTR ;指针加1
JMP FILL ;继续填入字符
RET
;********************************************** 清除1行LCD的字符
CLR_LINE:MOV R0,#24
CL1:MOV A,#' '
LCALL WDATA
DJNZ R0,CL1
RET
DE:
MOV R7,#250
DJNZ R7,$
RET
;**********************************************LCD间接控制方式命令写入
WCOM:MOV P0,A ;写入命令
CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲
CLR LCD_RW
SETB LCD_EN
LCALL DELAY1
CLR LCD_EN
RET
;**********************************************LCD间接控制方式数据写入
WDATA:MOV P0,A ;写入数据
SETB LCD_RS
CLR LCD_RW
SETB LCD_EN
LCALL DE
CLR LCD_EN
LCALL DE
RET
;**********************************************在LCD的第一行显示字符
LCDP1: PUSH ACC
MOV A,B ;设置显示地址
ADD A,#80H ;设置LCD的第一行地址
LCALL WCOM ;写入命令
POP ACC ;由堆栈取出A
LCALL WDATA ;写入数据
RET
;**********************************************声光报警子程序*********
BEEP_BL:MOV R6,#100
BL2:LCALL DEX1
CPL BEEP
CPL RELAY
DJNZ R6,BL2
MOV R5, #10
LCALL DELAY
RET
DEX1 : MOV R7, #180
DE2:NOP
DJNZ R7,DE2
RET
;**********************************************延时子程序
DELAY: MOV R6,#50
DL1:MOV R7,#100
DJNZ R7,$
DJNZ R6, DL1
DJNZ R5,DELAY
RET
DELAY1: MOV R6,#25;延时5ms
DL2:MOV R7,#100
DJNZ R7,$
DJNZ R6, DL2
RET
END
|