;================定义字符===============================
RS BIT P2.6 ;RS=P2.6
RW BIT P2.5 ;RW=P2.5
E BIT P2.7 ;E=P2.7
DATALINE EQU P3.7 ;定义引脚
FLAG1 EQU 20H.0 ;20H单元可位寻址区
KEY1 BIT P3.0
KEY2 BIT P3.1
KEY3 BIT P3.2
KEY4 BIT P3.3
Y EQU 60H ;定义运行与否Y存储单元
M EQU 61H ;定义模式M存储单元
S EQU 62H ;定义风速S存储单元
L EQU 63H ;定义类型L存储单元
DDJ BIT P1.0 ;DDJ=P1.0
;====================主程序========================
ORG 0000H
AJMP MAIN
ORG 000BH ;T0中断入口
LJMP TIME0
ORG 001BH
LJMP TIME1 ;T1中断入口
ORG 0030H
MAIN: CLR A
MOV B,#00H
MOV 25H,#00H
MOV 26H,#00H
MOV 27H,#00H
MOV 28H,#00H
MOV 29H,#00H
MOV Y,#0 ;Y=0,不运行
MOV M,#1 ;模式为1,手动
MOV S,#1 ;风速为0
MOV L,#1 ;类型为1,正常
CLR DDJ ;将DDJ置0,风扇不转动
LCALL LCDRESET ;液晶显示器初始化
LCALL B20_INIT ;DS18B20初始化
LCALL FBLCHANGE ;改变温度分辨率为9位
LCALL TMAIN ;读取温度并显示
LCALL KEYA
JMP $
;======================扫描按键程序=================================
KEYA: MOV A,M
CJNE A,#2,KEYB
LCALL TMAIN
LCALL WENKONG
KEYB: MOV A,#0FFH ;扫描按键并处理
MOV P3,A ;P3口置1,使其为输入模式
JNB KEY1,D1 ;KEY1=0,说明K1键按下,转到D1
JNB KEY2,D2 ;KEY2=0,说明K1键按下,转到D2
JNB KEY3,D3 ;KEY4=0,说明K1键按下,转到D4
LJMP KEYA ;KEY3=0,说明K1键按下,转到D3
JNB KEY4,D4
D1: LCALL DELAY12ms ;延时12ms,消抖
JNB KEY1,K1 ;再次判断按键状态,若仍为0,转到K1
LJMP KEYA ;若不为0,返回继续查询
D2: LCALL DELAY12ms ;延时12ms,消抖
JNB KEY2,K2 ;再次判断按键状态,若仍为0,转到K2
LJMP KEYA ;若不为0,返回继续查询
D3: LCALL DELAY12ms ;延时12ms,消抖
JNB KEY3,K3 ;再次判断按键状态,若仍为0,转到K3
LJMP KEYA ;若不为0,返回继续查询
D4: LCALL DELAY12ms ;延时12ms,消抖
JNB KEY4,K4 ;再次判断按键状态,若仍为0,转到K4
LJMP KEYA ;若不为0,返回继续查询
K1: LCALL EK1 ;调按键K1处理子程序EK1
LJMP KEYA
K2: LCALL EK2 ;调按键K2处理子程序EK2
LJMP KEYA
K3: LCALL EK3 ;调按键K3处理子程序EK3
LJMP KEYA
K4: LCALL EK4 ;调按键K4处理子程序EK4
LJMP KEYA
;===================== K1处理子程序EK1======================
EK1: JNB KEY1,EK1 ;再次判断KEY1状态,KEY1=0,按键K1未释放,等待
;之后判断风扇工作状态,如果是运行状态,则按下K1后停止转动;若是停止状态,则按下K2后开始转动。
MOV A,Y ;P3.1=1,按键K1已释放,则执行按键K1功能
CJNE A,#0,STOP ;Y不为0,说明风扇在转动,转到STOP,使其停止转动
MOV Y,#01H ;Y=0,说明风扇不转动,之后判断风扇停止前的状态,逐一恢复
MOV A,Y
MOV P0,#82H
LCALL LOAD
ORL A,#30H
LCALL SENDDATA ;改变显示器上的Y=1
MOV A,M
CJNE A,#1,EK11 ;判断M的状态,M不为1,则为温控模式,转到EK11
MOV A,S ;M=1,则为手动模式,继续执行,判断S、L的状态
CJNE A,#1,EK12
LCALL DANG1
LJMP EK14
EK12:CJNE A,#2,EK13
LCALL DANG2
LJMP EK14
EK13:LCALL DANG3 ;判断了S的状态并恢复
EK14:MOV A,L
CJNE A,#1,EK15
LCALL ZHENGCHANG
LJMP EK17
EK15:CJNE A,#2,EK16
LCALL ZIRAN
LJMP EK17
EK16:LCALL SHUIMIAN
LJMP EK17 ;判断了L的状态并恢复
EK11:LCALL WENKONG ;温控模式
LJMP EK17
STOP:MOV Y,#0 ;停止运行程序
MOV A,Y
MOV P0,#82H
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器上的Y=0
CLR DDJ ;风扇停止转动
EK17:RET
;=============================K2处理子程序EK2===========================
EK2: JNB KEY2,EK2 ;再次判断KEY2状态,KEY2=0,按键K2未释放,等待
;判断风扇模式,若自动,则转为手动;若手动,则转为自动
MOV A,Y ;P3.0=1,按键K2已释放,则执行按键K2功能
CJNE A,#1,EK21 ;判断风扇运行情况,若风扇不运行,此键无效,跳转到EK21
MOV A,M ;Y=1,风扇运行,判断M的状态
CJNE A,#1,EK22 ;M=2,风扇为自动模式,则转到EK22,变为手动
MOV M,#2 ;M=1,风扇为手动模式,改为自动温控
MOV A,M
MOV P0,#86H
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器上M=2
LCALL WENKONG
LJMP EK21
EK22: MOV M,#1
MOV A,M
MOV P0,#86H
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器上M=1
MOV A,S ;之后判断S、L的状态并恢复
CJNE A,#1,EK23
LCALL DANG1
LJMP EK25
EK23:CJNE A,#2,EK24
LCALL DANG2
LJMP EK25
EK24:LJMP DANG3 ;判断了S的状态并恢复
EK25:MOV A,L
CJNE A,#1,EK26
LCALL ZHENGCHANG
LJMP EK21
EK26:CJNE A,#2,EK27
LCALL ZIRAN
LJMP EK21
EK27:LCALL SHUIMIAN ;判断了L的状态并恢复
EK21: RET
;========================= K3处理子程序EK3=====================
EK3: JNB KEY3,EK3 ;再次判断KEY3状态,KEY3=0,按键K3未释放,等待
;判断风扇是否运行,不允许此键无效。判断风扇模式,手动模式下风扇变速,自动模式下此键无效。判断当前风速,弱→中、中→强、强→弱
MOV A,Y ;P3.2=1,按键K3已释放,则执行按键K3功能
CJNE A,#1,EK31 ;Y=0,风扇不运行,此键无效跳转到EK31
MOV A,M
CJNE A,#1,EK31 ;M=2,自动模式,此键无效,跳转到EK31
MOV A,S
CJNE A,#1,EK32 ;S不为1,跳转到EK32
MOV S,#2 ;S=1,风速为1档,改为2档
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器S=2
LCALL DANG2 ;调风速
LJMP EK31
EK32: CJNE A,#2,EK33 ;S不为2,跳转到EK33
MOV S,#3 ;S=2,风速为2档,调为3档
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器上S=3
LCALL DANG3
LJMP EK31
EK33: MOV S,#1 ;S=3,风速为3档,调到1档
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;改变显示器上S=1
LCALL DANG1
EK31: RET
;============================== K4处理子程序EK4=============================
EK4: JNB KEY4,EK4 ;再次判断KEY4状态,KEY4=0,按键K4未释放,等待
;判断风扇模式,手动模式下风扇变类型, 判断当前模式,正常→睡眠、睡眠→自然、自然→正常
MOV A,Y ;P3.3=1,按键K4已释放,则执行按键K4功能
CJNE A,#1,EK41 ;Y=0,风扇不运行,此键无效跳转到EK41
MOV A,M
CJNE A,#1,EK41 ;M=2,自动模式,此键无效,跳转到EK41
MOV A,L
CJNE A,#1,EK42
MOV L,#2
MOV A,L
MOV P0,#8EH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL SHUIMIAN
LJMP EK41
EK42: CJNE A,#2,EK43
MOV L,#3
MOV A,L
MOV P0,#8EH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL ZIRAN
LJMP EK41
EK43: MOV L,#1
MOV A,L
MOV P0,#8EH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL ZHENGCHANG
EK41: RET
;==================== 12ms延时子程序====================
DELAY12ms: MOV R7,#26 ;12ms延时子程序
DEL3: MOV R6,#200
DJNZ R6,$
DJNZ R7,DEL3
RET
;=====================温度控制子程序====================
WENKONG:MOV A,29H
SUBB A,#20
JNC WEN1
MOV S,#1
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL DANG1
LJMP WEN2
WEN1:MOV A,29H
SUBB A,#20
JNC WEN3
MOV S,#2
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL DANG2
LJMP WEN2
WEN3:MOV S,#3
MOV A,S
MOV P0,#8AH
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA
LCALL DANG3
WEN2:RET
;===================调速程序DANG1、DANG2、DANG3=========
DANG1:MOV SP,#70H
SETB DDJ
MOV TMOD,#11H
MOV TH0,#0D8H
MOV TL0,#0F0H
SETB ET0
SETB EA
SETB TR0
RET
DANG2:MOV SP,#70H
SETB DDJ
MOV TMOD,#11H
MOV TH0,#0B1H
MOV TL0,#0E0H
SETB ET0
SETB EA
SETB TR0
RET
DANG3:SETB DDJ
CLR TR0
RET
;===================T0中断服务子程序===================
TIME0:CLR EA
PUSH PSW
PUSH Acc
SETB EA
MOV A,S
CJNE A,#1,TIME01
JB DDJ,TIME02
CPL DDJ
MOV TH0,#0D8H
MOV TL0,#0F0H
LJMP TIME03
TIME02:CPL DDJ
MOV TH0,#0B1H
MOV TL0,#0E0H
LJMP TIME03
TIME01:JB DDJ,TIME04
CPL DDJ
MOV TH0,#0B1H
MOV TL0,#0E0H
LJMP TIME03
TIME04: CPL DDJ
MOV TH0,#0D8H
MOV TL0,#0F0H
TIME03:CLR EA
POP Acc
POP PSW
SETB EA
RETI
;=======================模式改变程序 正常、睡眠、自然================
ZHENGCHANG:CLR TR1
CLR ET1
RET
SHUIMIAN: MOV TMOD,#11H
MOV TH1,#3CH
MOV TL1,#0B0H
MOV R7,#80
SETB EA
SETB TR1
SETB ET1
SETB PT1
RET
ZIRAN: MOV TMOD,#11H
MOV TH1,#3CH
MOV TL1,#0B0H
MOV R7,#160
SETB EA
SETB TR1
SETB ET1
SETB PT1
RET
;=======================T1中断服务子程序=====================
TIME1: CLR EA
PUSH PSW
PUSH Acc
SETB EA
MOV TH1,#3CH
MOV TL1,#0B0H
DJNZ R7,TIME11
MOV A,L
CJNE A,#2,TIME14
MOV R7,#80
LJMP TIME15
TIME14: MOV R7,#160
TIME15: MOV A,S
CJNE A,#3,TIME12
CPL DDJ
LJMP TIME11
TIME12: JB TR0,TIME13
SETB TR0
LJMP TIME11
TIME13: CLR TR0
CLR DDJ
TIME11: CLR EA
POP Acc
POP PSW
SETB EA
RETI
;=========================改变温度分辨率=====================
FBLCHANGE:
LCALL B20_INIT ;复位
MOV A,#0CCH ;跳过ROM
LCALL WRITE
MOV A,#1FH ;改变分辨率为9
LCALL WRITE
RET
;========================= 液晶显示器初始化==================
LCDRESET:
MOV P0,#01H ;清屏(命令1)
LCALL LOAD ;向LCD1602 写入命令字 01H
MOV P0,#38H ;显示设定,显示两行(命令 6)
LCALL LOAD ;向LCD1602写入命令字38H
MOV P0,#0FH ;打开显示和光标,光标闪烁(命令4)
LCALL LOAD ;向 LCD1602 写入命令字 0FH
MOV P0,#14H ;光标右移(命令5)
LCALL LOAD ;向LCD1602写人命令字 14H
MOV P0,#80H ;光标回到第1行00H位置(命令8)
LCALL LOAD ;向LCD1602写人命令字80H(80H+00H)
MOV DPTR,#TABLE1 ;DPTR指向TABLE1的表
LCALL DISPLAY ;调用液晶屏显示字程序
MOV P0,#0C0H ;光标回到第2行40H位置(命令8)
LCALL LOAD ;向LCD1602写入命令字COH(80H+40H)
MOV DPTR,#TABLE2 ;DPTR指向 TABLE 2 的表
CALL DISPLAY ;调用液晶屏显示字程序
RET ;返回主程序
;======================命令装载子程序,对液晶屏下命令LOAD=========================
LOAD:
CLR RS ;RS=0,D0~D7 上的信号作为命令使用
CLR RW ;RW=0,写数据
CLR E ;E=0,E引脚电平由1变0,数据被读入
LCALL DELAY ;延时
SETB E ;E=1,屏蔽DO~D7的数据
RET ;返回
;============================初始化显示子程序=============================
DISPLAY:
MOV R0,#00H ;取数据表时,用RO为指针
REFETCH:
MOV A,R0
MOVC A,@A+DPTR ;ACC装载数据表中的数据
LCALL SENDDATA ;调用显示数据发送子程序
INC R0 ;R0 增加 1
CJNE R0,#10H,REFETCH ;如R0=10H,取表结束,否则跳回REFETCH
RET ;返回
;============================显示数据发送子程序===========================
SENDDATA:
MOV P0,A ;显示数据从 P1口送出
SETB RS ;RS=1,D0~D7 上的信号作为显示数据使用
CLR RW ;RW=0,写数据
CLR E ;E=0,引脚电平由1变0,D0~D7数据被读入
LCALL DELAY ;延时
SETB E ;E=1,屏蔽 D0~D7 的数据
RET ;返回
;=========================延时子程序=================================
DELAY:
MOV R5,#100
DEL1: MOV R6,#20
DEL2: DJNZ R6,DEL2
DJNZ R5,DEL1
RET
TABLE1: ;数据表,第1行字符 .
DB'Y:0 M:1 S:1 L:1 '
TABLE2: ;数据表,第2行字符
DB' T: . '
DB 0DFH
DB'C '
;=====================温度读取+显示程序======================
TMAIN: MOV SP,#30H
LCALL B20_INIT ;复位与检测DS18B20
SETB DATALINE
LCALL B20_INIT
JB FLAG1,START
RET
START:
MOV A,#0CCH ;跳过ROM 匹配
LCALL WRITE
MOV A,#44H ;发出温度转换命令
LCALL WRITE
;LCALL DISPLAYT
LCALL B20_INIT
MOV A,#0CCH ;跳过ROM 匹配
LCALL WRITE
MOV A,#0BEH ;发出读温度命令
LCALL WRITE
LCALL READ ;读温度数据
LCALL CTEMP ;计算温度值
LCALL DISPLAYT ;显示
RET
;=========================DS18B20初始化子程序======================
;DS18B20 复位与检测子程序
;FLAG1-1OKFLAG1=0ERROR
B20_INIT:
SETB DATALINE
NOP
ClR DATALINE
MOV R0,#0FBH ;主机发出延时600us 的复位低脉冲
B20_INIT1:
DJNZ R0,B20_INIT1
SETB DATALINE ;拉高数据线
MOV R0,#25H
B20_INIT2:
JNB DATALINE,B20_INIT3 ;等待DS18B20 回应
DJNZ R0,B20_INIT2
;延时
B20_INIT3:
SETB FLAG1
MOV R0,#06BH ;置标志位,表示DS18B20 存在
B20_INIT4:DJNZ R0,B20_INIT4 ;清标志位,表示DS18B20 不存在
SETB DATALINE
RET
;====================读字节子程序READ============================
READ: MOV R4,#2 ; 读取两个八位数据,外层循环次数
MOV R1,#29H ; 立即数寻址给定存储位置
REE0: MOV R2,#8 ; 给定数据位数,是内层循环次数
REE1: CLR C ; 进位标志位初始置零
SETB C
NOP
NOP
CLR DATALINE
NOP
NOP
NOP
SETB DATALINE ; 输入脉冲并持续2-3个机器周期
MOV R3,#7
DJNZ R3,$ ; 延时,等待传感器响应
MOV C,DATALINE ; 按位读出
MOV R3,#23
DJNZ R3,$ ; 延时
RRC A ; 把C存入A内
DJNZ R2,REE1 ; 循环8次
MOV @R1,A ; 在29H存储A,数据的低八位
DEC R1 ; 更换地址为28H,存储数据高八位
DJNZ R4,REE0 ; 循环2次
RET
;===================写字节子程序WRITE==========================
WRITE:
MOV R2,#8 ; 写入八位二进制码,即循环次数
CLR C ; 进位标志位初始置零
WR1: CLR DATALINE ; 拉低总线为写入做准备
MOV R3,#6
DJNZ R3,$ ; 延时
RRC A ; A的最低为给CY,使A从低到高写入从机
MOV DATALINE,C ; 将A又循环写入C,写入总线以输入到传感器
MOV R3,#23
DJNZ R3,$ ; 延时
SETB DATALINE ; 释放,表示此位写入完毕
NOP
DJNZ R2,WR1 ; 循环八次,一次写入八位
SETB DATALINE ; 释放总线
RET
;=========================计算温度值CTEMP========================
CTEMP:
MOV A,29H
MOV 26H,29H
MOV 25H,28H
MOV 24H,28H ; 在24H存储原始数据防止丢失
MOV C,25H.7 ; 存储符号位进C
JNC SN1 ; 判断温度的正负,正数则跳过转补码程序
MOV A,25H
CPL A ; 取补码,由于无效位置1,25H不必担心数据溢出
MOV 25H,A
MOV A,26H
CPL A
INC A ; 由于是末位,需要加一
MOV 26H,A
MOV 29H,26H
MOV 28H,25H ; 在26H,25H中操作后放回29H,28H
SN1:
MOV C,28H.0 ; 正负温度到此均得到整数部分绝对值
RRC A
MOV C,28H.1
RRC A
MOV C,28H.2
RRC A
MOV C,28H.3 ; 分别循环,存入A内,连续4次滤掉小数部分
RRC A ; 可分析A内八位恰为整数部分(最高位为0)
JC SL0
MOV 27H,#00H
AJMP SL5
SL0:
MOV 27H,#05H ;为小数部分显示0和5做准备
SL5:
MOV 29H,A ;29H内存放的是温度的整数部分
LCALL DISPLAYT ;27H内存放的是温度的小数部分
RET
;=====================温度显示DISPLAYT=========================
DISPLAYT:
MOV P0,#0C9H
LCALL LOAD
MOV R1,#27H
CJNE @R1,#0,AAA
MOV A,#'0'
AJMP BBB
AAA:MOV A,#'5'
BBB:LCALL SENDDATA ;显示小数部分
MOV A,29H
MOV B,#10
DIV AB
MOV P0,#0C6H
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA ;显示十位数
MOV P0,#0C7H
LCALL LOAD
MOV A,B
ADD A,#'0'
LCALL SENDDATA ;显示个位数
MOV P0,#0CH
LCALL LOAD ;关掉光标
RET
END
|