📄 zbint.asm
字号:
;------------------------------------------------------------------------------------
;载波发送和接收中断服务子程序
;--接收:FRM_PROCESS,SYNB,HEAD_LO,HEAD_HI,REC_WHOLE_BYTE,REC_BIT_LEN,REC_CUR_LEN
;--发送:TXD_READY_FLAG,COUNTER_SEND_DELAY,SEND_BYTE_OVER,SEND_WHOLE_BYTE,SEND_BIT_LEN
;------------------------------------------------------------------------------------
CARRIER: PUSH ACC ;压栈ACC
PUSH PSW ;压栈PSW
PUSH 0F0H ;压栈B寄存器
PUSH 00H ;压栈R0
PUSH 06H
; CLR ZB_HW ;串行口置载波收发状态
; SETB RXD ;收发数据线置高准备好接收下一位
JB RX_TX,CARRIER_REC ;ST7536是否处在接收状态
JB TXD_READY_FLAG,CARRIER_SEND
DJNZ COUNTER_SEND_DELAY,JMP_EXIT
SETB TXD_READY_FLAG
MOV SEND_BIT_LEN,#8 ;发送的位数=8
SJMP JMP_EXIT
;--------------------------------------------------
;载波发送
CARRIER_SEND:
JB SEND_BYTE_OVER,JMP_EXIT ;当前字节发送完否
WAIT_FOR_304CYCLES:
WAIT_01:
CPL WATCH_DOG
MOV R6,#70
WAIT_02:
NOP
NOP
DJNZ R6,WAIT_02
MOV A,SEND_WHOLE_BYTE ;先发字节的低位
CLR C
RLC A
MOV SEND_WHOLE_BYTE,A ;
JC SETB_TXD_1
CLR TXD
SJMP SEND_NEXT_BIT
SETB_TXD_1:
SETB TXD
SEND_NEXT_BIT:
DEC SEND_BIT_LEN ;已发送的位数加1
MOV A,SEND_BIT_LEN
CJNE A,#00H,JMP_EXIT ;8位发送完否
SETB SEND_BYTE_OVER ;置字节发送完标志
MOV SEND_BIT_LEN,#8 ;已发送的位数清零,准备发送下一字节
LJMP EXIT_INT
;-------------------------------------------------
;载波接收
;同步字节09AF接收判断:
CARRIER_REC:
JB FRM_PROCESS,JMP_EXIT ;当前帧命令处理完否?未处理完时,跳出中断,不处理该字节
JB SYNB,RECEIVE0 ;判断同步头09AF,;--先发高字节09H(HEAD_HI)的低位,依次类推
SETB R_LEDC ;收到正确信息后亮,然后收到干扰信息后接收灯灭
JNB RXD,CLR_CY
SETB C
SJMP SETB_CY
CLR_CY: CLR C
SETB_CY:
MOV A,HEAD_LO
RLC A ;每收1位同步字右移1位
MOV HEAD_LO,A
MOV A,HEAD_HI
RLC A
MOV HEAD_HI,A ;先收高字节09H(HEAD_HI)的低位,依次类推
CJNE A,#0AAH,JMP_EXIT ;同步头第1字节为#09H?
MOV A,HEAD_LO
CJNE A,#0AAH,JMP_EXIT ;同步头第2字节为#0AFH?
MOV HEAD_LO,#0FFH
MOV HEAD_HI,#0FFH
SETB SYNB
MOV REC_BIT_LEN,#00H ;8位字节数清零
JMP_EXIT: LJMP EXIT_INT
;----------------------------
;接收数据容错判断程序: 连续接收3字节,逐位比较得出正确字节。
RECEIVE0:
JNB RXD,REST_CY
SETB C
SJMP SETB_CY_BIT
REST_CY:
CLR C
SETB_CY_BIT:
; MOV C,RXD ;接收下一位
MOV A,REC_WHOLE_BYTE ;要接收的当前字节
RLC A ;右移1位
MOV REC_WHOLE_BYTE,A ;重新存入接收寄存器
INC REC_BIT_LEN ;当前接收位长度+1
MOV A,REC_BIT_LEN
CJNE A,#8,RECE_SECOND_BYTE ;8位接收完毕否?
MOV ZBREC_FIRST_BYTE,REC_WHOLE_BYTE ;第一次接收到的数据暂存
LJMP EXIT_INT
RECE_SECOND_BYTE:
CJNE A,#16,RECE_THIRD_BYTE ;16位接收完毕否?
MOV ZBREC_SECOND_BYTE,REC_WHOLE_BYTE ;第二次接收到的数据暂存
LJMP EXIT_INT
RECE_THIRD_BYTE:
CJNE A,#24,JUDGE_REC_TIMES ;24位接收完毕否?
MOV ZBREC_THIRD_BYTE,REC_WHOLE_BYTE ;第三次接收到的数据暂存
MOV REC_BIT_LEN,#00H ;3字节接收完毕,接收位字节计数器清零
;-------------------------
;错误校正程序
ERROR_CORRECTION:
MOV B,#08H ;3字节比较次数
CLR C ;清进位位为0
ERROR_JUDGE_STA:
MOV A,ZBREC_FIRST_BYTE ;取出接收首字节
RRC A ;右移一位
MOV ZBREC_FIRST_BYTE,A ;重存首字节
JC ERROR_JUDGE_AA ;判断当前位为1否?
MOV A,ZBREC_SECOND_BYTE ;取出接收第2字节
RRC A ;右移一位
MOV ZBREC_SECOND_BYTE,A ;重存第2字节
JC ERROR_JUDGE_BB ;判断当前位为1否?
MOV A,ZBREC_THIRD_BYTE ;取出接收第3字节
RRC A ;右移一位
MOV ZBREC_THIRD_BYTE,A ;重存第3字节
ERROR_JUDGE_00:
MOV A,REC_WHOLE_BYTE ;取出接收正确字节寄存器存储数据
CLR C ;3字节相同位有至少2位为0则清进位位
RRC A ;右移一位
MOV REC_WHOLE_BYTE,A ;重存
ERROR_NEXT_BIT:
DJNZ B,ERROR_JUDGE_STA ;判断8位比较完否?
AJMP FRM_JUDGE ;转帧处理程序
ERROR_JUDGE_AA:
MOV A,ZBREC_SECOND_BYTE ;取出接收第2字节
RRC A ;右移一位
MOV ZBREC_SECOND_BYTE,A ;重存第2字节
JC ERROR_JUDGE_CC ;判断当前位为1否?
ERROR_JUDGE_BB:
MOV A,ZBREC_THIRD_BYTE ;取出接收第3字节
RRC A ;右移一位
MOV ZBREC_THIRD_BYTE,A ;重存第3字节
JC ERROR_JUDGE_01 ;判断当前位为1否?
AJMP ERROR_JUDGE_00 ;1字节为1,2字节为0,3字节为0正确字节该位置为0
ERROR_JUDGE_CC:
MOV A,ZBREC_THIRD_BYTE ;取出接收第3字节
RRC A ;右移一位
MOV ZBREC_THIRD_BYTE,A ;重存第3字节
ERROR_JUDGE_01:
MOV A,REC_WHOLE_BYTE ;取出接收正确字节寄存器存储数据
SETB C ;任意2位或以上位为1,置进位为1
RRC A ;右移一位
MOV REC_WHOLE_BYTE,A ;重存
AJMP ERROR_NEXT_BIT
JUDGE_REC_TIMES:
SUBB A,#25 ;判断接收位数大于25否?
JC EXIT_INT ;<=24,继续接收
MOV REC_BIT_LEN,#00H ;>24,表示出错,接收位长度清0
SJMP ERROR_CORRECTION ;转接收数据错误冗余修正判断
;----------------------
;接收帧正确否判断程序:
FRM_JUDGE:
MOV R0,#REC_HEAD ;判断接收缓冲区首字节为帧头68H否
CJNE @R0,#68H,FINDING_HEAD ;帧头是否找到?
MOV A,REC_WHOLE_BYTE
CJNE A,#16H,SAVE_BYTE
MOV R0,#REC_DATA_FEILD_LEN ;接收到的字节为16H,且数据域长度不为0
CJNE @R0,#00H,FINDING_END ;是否帧尾?
SJMP SAVE_BYTE ;非帧尾,是帧内中间字节(ADDR OR CODE) 保存
FINDING_HEAD: MOV A,REC_WHOLE_BYTE
CJNE A,#68H,NOT_HEAD
SJMP SAVE_BYTE ;是帧头,保存
NOT_HEAD: SJMP ERROR_HANDLE
FINDING_END: MOV R0,#REC_DATA_FEILD_LEN
MOV A,#07H
ADD A,@R0 ;帧尾字节应在的位置
DEC A ;若是帧尾,当前接收到的字节数比应接收到的字节数少1
CJNE A,REC_CUR_LEN,SAVE_BYTE ;非帧尾,是帧内的字节,保存
SETB FRM_PROCESS ;置帧处理标志,保存帧尾
CLR SYNB ;清同步头
SAVE_BYTE: MOV A,REC_CUR_LEN
CLR C
SUBB A,#REC_BUF_LEN+1 ;接收的总长度是否超过20个字节?
JNC ERROR_HANDLE
MOV A,#REC_BUF ;是帧内的字节,保存
ADD A,REC_CUR_LEN ;计算在帧内应存放的地址
MOV R0,A
MOV A,REC_WHOLE_BYTE
MOV @R0,A
INC REC_CUR_LEN ;当前接收到的帧字节数+1
JNB FRM_PROCESS,EXIT_INT ;和校验
MOV A,REC_CUR_LEN
DEC A
DEC A
MOV B,A
ADD A,#REC_BUF ;校验和的地址
MOV R0,A
MOV A,@R0
PUSH A ;校验和压栈
MOV R0,#REC_BUF
MOV A,#00
CHECK_SUM: ADD A,@R0
INC R0
DJNZ B,CHECK_SUM
MOV B,A
POP A
CJNE A,B,ERROR_HANDLE ;和校验错,清FRM_PROCESS
CLR R_LEDC ;收到正确信息后亮.
SJMP EXIT_INT
ERROR_HANDLE: SETB R_LEDC ;接收灯灭
MOV REC_CUR_LEN,#00H ;当前帧长度清0
MOV R0,#REC_BUF
MOV B,#REC_BUF_LEN
CLR_REC1: MOV @R0,#00H
INC R0
DJNZ B,CLR_REC1
CLR FRM_PROCESS
CLR SYNB ;直接接收时,不判同步头,该指令可不要
EXIT_INT:
; SETB ZB_HW ;串行口初始置红外接收状态
POP 06H
POP 00H
POP 0F0H
POP PSW
POP ACC
RETI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -