找一下这两段代码有何不同
1:
ORG 0000H
AJMP MAIN
ORG 000BH ; 定时器0中断入口
AJMP TIMER0_ISR
ORG 0040H
MAIN:
MOV SP,#60H
; 初始化定时器
MOV TMOD,#01H ; 定时器0模式1
MOV TH0,#3CH ; 50ms定时初值
MOV TL0,#0B0H
SETB ET0 ; 允许定时器0中断
SETB EA ; 开总中断
SETB TR0 ; 启动定时器0
; 初始化模式标志位(0=自动模式,1=手动模式)
CLR 20H.0
; 初始化报警延时标志
MOV 30H,#0 ; 报警延时计数器
MOV 31H,#0 ; 温度采样间隔计数器
; LCD初始化
LCALL LCD_INIT
MOV R0,#66H
MOV R1,#11
MOV R2,#0
MOV R4,#00H
MOV P2,#1FH
MOV DPTR,#INIT_STRING
INIT_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,INIT_DISP
LCALL MIDDLE_DELAY
MOV A,#0
MOV B,#10
LCALL SET_CURSOR
AJMP KEY
INIT_STRING: DB "SetValue1:"
; 键盘输入温度阈值
KEY:
INC R0
MOV P1, #0FH ; 准备扫描键盘
MOV A, P1 ; 读取按键状态
ANL A, #0FH ; 屏蔽高4位
CJNE A, #0FH, k1 ; 检测是否有键按下
MOV P0,#00H
AJMP KEY
k1: ; 去抖后重新检测
LCALL SHORT_DELAY
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,k2
AJMP KEY
k2:
MOV R3,A ; 暂存键值
MOV P1,#0F0H
MOV A,P1
ANL A,#0F0H
ORL A,R3
MOV B,A ; 用于后面的CHECK_LOOP
; 查键值对应键号
CJNE A,#77H,S2
MOV A,#'1'
LJMP DISP_SET
S2:
CJNE A,#7BH,S3
MOV A,#'2'
LJMP DISP_SET
S3:
CJNE A,#7DH,S4
MOV A,#'3'
LJMP DISP_SET
S4:
CJNE A,#7EH,S5
MOV A,#'4'
LJMP DISP_SET
S5:
CJNE A,#0B7H,S6
MOV A,#'5'
LJMP DISP_SET
S6:
CJNE A,#0BBH,S7
MOV A,#'6'
LJMP DISP_SET
S7:
CJNE A,#0BDH,S8
MOV A,#'7'
LJMP DISP_SET
S8:
CJNE A,#0BEH,S9
MOV A,#'8'
LJMP DISP_SET
S9:
CJNE A,#0D7H,S10
MOV A,#'9'
LJMP DISP_SET
S10:
CJNE A,#0DBH,S11
MOV A,#'0'
LJMP DISP_SET
S11:
CJNE A,#0DDH,S16 ; S11键检测(键值0xED)
; 模式切换功能
LCALL TOGGLE_MODE
AJMP KEY
S16:
CJNE A,#0EEH,JMP_TO_KEY
LCALL LCD_INIT
AJMP TEMP_DET
DISP_SET:
PUSH ACC
LCALL WRITE_BYTE_NUM
; 检查按键是否松开
CHECK_LOOP:
MOV P1,#0F0H
MOV A,P1
ANL A,#0F0H
ORL A,R3
CJNE A,B,JMP_TO_KEY
LCALL MIDDLE_DELAY
AJMP CHECK_LOOP
JMP_TO_KEY:
AJMP KEY
; 模式切换函数
TOGGLE_MODE:
CPL 20H.0 ; 切换模式标志位
LCALL LCD_INIT ; 刷新LCD显示
; 显示模式信息
MOV DPTR,#MODE_STRING
MOV R1,#5
MOV R2,#0
MODE_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,MODE_DISP
LCALL NEXT_LINE
; 显示当前模式
JB 20H.0,SHOW_MANUAL
MOV DPTR,#AUTO_STRING
SJMP SHOW_MODE
SHOW_MANUAL:
MOV DPTR,#MANUAL_STRING
SHOW_MODE:
MOV R1,#6
MOV R2,#0
CURRENT_MODE_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,CURRENT_MODE_DISP
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
RET
MODE_STRING: DB "Mode:"
AUTO_STRING: DB "Auto "
MANUAL_STRING: DB "Manual"
; 温度检测程序
TEMP_DET:
; 显示阈值和当前温度值
LCALL TEMP_INIT
LCALL CONVERT_T
MOV R1,#11
MOV R2,#0
MOV DPTR,#THRESHOLD_STRING
THRESHOLD_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,THRESHOLD_DISP
LCALL CURSOR_LEFT
MOV R0,#31H
POP ACC
MOVX @R0,A
MOV R0,#30H
POP ACC
MOVX @R0,A
MOV R0,#30H
MOV R4,#2
THRES_NUM_DISP:
MOVX A,@R0
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
LCALL MIDDLE_DELAY
INC R0
DJNZ R4,THRES_NUM_DISP
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
LCALL NEXT_LINE
MOV DPTR,#CURRENT_TEMP_STRING
MOV R1,#9
MOV R2,#0
CURRENT_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,CURRENT_DISP
LCALL CURSOR_LEFT
LCALL TEMP_INIT
LCALL READ_TEMP
CURRENT_NUM_DISP:
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
MOV A,B
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
MOV A,#1
MOV B,#8
LCALL SET_CURSOR
READ_TEMP_LOOP:
; 显示当前温度
LCALL DISPLAY_TEMP
; 检查温度
LCALL CMP_TEMP
JC CALL_ALARM ; 超过阈值则报警
; 温度正常,确保风扇关闭
CLR P1.0
SJMP READ_TEMP_LOOP
CALL_ALARM:
LCALL ALARM
SJMP READ_TEMP_LOOP
THRESHOLD_STRING: DB "Threshold:"
CURRENT_TEMP_STRING: DB "Current:"
; 延时函数
LONG_DELAY: ; 约33秒延时
MOV R5,#0FFH
LOOP_1:
MOV R6,#0FFH
LOOP_2:
MOV R7,#0FFH
LOOP_3:
DJNZ R7,LOOP_3
DJNZ R6,LOOP_2
DJNZ R5,LOOP_1
RET
MIDDLE_DELAY: ; 约48ms延时
MOV R6,#18H
LOOP_4:
MOV R7,#0FFH
LOOP_5:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_5
DJNZ R6,LOOP_4
RET
SHORT_DELAY: ; 约16ms延时
MOV R6,#08H
LOOP_6:
MOV R7,#0FFH
LOOP_7:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_7
DJNZ R6,LOOP_6
RET
NORMAL_DELAY: ; 约1秒延时
MOV R5,#03H
LOOP_8:
MOV R6,#0FFH
LOOP_9:
MOV R7,#0FFH
LOOP_10:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_10
DJNZ R6,LOOP_9
DJNZ R5,LOOP_8
RET
TWO_SEC_DELAY: ; 2秒延时
MOV R5,#0DH
TWO_SEC_LOOP:
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
DJNZ R5,TWO_SEC_LOOP
RET
TINY_DELAY: ; 约60us,DS18B20专用延时
MOV R3,#10
LOOP_11:
NOP
NOP
NOP
NOP
DJNZ R3,LOOP_11
RET
; LCD相关函数
LCD_INIT:
; 清屏
MOV P2, #1FH
MOV P0, #01H
SETB P2.7
LCALL SHORT_DELAY
; 模式设置为右移,显示,光标闪烁,数据总线8位,显示两行,5×8点阵每字符
MOV P2,#1FH
MOV P0,#06H
SETB P2.7
LCALL SHORT_DELAY
MOV P2,#1FH
MOV P0,#0EH
SETB P2.7
LCALL SHORT_DELAY
MOV P2,#1FH
MOV P0,#38H
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
RET
WRITE_BYTE_STR:
CLR P2.7
MOV P0,A
MOV P2,#5FH
SETB P2.7
LCALL MIDDLE_DELAY
RET
WRITE_BYTE_NUM:
CLR P2.7
MOV P0,A
MOV P2,#5FH
SETB P2.7
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
CLR P2.7
RET
NEXT_LINE:
MOV P2,#1FH
MOV P0,#0C0H
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
RET
SET_CURSOR: ; A=行号(0第一行,1第二行),B=列号(0-15)
PUSH ACC
CJNE A,#0,SECOND_LINE
MOV A,#80H
JMP CALC_COL
SECOND_LINE:
MOV A,#0C0H
CALC_COL:
ADD A,B
MOV P2,#1FH
MOV P0,A
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
POP ACC
RET
CURSOR_LEFT:
MOV P2,#1FH
MOV P0,#10H
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
RET
; 温度传感器相关函数
TEMP_INIT:
CLR P3.7 ; 拉低DS18B20总线(复位)
MOV R7,#240 ; 延时480μs
DELAY_LOOP1:
DJNZ R7,DELAY_LOOP1
SETB P3.7 ; 释放总线
MOV R7,#5
LCALL TINY_DELAY
JB P3.7,TEMP_INIT ; 检测传感器存在脉冲
MOV R7,#120
WAIT:
DJNZ R7,WAIT
MOV A,#0CCH ; SKIP ROM命令
LCALL WRITE_COMMAND
RET
WRITE_COMMAND:
MOV R7,#8
COMMAND:
RRC A
CLR P3.7
NOP
NOP
JC WRITE_ONE
MOV R6,#28
DELAY_LOOP3:
DJNZ R6,DELAY_LOOP3
SJMP BIT_END
WRITE_ONE:
SETB P3.7
MOV R6,#27
DELAY_LOOP4:
DJNZ R6,DELAY_LOOP4
BIT_END:
SETB P3.7
NOP
DJNZ R7,COMMAND
RET
CONVERT_T:
MOV A,#44H ; 温度转换命令
LCALL WRITE_COMMAND
RET
READ_TEMP: ; 返回ASCII码,A=十位,B=个位,片外7AH存二进制值
MOV A,#0BEH ; 读取暂存器命令
LCALL WRITE_COMMAND
NOP
MOV R6,#9
MOV R0,#70H
READ_DATA:
ONE_BYTE:
MOV R7,#8
ONE_BIT:
CLR P3.7
NOP
NOP
SETB P3.7
NOP
MOV C,P3.7
RRC A
LCALL TINY_DELAY
DJNZ R7,ONE_BIT
MOVX @R0,A ; 读取的温度值存入70H-7AH
INC R0
DJNZ R6,READ_DATA
MOV R0,#70H
MOVX A,@R0
ANL A,#0F0H
SWAP A
MOV R1,A
MOV R0,#71H
MOVX A,@R0
ANL A,#07H
SWAP A
ORL A,R1
MOV R0,#7AH
MOVX @R0,A
MOV B,#10
DIV AB
ORL A,#30H
ORL B,#30H
RET
ASC2BIN: ; 将ASCII码转换为二进制数
MOVX A, @R0 ; 读取ASCII码
ANL A, #0FH ; 保留低4位(数字部分)
MOV B, #10 ; 十位转换
MUL AB ; A*10→BA
MOV B,A
INC R0
MOVX A,@R0
ANL A,#0FH
ADD A,B ; 合并十位和个位
RET
CMP_TEMP: ; 比较温度,C=1表示温度超过阈值
MOV R0,#30H
LCALL ASC2BIN ; 获取阈值
MOV B,A
MOV R0,#7AH
MOVX A,@R0 ; 获取当前温度
; 比较温度
CLR C
SUBB A,B
JC TEMP_OK
SETB C ; 温度超过阈值
RET
TEMP_OK:
CLR C ; 温度正常
RET
ALARM:
MOV R5,#12 ; 设置报警循环次数
CLR P2.7 ; 启动蜂鸣器
ALARM_LOOP:
; 检查当前模式
JB 20H.0,MANUAL_ALARM ; 手动模式只报警
; 自动模式启动风扇
SETB P1.0 ; 启动风扇
MANUAL_ALARM:
; 声光报警
CLR P2.0 ; LED1亮
CLR P2.5 ; LED2亮
LCALL MIDDLE_DELAY
SETB P2.0 ; LED1灭
SETB P2.5 ; LED2灭
LCALL MIDDLE_DELAY
; 检查按键
LCALL CHECK_KEY
JC KEY_PRESSED ; 有按键则处理
DJNZ R5,ALARM_LOOP ; 循环闪烁
; 报警循环结束,重新检查温度
LCALL CMP_TEMP
JNC ALARM ; 仍然超限则重新报警
CLR P1.0 ; 温度正常,关闭风扇
CLR P2.7 ; 关闭蜂鸣器
RET
KEY_PRESSED:
; 关闭声光报警
SETB P2.0 ; 关闭LED
SETB P2.5 ; 关闭LED
SETB P2.7 ; 关闭蜂鸣器
; 延时2秒后重新检查
LCALL TWO_SEC_DELAY
; 重新检查温度
LCALL CMP_TEMP
JNC ALARM ; 仍然超限则重新报警
CLR P1.0 ; 温度正常,关闭风扇
RET
DISPLAY_TEMP:
LCALL TEMP_INIT
LCALL READ_TEMP
MOV A,#1
MOV B,#8
LCALL SET_CURSOR
LCALL WRITE_BYTE_NUM
MOV A,B
LCALL WRITE_BYTE_NUM
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
RET
; 定时器0中断服务程序
TIMER0_ISR:
PUSH ACC
PUSH PSW
; 重装定时初值
MOV TH0,#3CH
MOV TL0,#0B0H
; 温度采样间隔控制(约1秒)
INC 31H
MOV A,31H
CJNE A,#20,TIMER_EXIT ; 20*50ms=1秒
; 1秒到,执行温度检测
MOV 31H,#0
LCALL TEMP_DET
TIMER_EXIT:
POP PSW
POP ACC
RETI
CHECK_KEY:
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,AGAIN
CLR C ; 无按键按下
RET
AGAIN:
; 去抖检测
LCALL SHORT_DELAY
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,KEY_DETECTED
CLR C
RET
KEY_DETECTED:
SETB C ; 有按键按下
RET
END
2:
ORG 0000H
AJMP MAIN
ORG 000BH ; 定时器0中断入口
AJMP TIMER0_ISR
ORG 0040H
MAIN:
MOV SP,#60H
; 初始化定时器
MOV TMOD,#01H ; 定时器0模式1
MOV TH0,#3CH ; 50ms定时初值
MOV TL0,#0B0H
SETB ET0 ; 允许定时器0中断
SETB EA ; 开总中断
SETB TR0 ; 启动定时器0
; 初始化模式标志位(0=自动模式,1=手动模式)
CLR 20H.0
; 初始化报警延时标志
MOV 30H,#0 ; 报警延时计数器
MOV 31H,#0 ; 温度采样间隔计数器
; LCD初始化
LCALL LCD_INIT
MOV R0,#66H
MOV R1,#11
MOV R2,#0
MOV R4,#00H
MOV P2,#1FH
MOV DPTR,#INIT_STRING
INIT_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,INIT_DISP
LCALL MIDDLE_DELAY
MOV A,#0
MOV B,#10
LCALL SET_CURSOR
AJMP KEY
INIT_STRING: DB "SetValue1:"
; 键盘输入温度阈值
KEY:
INC R0
MOV P1, #0FH ; 准备扫描键盘
MOV A, P1 ; 读取按键状态
ANL A, #0FH ; 屏蔽高4位
CJNE A, #0FH, k1 ; 检测是否有键按下
MOV P0,#00H
AJMP KEY
k1: ; 去抖后重新检测
LCALL SHORT_DELAY
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,k2
AJMP KEY
k2:
MOV R3,A ; 暂存键值
MOV P1,#0F0H
MOV A,P1
ANL A,#0F0H
ORL A,R3
MOV B,A ; 用于后面的CHECK_LOOP
; 查键值对应键号
CJNE A,#77H,S2
MOV A,#'1'
LJMP DISP_SET
S2:
CJNE A,#7BH,S3
MOV A,#'2'
LJMP DISP_SET
S3:
CJNE A,#7DH,S4
MOV A,#'3'
LJMP DISP_SET
S4:
CJNE A,#7EH,S5
MOV A,#'4'
LJMP DISP_SET
S5:
CJNE A,#0B7H,S6
MOV A,#'5'
LJMP DISP_SET
S6:
CJNE A,#0BBH,S7
MOV A,#'6'
LJMP DISP_SET
S7:
CJNE A,#0BDH,S8
MOV A,#'7'
LJMP DISP_SET
S8:
CJNE A,#0BEH,S9
MOV A,#'8'
LJMP DISP_SET
S9:
CJNE A,#0D7H,S10
MOV A,#'9'
LJMP DISP_SET
S10:
CJNE A,#0DBH,S11
MOV A,#'0'
LJMP DISP_SET
S11:
CJNE A,#0DDH,S16 ; S11键检测(键值0xED)
; 模式切换功能
LCALL TOGGLE_MODE
AJMP KEY
S16:
CJNE A,#0EEH,JMP_TO_KEY
LCALL LCD_INIT
AJMP TEMP_DET
DISP_SET:
PUSH ACC
LCALL WRITE_BYTE_NUM
; 检查按键是否松开
CHECK_LOOP:
MOV P1,#0F0H
MOV A,P1
ANL A,#0F0H
ORL A,R3
CJNE A,B,JMP_TO_KEY
LCALL MIDDLE_DELAY
AJMP CHECK_LOOP
JMP_TO_KEY:
AJMP KEY
; 模式切换函数
TOGGLE_MODE:
CPL 20H.0 ; 切换模式标志位
LCALL LCD_INIT ; 刷新LCD显示
; 显示模式信息
MOV DPTR,#MODE_STRING
MOV R1,#5
MOV R2,#0
MODE_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,MODE_DISP
LCALL NEXT_LINE
; 显示当前模式
JB 20H.0,SHOW_MANUAL
MOV DPTR,#AUTO_STRING
SJMP SHOW_MODE
SHOW_MANUAL:
MOV DPTR,#MANUAL_STRING
SHOW_MODE:
MOV R1,#6
MOV R2,#0
CURRENT_MODE_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,CURRENT_MODE_DISP
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
RET
MODE_STRING: DB "Mode:"
AUTO_STRING: DB "Auto "
MANUAL_STRING: DB "Manual"
; 温度检测程序
TEMP_DET:
; 显示阈值和当前温度值
LCALL TEMP_INIT
LCALL CONVERT_T
MOV R1,#11
MOV R2,#0
MOV DPTR,#THRESHOLD_STRING
THRESHOLD_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,THRESHOLD_DISP
LCALL CURSOR_LEFT
MOV R0,#31H
POP ACC
MOVX @R0,A
MOV R0,#30H
POP ACC
MOVX @R0,A
MOV R0,#30H
MOV R4,#2
THRES_NUM_DISP:
MOVX A,@R0
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
LCALL MIDDLE_DELAY
INC R0
DJNZ R4,THRES_NUM_DISP
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
LCALL NEXT_LINE
MOV DPTR,#CURRENT_TEMP_STRING
MOV R1,#9
MOV R2,#0
CURRENT_DISP:
MOV A,R2
MOVC A,@A+DPTR
LCALL WRITE_BYTE_STR
INC R2
DJNZ R1,CURRENT_DISP
LCALL CURSOR_LEFT
LCALL TEMP_INIT
LCALL READ_TEMP
CURRENT_NUM_DISP:
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
MOV A,B
LCALL MIDDLE_DELAY
LCALL WRITE_BYTE_NUM
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
MOV A,#1
MOV B,#8
LCALL SET_CURSOR
READ_TEMP_LOOP:
; 显示当前温度
LCALL DISPLAY_TEMP
; 检查温度
LCALL CMP_TEMP
JC CALL_ALARM ; 超过阈值则报警
; 温度正常,确保风扇关闭
CLR P1.0
SJMP READ_TEMP_LOOP
CALL_ALARM:
LCALL ALARM
SJMP READ_TEMP_LOOP
THRESHOLD_STRING: DB "Threshold:"
CURRENT_TEMP_STRING: DB "Current:"
; 延时函数
LONG_DELAY: ; 约33秒延时
MOV R5,#0FFH
LOOP_1:
MOV R6,#0FFH
LOOP_2:
MOV R7,#0FFH
LOOP_3:
DJNZ R7,LOOP_3
DJNZ R6,LOOP_2
DJNZ R5,LOOP_1
RET
MIDDLE_DELAY: ; 约48ms延时
MOV R6,#18H
LOOP_4:
MOV R7,#0FFH
LOOP_5:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_5
DJNZ R6,LOOP_4
RET
SHORT_DELAY: ; 约16ms延时
MOV R6,#08H
LOOP_6:
MOV R7,#0FFH
LOOP_7:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_7
DJNZ R6,LOOP_6
RET
NORMAL_DELAY: ; 约1秒延时
MOV R5,#03H
LOOP_8:
MOV R6,#0FFH
LOOP_9:
MOV R7,#0FFH
LOOP_10:
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,LOOP_10
DJNZ R6,LOOP_9
DJNZ R5,LOOP_8
RET
TWO_SEC_DELAY: ; 2秒延时
MOV R5,#0DH
TWO_SEC_LOOP:
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
DJNZ R5,TWO_SEC_LOOP
RET
TINY_DELAY: ; 约60us,DS18B20专用延时
MOV R3,#10
LOOP_11:
NOP
NOP
NOP
NOP
DJNZ R3,LOOP_11
RET
; LCD相关函数
LCD_INIT:
; 清屏
MOV P2, #1FH
MOV P0, #01H
SETB P2.7
LCALL LONG_DELAY
; 模式设置为右移,显示,光标闪烁,数据总线8位,显示两行,5×8点阵每字符
MOV P2,#1FH
MOV P0,#06H
SETB P2.7
LCALL LONG_DELAY
MOV P2,#1FH
MOV P0,#0EH
SETB P2.7
LCALL LONG_DELAY
MOV P2,#1FH
MOV P0,#38H
SETB P2.7
LCALL LONG_DELAY
CLR P2.7
RET
WRITE_BYTE_STR:
CLR P2.7
MOV P0,A
MOV P2,#5FH
SETB P2.7
LCALL MIDDLE_DELAY
CLR P2.7
RET
WRITE_BYTE_NUM:
CLR P2.7
MOV P0,A
MOV P2,#5FH
SETB P2.7
LCALL MIDDLE_DELAY
LCALL MIDDLE_DELAY
CLR P2.7
RET
NEXT_LINE:
MOV P2,#1FH
MOV P0,#0C0H
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
RET
SET_CURSOR: ; A=行号(0第一行,1第二行),B=列号(0-15)
PUSH ACC
CJNE A,#0,SECOND_LINE
MOV A,#80H
JMP CALC_COL
SECOND_LINE:
MOV A,#0C0H
CALC_COL:
ADD A,B
MOV P2,#1FH
MOV P0,A
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
POP ACC
RET
CURSOR_LEFT:
MOV P2,#1FH
MOV P0,#10H
SETB P2.7
LCALL SHORT_DELAY
CLR P2.7
RET
; 温度传感器相关函数
TEMP_INIT:
CLR P3.7 ; 拉低DS18B20总线(复位)
MOV R7,#240 ; 延时480μs
DELAY_LOOP1:
DJNZ R7,DELAY_LOOP1
SETB P3.7 ; 释放总线
MOV R7,#5
LCALL TINY_DELAY
JB P3.7,TEMP_INIT ; 检测传感器存在脉冲
MOV R7,#120
WAIT:
DJNZ R7,WAIT
MOV A,#0CCH ; SKIP ROM命令
LCALL WRITE_COMMAND
RET
WRITE_COMMAND:
MOV R7,#8
COMMAND:
RRC A
CLR P3.7
NOP
NOP
JC WRITE_ONE
MOV R6,#28
DELAY_LOOP3:
DJNZ R6,DELAY_LOOP3
SJMP BIT_END
WRITE_ONE:
SETB P3.7
MOV R6,#27
DELAY_LOOP4:
DJNZ R6,DELAY_LOOP4
BIT_END:
SETB P3.7
NOP
DJNZ R7,COMMAND
RET
CONVERT_T:
MOV A,#44H ; 温度转换命令
LCALL WRITE_COMMAND
RET
READ_TEMP: ; 返回ASCII码,A=十位,B=个位,片外7AH存二进制值
MOV A,#0BEH ; 读取暂存器命令
LCALL WRITE_COMMAND
NOP
MOV R6,#9
MOV R0,#70H
READ_DATA:
ONE_BYTE:
MOV R7,#8
ONE_BIT:
CLR P3.7
NOP
NOP
SETB P3.7
NOP
MOV C,P3.7
RRC A
LCALL TINY_DELAY
DJNZ R7,ONE_BIT
MOVX @R0,A ; 读取的温度值存入70H-7AH
INC R0
DJNZ R6,READ_DATA
MOV R0,#70H
MOVX A,@R0
ANL A,#0F0H
SWAP A
MOV R1,A
MOV R0,#71H
MOVX A,@R0
ANL A,#07H
SWAP A
ORL A,R1
MOV R0,#7AH
MOVX @R0,A
MOV B,#10
DIV AB
ORL A,#30H
ORL B,#30H
RET
ASC2BIN: ; 将ASCII码转换为二进制数
MOVX A, @R0 ; 读取ASCII码
ANL A, #0FH ; 保留低4位(数字部分)
MOV B, #10 ; 十位转换
MUL AB ; A*10→BA
MOV B,A
INC R0
MOVX A,@R0
ANL A,#0FH
ADD A,B ; 合并十位和个位
RET
CMP_TEMP: ; 比较温度,C=1表示温度超过阈值
MOV R0,#30H
LCALL ASC2BIN ; 获取阈值
MOV B,A
MOV R0,#7AH
MOVX A,@R0 ; 获取当前温度
; 比较温度
CLR C
SUBB A,B
JC TEMP_OK
SETB C ; 温度超过阈值
RET
TEMP_OK:
CLR C ; 温度正常
RET
ALARM:
MOV R5,#12 ; 设置报警循环次数
CLR P2.7 ; 启动蜂鸣器
ALARM_LOOP:
; 检查当前模式
JB 20H.0,MANUAL_ALARM ; 手动模式只报警
; 自动模式启动风扇
SETB P1.0 ; 启动风扇
MANUAL_ALARM:
; 声光报警
CLR P2.0 ; LED1亮
CLR P2.5 ; LED2亮
LCALL MIDDLE_DELAY
SETB P2.0 ; LED1灭
SETB P2.5 ; LED2灭
LCALL MIDDLE_DELAY
; 检查按键
LCALL CHECK_KEY
JC KEY_PRESSED ; 有按键则处理
DJNZ R5,ALARM_LOOP ; 循环闪烁
; 报警循环结束,重新检查温度
LCALL CMP_TEMP
JNC ALARM ; 仍然超限则重新报警
CLR P1.0 ; 温度正常,关闭风扇
CLR P2.7 ; 关闭蜂鸣器
RET
KEY_PRESSED:
; 关闭声光报警
SETB P2.0 ; 关闭LED
SETB P2.5 ; 关闭LED
SETB P2.7 ; 关闭蜂鸣器
; 延时2秒后重新检查
LCALL TWO_SEC_DELAY
; 重新检查温度
LCALL CMP_TEMP
JNC ALARM ; 仍然超限则重新报警
CLR P1.0 ; 温度正常,关闭风扇
RET
DISPLAY_TEMP:
LCALL TEMP_INIT
LCALL READ_TEMP
MOV A,#1
MOV B,#8
LCALL SET_CURSOR
LCALL WRITE_BYTE_NUM
MOV A,B
LCALL WRITE_BYTE_NUM
MOV A,#0DFH
LCALL WRITE_BYTE_NUM
MOV A,#'C'
LCALL WRITE_BYTE_NUM
RET
; 定时器0中断服务程序
TIMER0_ISR:
PUSH ACC
PUSH PSW
; 重装定时初值
MOV TH0,#3CH
MOV TL0,#0B0H
; 温度采样间隔控制(约1秒)
INC 31H
MOV A,31H
CJNE A,#20,TIMER_EXIT ; 20*50ms=1秒
; 1秒到,执行温度检测
MOV 31H,#0
LCALL TEMP_DET
TIMER_EXIT:
POP PSW
POP ACC
RETI
CHECK_KEY:
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,AGAIN
CLR C ; 无按键按下
RET
AGAIN:
; 去抖检测
LCALL SHORT_DELAY
MOV P1,#0FH
MOV A,P1
ANL A,#0FH
CJNE A,#0FH,KEY_DETECTED
CLR C
RET
KEY_DETECTED:
SETB C ; 有按键按下
RET
END