📄 hwframe.asm
字号:
MOV @R0,A ;转换后重存回接收缓冲
MOV A,#REPEATER_ADDR ;得出当前采集器的中继器的地址
MOV DPL,A
MOV DPH,#C04_ADDR_H
MOV A,@R0
ADD A,#50H ;得出中继器低位字节
MOV B,A ;存当前表的采集器的中继器的低位地址
LCALL WR_C04_1BYTE
INC DPL ;高位地址
MOV DPH,#C04_ADDR_H
MOV B,#0C3H ;高位字节
LCALL WR_C04_1BYTE
RET
;------------------------------------------------------
;写继电器状态字
HW_WR_JDQ_BYTE:
PUSH 07H ;保存当前表号
MOV R0,#HW_REC_DATA_ITEM
MOV A,@R0
LCALL BCD_HEX_1BYTE
POP 07H
MOV @R0,A ;转换后重存回接收缓冲
CJNE A,#00H,HW_JUDGE_JDQ01
AJMP HW_WRITE_JDQSTATE
HW_JUDGE_JDQ01:
CJNE A,#01H,HW_WR_FRM_OVER
HW_WRITE_JDQSTATE:
LCALL JUDGE_JDQ_STATE_BYTE ;判断当前表对应继电器下发状态
MOV A,R7
DEC A
ADD A,#C04_RELAY_STATE_0 ;得出当前表的继电器状态字的地址
MOV DPL,A
MOV DPH,#C04_ADDR_H ;状态合法,存储当前状态字
MOV R0,#HW_REC_DATA_ITEM
MOV B,@R0 ;存当前表的继电器状态字
LCALL WR_C04_1BYTE
HW_WR_FRM_OVER:
RET
;-------------------------------
;判断接收的地址号是否为本采集器号
JUDGE_REC_TERMINAL_ID:
MOV R0,#HW_REC_ADDR+5 ;接收到的地址第六字节(AA)
CJNE @R0,#0AAH,ADDR_IS_ERR ;;取出接收到的地址高位第一字,不是AA,错误地址
DEC R0 ;下一字节
CJNE @R0,#0AAH,ADDR_IS_ERR ;接收到的地址第五字节(AA),不是AA,错误地址
DEC R0 ;下一字节
CJNE @R0,#0AAH,ADDR_IS_ERR ;接收到的地址第四字节(AA),不是AA,错误地址
DEC R0 ;下一字节
MOV A,@R0 ;接收到的地址第五字节(AA)
ANL A,#0FH ;分离出采集器地址高位字节
MOV R4,A ;暂存到R4
DEC R0 ;下一字节
MOV A,@R0 ;采集器地址第二字节
MOV R5,A ;暂存到R5
DEC R0 ;下一字节
MOV A,@R0 ;接收到的地址第三字节
MOV R6,A ;暂存到R6
LCALL BCD_HEX_3BYTES ;将地址由BCD码转换为16进制
LJMP IS_RIGHT_ID ;地址正确转
;------------------------------------------
;接收到的地址非法或非本采集器地址号
ADDR_IS_ERR:
CLR HW_FRM_PROCESS ;不是本采集器地址,清帧处理标志位
;------------------------------------------
;接收地址为本采集器地址或为广播地址等合法地址
IS_RIGHT_ID:
RET
;------------------------------------------------------------------------------------------------
;数据域数据减33H处理子程序
DATA_SUBB_33H:
MOV R0,#HW_REC_DATA_FEILD_LEN ;数据域长度
CJNE @R0,#00H,ABLE_SUBB_33H ;数据域长度不为0才能进行减33H处理
SJMP UNABLE_SUBB_33H ;不进行减33H处理
ABLE_SUBB_33H:
MOV B,@R0 ;放到B寄存器
MOV R0,#HW_REC_DATA_FEILD ;数据域首地址
SUBB_33H_LOOP: CLR C
MOV A,@R0 ;读出数据域数据
SUBB A,#33H ;数据减33H
MOV @R0,A ;减后数据重写到原地址
INC R0 ;下一字节
DJNZ B,SUBB_33H_LOOP ;数据域数据减33H完成否?
UNABLE_SUBB_33H:
RET
;----------------------------------------------------------------------------------------------
;形成读/写帧正常回应帧
;R5:正常应答控制码;R6:数据域长度
FORM_SEND_READ_FRAMES:
LCALL CJQ_ACK_AND_FRAMES_HEAD_ADDR;形成发送帧头地址
MOV A,R5 ;正常应答控制码
LCALL PRODUCE_CTRL_CODE ;发送帧的控制码暂存发送缓冲区
MOV A,R6 ;数据域长度
LCALL PRODUCE_DATA_FEILD_LEN ;发送帧的数据长度
LCALL MAKE_AND_SEND_ACK_FRAMES ;产生数据标/校验和/帧结束符并发送回应帧
RET
;------------------------------------------------------------------------------------------
;从站读异常应答帧
READ_FRAMES_ERR_ACK:
RET ;数据标识错误不回应
MOV A,#02H ;数据标识错
ADD A,#33H ;加33H
MOV R0,#HW_SEND_DATA_ID1 ;发送缓冲区中要放错误信息字地址
MOV @R0,A ;错误信息字送发送缓冲区
LCALL CJQ_ACK_AND_FRAMES_HEAD_ADDR ;形成发送帧头地址
MOV A,#0C1H ;读异常回应标识
LCALL PRODUCE_CTRL_CODE ;发送帧的控制码暂存发送缓冲区
MOV A,#01H ;数据域长度
LCALL PRODUCE_DATA_FEILD_LEN ;发送帧的数据长度
LCALL PRODUCE_SUM_TAIL ;形成校验和与帧结束符#16H
LCALL SEND_ONE_FRAMES_ACK ;发送读回应帧
RET
;------------------------------------------------------------------------------------------
;从站写异常应答帧
WRITE_FRAMES_ERR_ACK:
RET ;数据标识错误不回应
MOV A,#02H ;数据标识错
ADD A,#33H ;加33H
MOV R0,#HW_SEND_DATA_ID1 ;发送缓冲区中要放错误信息字地址
MOV @R0,A ;错误信息字送发送缓冲区
LCALL CJQ_ACK_AND_FRAMES_HEAD_ADDR ;形成发送帧头地址
MOV A,#0C4H ;写异常回应标识
LCALL PRODUCE_CTRL_CODE ;发送帧的控制码暂存发送缓冲区
MOV A,#01H ;数据域长度
LCALL PRODUCE_DATA_FEILD_LEN ;发送帧的数据长度
LCALL PRODUCE_SUM_TAIL ;形成校验和与帧结束符#16H
LCALL SEND_ONE_FRAMES_ACK ;发送写回应帧
RET
;---------------------------------------
;发送帧的控制码暂存发送缓冲区
;入口:A 控制码
PRODUCE_CTRL_CODE:
MOV R0,#HW_SEND_CTRL_CODE ;控制码在接收缓冲区的地址
MOV @R0,A ;控制码暂存到接收缓冲区中
RET
;---------------------------------------
;发送帧的数据长度域暂存发送缓冲区
;入口:A 数据域长度
PRODUCE_DATA_FEILD_LEN:
MOV R0,#HW_SEND_DATA_FEILD_LEN ;数据长度域在接收缓冲区的地址
MOV @R0,A ;数据长度域暂存到接收缓冲区中
RET
;--------------------------------------
;发送帧的数据标识1暂存发送缓冲区
;入口:A 数据标识DI0
;-------------------------------------
PRODUCE_DATA_ID1:
MOV R0,#HW_SEND_DATA_ID1 ;数据标识1在接收缓冲区的地址
ADD A,#33H ;数据域数据加33H处理
MOV @R0,A ;数据标识1暂存到接收缓冲区中
RET
;--------------------------------------
;发送帧的数据标识2暂存发送缓冲区
;入口:A 数据标识DI1
;-------------------------------------
PRODUCE_DATA_ID2:
MOV R0,#HW_SEND_DATA_ID2 ;数据标识2在接收缓冲区的地址
ADD A,#33H ;数据域数据加33H处理
MOV @R0,A ;数据标识2暂存到接收缓冲区中
RET
;---------------------------------------
;形成发送帧头和地址域
CJQ_ACK_AND_FRAMES_HEAD_ADDR:
MOV R0,#HW_SEND_BUF ;发送缓冲区首地址
MOV @R0,#68H ;第一个帧起始符68H
INC R0 ;下一字节,地址域首址
MOV R1,#HW_REC_ADDR ;接收到的设备(采集器/表)地址
SAVE_RECE_ADDR_TO_SBUF:
MOV A,@R1
MOV @R0,A ;设备地址第一字节送发送缓冲区
INC R0 ;下一字节
INC R1 ;下一地址
CJNE R1,#HW_REC_HEAD2,SAVE_RECE_ADDR_TO_SBUF ;6字节没存完继续
MOV @R0,#68H ;第二个帧起始符68H
RET
;----------------------------------------------------------------------------------------------
;读写正常应答产生数据标识(读回应)和校验和及帧结束符并发送回应帧
MAKE_AND_SEND_ACK_FRAMES:
CJNE R5,#81H,MAKE_WRITE_RRIGHT_ACK ;判断是读回应帧还是写回应帧
MOV R0,#HW_REC_DATA_ID1
MOV A,@R0 ;数据标识一
LCALL PRODUCE_DATA_ID1 ;形成发送数据标识一
MOV R0,#HW_REC_DATA_ID2 ;数据标识二
MOV A,@R0
LCALL PRODUCE_DATA_ID2 ;形成发送数据标识二
MAKE_WRITE_RRIGHT_ACK:
LCALL PRODUCE_SUM_TAIL ;形成校验和与帧结束符#16H
LCALL SEND_ONE_FRAMES_ACK ;发送读回应帧
RET
;-------------------------------------------------------------------------------------------
;产生发送帧的和校验和帧尾
;B:需累加字节总数,R0:发送缓冲区地址,R1:当前累加器值暂存
;-------------------------------------------------------------------------------------------
PRODUCE_SUM_TAIL:
MOV R0,#HW_SEND_DATA_FEILD_LEN ;发送数据域字节长度地址
MOV A,@R0 ;读出数据域字节长度
ADD A,#0AH ;计算出需累加字节总数
MOV B,A ;送B寄存器
MOV R0,#HW_SEND_BUF ;发送缓冲区首地址
MOV A,@R0 ;读出帧起始符68H
MOV R1,A ;暂存到R1
MOV A,#00H ;累加器清0
PRODUCE_SUM_TAIL_LOOP:
ADD A,R1 ;需累加字节相加
MOV R1,A ;低位保存高位溢出
INC R0 ;下一字节
MOV A,@R0
DJNZ B,PRODUCE_SUM_TAIL_LOOP
MOV A,R1 ;加完后R1中为和校验值
MOV @R0,A ;存和校验
INC R0
MOV @R0,#16H ;存帧尾16H
RET
;------------------------------------------
;发送一完整回应帧
;------------------------------------------
SEND_ONE_FRAMES_ACK:
CLR R_LEDR ;红外发送灯亮
CLR ES ;禁止串行中断
SETB HW_CONTRA ;置红外发送状态
MOV SCON,#0C0H ;设置串行控制寄存器为发送状态
CLR TB8 ;清数据第9位(偶校验位)
CLR REN ;禁止接收
CPL WATCH_DOG
LCALL SEND_FRAM_HEAD_BYTE ;发送3个前导字#0FEH以唤醒从机
SETB S_LEDR ;红外接收灯灭
;-----------------------------------------------------
;发送数据帧
MOV R0,#HW_SEND_DATA_FEILD_LEN ;发送帧数据域长度
MOV A,@R0
ADD A,#0CH ;待发送帧的总长度=数据域长度+12个固定字节长度
MOV B,A
MOV R0,#HW_SEND_BUF ;发送缓冲区首地址
HW_SEND_FRM1:
MOV A,@R0
LCALL HW_SEND_ONE_BYTE ;发送单字节
INC R0
DJNZ B,HW_SEND_FRM1
MOV SCON,#0D0H ;允许接收状态
SETB ES ;开串行中断
CLR HW_CONTRA ;置红外为接收状态
SETB R_LEDR ;红外发送灯灭
RET
;-----------------------------------------------------------------
;发送3个前导字#0FEH
;-----------------------------------------------------------------
SEND_FRAM_HEAD_BYTE:
MOV A,#0FEH ;发送帧唤醒字FEH
LCALL HW_SEND_ONE_BYTE ;调发送一字节子程序
MOV A,#0FEH
LCALL HW_SEND_ONE_BYTE
MOV A,#0FEH
LCALL HW_SEND_ONE_BYTE
RET
;-----------------------------------------------------------------
;发送单个字节
;入口:A为要发送字节
;-----------------------------------------------------------------
HW_SEND_ONE_BYTE:
CPL WATCH_DOG
MOV C,P ;奇偶标志位赋予C(A中1的位数为奇数时P=1,反之为0)
MOV TB8,C ;送到第9位,使整个数据1的个数为偶数,形成偶校验
MOV SBUF,A ;要发送字节送发送缓冲区
HW_SEND_WAIT:
JBC TI,HW_SEND_BYTE_OK ;TI=1当前字节发送完毕,清TI位允许发送下一字节
SJMP HW_SEND_WAIT ;TI=0该字节没发完继续等待
HW_SEND_BYTE_OK:
RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -