;
;*************************************************************************
;* ★温湿度读取子程序★ *
;*-----------------------------------------------------------------------*
;* 总线空闲状态为高电平 *
;* 主机把总线拉低等待DHT11响应,>18毫秒,保证DHT11能检测到起始信号。 *
;* DHT11接收到主机的开始信号后,等待主机开始信号结束 *
;* 然后发送80us低电平响应信号. *
;* 主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号, *
;* 主机发送开始信号后,切换到输入模式或输出高电平均可, 总线由上拉电阻拉高 *
;* 总线为低电平,说明DHT11发送响应信号 *
;* DHT11发送响应信号后,再把总线拉高80us,准备发送数据 *
;* 每一bit数据都以50us低电平时隙开始 *
;*-----------------------------------------------------------------------*
;* 20 ~ 40μs *
;* 主机:  ̄|__________| ̄ ̄ ̄ ̄ ̄ ̄|_ *
;* 18mS ↓ *
;*--------------------------------↓-------------------------------------*
;* ↓ 80μs 80μs *
;* 从机:  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|_______________| ̄ ̄ ̄ ̄ ̄ ̄|_____ *
;* 应答信号 拉高准备送数 *
;*-----------------------------------------------------------------------*
;* 上限 下限 *
;* 26μs 28μs *
;* ↓ ↓ *
;* "0" 位:  ̄|______| ̄ ̄ ̄|_____| ̄ ̄ ̄ *
;* ↑ ↑ *
;* 50μs 77μs *
;*-----------------------------------------------------------------------*
;* 70μs *
;* ↓ *
;* "1" 位:  ̄|______| ̄ ̄ ̄ ̄ ̄ ̄ ̄|___| ̄ ̄ *
;* ↑ ↑ *
;* 50μs 120μs *
;*************************************************************************
RH:
SZ T_H_EN ;检查温湿度采样允许标志
JMP RH_0 ;T_H_EN="1",允许采样
RET
;
RH_0: SZ TIM_20MS
JMP RH_1 ;正在20mS定时,转RH_1
;
CLR PAC.2 ;PA.2口(测温)定义为输出口
CLR DATA ;PA.2  ̄\_ ,主机拉低总线
;**************************************
;* 主机拉低总线,至少延时18mS *
;* 此处与众不同,<15mS不行,多一高电平 *
;**************************************
;
SET TIM_20MS ;TIM_20MS←"1",开始计时
MOV A,03 ;8ms x 2=16ms
MOV T_20MS,A
;
RH_1: SZ T_20MS
JMP RH_END ;20mS未到,出去
CLR TIM_20MS
;
;*******************************************************
;* 主机拉高总线等候从机应答,延时50μs *
;*-----------------------------------------------------*
;* "#" *
;* ←-----20mS--------→ ← 80μS→ *
;*  ̄|__________| ̄ ̄ ̄|____| ̄ ̄ ̄ ̄|_ *
;* --→12μs ←-- ←80μS → *
;* "&" "$" *
;*-----------------------------------------------------*
;* 关于"&"处延时,手册上要求20~40μs,实测至少12μs *
;* 主机至少拉高12μs,从机才来得及响应 *
;*******************************************************
SET DATA ;PA.2 _/ ̄ ,主机拉高总线
D_50 ;延时48μs,位置与上图"&"处对应
;**********************************
;* 主机延时48μs,跨越20~40μs区 *
;* 检测从机是否响应,无响应则出去 *
;**********************************
SET PAC.2 ;PA.2口(测温)定义为输入口
RH_2: SZ DATA ;检查PA.2数据脚状态
JMP RH_END ;≠"0",转RH_END,出去
;***************************************
;* 数据脚为低,从机 ̄\_ 拉低总线已响应 *
;* OVER=09 x 3μs=30μs 为最小值 *
;***************************************
MOV A,50 ;设置超时计数
MOV OVER,A ;50 x 3μs =150μs
RH_3: SZ DATA ;检查PA.2数据脚状态
JMP RH_4 ;="1",转RH_4,从机_/ ̄己拉高(80μs)
SDZ OVER ;超时计数减1
JMP RH_3 ;OVER≠"0",未超时,转RH_3循环检测
JMP RH_END ;OVER="0",超时了,转RH_END,出去
;
;***************************************
;* 80μs后,从机_/ ̄ 拉高总线,响应结束 *
;***************************************
RH_4: MOV A,OFFSET ACP_DAT;接收数据初始赋值
MOV MP0,A ;设置12位接收码变量数组指针
MOV A,05
MOV BYTE_CNT,A ;预置5字节接收字节计数器
;
RH_11: MOV A,08H ;
MOV BIT_CNT,A ;每字节共接收8bit
MOV A,00
MOV ACCEPT_DATA,A ;读出当前字节接收数据
;
MOV A,50 ;设置超时计数
MOV OVER,A ;50 x 3μs =150μs
RH_5: SNZ DATA ;检查PA.2数据脚状态
JMP RH_13 ;="0",转RH_13,从机 ̄\_ ,80μs拉高结束
SDZ OVER ;超时计数减1
JMP RH_5 ;OVER≠"0",未超时,转RH_5循环检测
JMP RH_END ;OVER="0",超时了,转RH_END,出去
;
;******************************************
;* 80μs后,以下为从机开始发送数据部分 *
;*----------------------------------------*
;* ← 54μS→ *
;* "0"  ̄|____| ̄ ̄ ̄|_ *
;* → 24μs← *
;*----------------------------------------*
;* ← 54μS→ *
;* "1"  ̄|____| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|_ *
;* ←---- 70μs ----→ *
;******************************************
;
;******************************************
;* 从机 ̄\_ 拉低总线50μs,发送数据引导位 *
;******************************************
RH_13: MOV A,50 ;设置超时计数
MOV OVER,A ;50 x 3μs =150μs
RH_6: SZ DATA ;检查PA.2数据脚状态
JMP RH_7 ;="1",转RH_7,从机数据引导位信号结束
SDZ OVER ;超时计数减1
JMP RH_6 ;OVER≠"0",未超时,转RH_6循环检测
JMP RH_END ;OVER="0",超时了,转RH_END,出去
;
;*****************************************************
;* 引导位结束,从机_/ ̄拉高总线发送数据位 *
;*---------------------------------------------------*
;* 主机延时42μs后测DATA线,低为"0",高为"1" *
;* 实测20μs~42μs(>42μs,<20μs出错),取中值31μs *
;*****************************************************
RH_7:
D_30 ;主机延时31μs
NOP
;
SET FLAG ;数据位标志置"1"
SZ DATA ;检查PA.2数据脚状态
JMP RH_8 ;≠"0",转RH_7,待从机数据引导位信号结束
;*****************************
;* <42μs就拉低了,是数据"0" *
;*****************************
CLR FLAG ;数据位标志置"0"
JMP RH_9 ;转RH_9保存数据处理
;
;*****************************
;* >42μs还未拉低,是数据"1" *
;*****************************
RH_8: MOV A,50 ;设置超时计数
MOV OVER,A ;50 x 3μs =150μs
SNZ DATA
JMP RH_9 ;="0",高电平己结束,转RH_9保存数据
SDZ OVER ;超时计数减1
JMP RH_8 ;OVER≠"0",未超时,转RH_8循环检测
JMP RH_END ;OVER="0",超时了,转RH_END,出去
;
;******************************************
;* 保存数据处理 *
;*----------------------------------------*
;* 数据格式:(高位先出,小数未用,输出为"0") *
;* 8bit湿度整数+8bit湿度小数 *
;* +8bit温度整数+8bit温度小数 *
;* +8bit校验和 *
;******************************************
RH_9: SET C ;进位位标志先预置"1"
SZ FLAG ;检查数据位标志
JMP RH_10 ;数据位是"1',转RH_10继续
CLR C ;数据位是"0',则进位位标志置"0"
;**********************************
;* ACCEPT_DATA C←D7......←D0 *
;* 带进位左环移 ↓___________↑ *
;**********************************
RH_10: RLC ACCEPT_DATA ;将接收到的信号放入ACCEPT_DATA
SDZ BIT_CNT ;检查接收位计数器,并减一
JMP RH_5 ;8位未到,转RH_5继续收数循环
;***************************
;* 满8bit,保存当前字节数据 *
;***************************
MOV A,ACCEPT_DATA ;读出当前字节接收数据
MOV IAR0,A ;送到接收码变量数组
INC MP0 ;数组指针加一
SDZ BYTE_CNT ;字节计数器减一,并检查是否为"0"
JMP RH_11 ;≠"0",5字节未满,转RH_11循环
;****************************************
;* 检查电源是否欠压 *
;* 若为欠压状态,则不作温湿度上下限判断, *
;* 禁止马达工作,并定时蜂鸣 *
;****************************************
CLR ALM_EN ;低电压报警允许标志复位
CLR ALM_TIM
SZ POWER_LOW ;检查低电压检测信号
JMP RH_12 ;="1",电压正常,转RH_12继续
;******************
;* 低电压报警处理 *
;******************
SET ALM_EN ;低电压报警允许标志置位
SET ALM_TIM
MOV A,02 ;开启应答,短鸣2次
MOV FM_CNT,A
SET BEE ;蜂鸣一次允许
JMP RH_END2 ;直接转出口
;
RH_12: JMP T_H_CP ;温湿度上下限判断(16进制运算)
RH_12_RET: NOP ;〓◆此处把CALL指令改为JMP,减少堆栈级数◆〓
; CALL T_H_CP ;温湿度上下限判断(16进制运算)
JMP DTB ;十进制转换
; CALL DTB ;十进制转换
CALL_DTB_RET: NOP ;〓◆此处把CALL指令改为JMP,减少堆栈级数◆〓
;
RH_END2: CLR T_H_EN ;禁止温湿度采样
RH_END: RET |