📄 实验十五(自适应软件解码程序).asm
字号:
;*****定义软件解码变量*****
WUSTU DATA 2EH ;b2-b0作无线接收状态标志
;000-开始;001-同步头高电平;010-同步头低电平
;101-数据位高电平;110-数据位低电平
LXJIE BIT WUSTU.3 ;信息帧连续标志
JIEMA BIT WUSTU.4 ;接收数据有效标志(可以利用数据有效标志作为
;数据处理标志)
;数据有效,而信息帧连续标志无效时,即认为接收无效
HDATAB BIT 01H ;高电平时间,码长标志(4a为0,12a为1)
OVERT DATA 2FH ;相邻居两次捕获之间定时器溢出次数
BUFF0 DATA 30H ;解码接收缓冲区(30-3F)
TIMEL DATA 5AH ;相邻两次捕获间隔时间低8位
TIMEH DATA 5BH ;相邻两次捕获间隔时间高8位
CNTB DATA 5CH ;信息帧长度(单位为bit)
TIMEBCL DATA 7DH ;同步头高电平时间(即4a)的低8位
TIMEBCH DATA 7EH ;同步头高电平时间(即4a)的高8位
CCAP0L DATA 40H
CCAP0H DATA 43H
CCAPM0 DATA 4AH
CCON DATA 4BH
CF BIT 02H
CH BIT 03H
CL BIT 04H
CMOD DATA 4CH
EC BIT 05H
PPC BIT 06H
ORG 0000H
LJMP MAIN
ORG 0033H
LJMP PCA ;PCA中断服务程序入口地址(用于解码接收)
ORG 0050H
PROC MAIN ;主程序开始
MAIN:
MOV DPTR, #8000H ;关闭蜂鸣器
MOV A, #0FFH
MOVX @DPTR, A
;清除内部RAM
MOV R0, #08H ;清内部RAM(08H-0FFH)
LOOP1:
MOV @R0, #00H
INC R0
CJNE R0, #0, LOOP1
MOV SP, #0E3H ;堆栈区在E4-FFH,28字节
;---PCA模块初始化
;模块0工作在16位上下沿捕获方式,作解码定时器。
MOV CMOD, #00000001B ;计数脉冲为内部时钟信号/6,允许CH、CL溢出中断
MOV CH, #0 ;从0开始计数
MOV CL, #0
MOV CCON, #40H ;启动CH、CL计数
MOV CCAPM0, #00100001B ;模块0工作在16位上沿捕获方式,允许模块0中断
;开始时先用上沿捕获,中断后上下交替捕获,比用引脚高低电平
;区分上沿还是下沿触发好,因为中断后如果不能及时响应,而引脚电平在动态变化
SETB PPC ;PCA中断优先级置为高
SETB EC ;允许PCA中断
SETB EA ;开中断
NEXT1:
JNB JIEMA, NEXT1
NOP ;虚拟等待解码有效
SJMP NEXT1
END
;PCA中断服务程序
PROC PCA
PCA:
PUSH PSW
PUSH ACC
PUSH B
ORL PSW, #18H
; SETB RS1
; SETB RS0 ;使用工作寄存器区3
JBC CF, TNEXT1
;不是由定时器溢出引起
SJMP CANEXT
TNEXT1:
;定时器T溢出,则
INC OVERT
MOV A, WUSTU
JB ACC.0, TNEXT2
;低电平,看溢出次数
MOV A, OVERT
CJNE A, #2, TNEXT21
TNEXT21:
JC TOEXIT ;小于2,退出!
;溢出次数大于2,肯定是错误!
MOV OVERT, #2
ANL WUSTU, #0D0H ;解码状态清0,清除连续有效标志
SJMP TOEXIT
TNEXT2:
;在高电平期间,发现溢出次数大于指定值
MOV A, OVERT
CJNE A, #2, TNEXT22
TNEXT22:
JC TOEXIT ;小于2,退出!
;大于2
MOV OVERT, #2
ANL WUSTU, #0F0H ;清除连续有效标志,解码状态置为011(即等幅干扰状态)
ORL WUSTU, #03H ;置为011态!
TOEXIT:
JMP RETURN
CANEXT:
;捕获中断引起
MOV R3, CCAP0L
MOV R4, CCAP0H ;取捕获发生的时刻
CLR C
MOV A, R3
SUBB A, TIMEL
MOV TIMEL, A
MOV A, R4
SUBB A, TIMEH
MOV TIMEH, A ;计算并保存相邻两次捕获时间间隔到TIMEH、TIMEL中
MOV A, CCAPM0
MOV C, ACC.5 ;上升沿触发捕获标志送C
XRL CCAPM0, #30H ;与30异或,强迫CAPP、CAPN取反
ANL CCON, #0FEH ;清除CCF0中断标志
MOV OVERT, #0 ;捕获时清除溢出次数
;判别捕获原因
JC HNEXT
;下沿触发引起
; CLR C
MOV A, TIMEL
SUBB A, #140 ;PCA模块计数脉冲为系统时钟信号的6分频(晶振频率为11.0592MHz)
MOV A, TIMEH ;140对应的时间为(1/11.0592)*6*140,约76us
SUBB A, #0
JNC LNEXT0
;高电平时间太短,
ANL WUSTU, #0F0H ;重置为000态,清除连续标志
JMP RETURN ;没有必要记录
LNEXT0:
LJMP LNEXT
;上边沿触发
HNEXT:
MOV A, WUSTU
ANL A, #07H
CJNE A, #0, HNEXT1
;000态, 说明尚未开始
ORL WUSTU, #21H ;置为001态
JMP CAEND ;记录捕获时间后退出
HNEXT1:
CJNE A, #2, HNEXT2
;原来处于010态,计算同步头时间
;计算同步头脉冲相对宽度
; CLR C
MOV A, TIMEL
SUBB A, #51H
MOV A, TIMEH ;;假设a在25us~120us(允许存在25%的误差)之间
SUBB A, #16H ;124a对应计数器读数为5713~34174,即1651H~857EH
JNC HNEXT20
;小于最小值,错误
JMP HERROR ;上升沿出错处理
HNEXT20:
;CLR C
MOV A, TIMEL
SUBB A, #7EH
MOV A, TIMEH
SUBB A, #85H
JC HNEXT201
;大于124a的上限(即最大值),错误
JMP HERROR ;上升沿出错处理
HNEXT201:
;在同步头间歇期时间最小值与最大值之间
LCALL CAL1 ;当被除数较大时,用多项式除法比较合理
CJNE R6, #29, HNEXT21
HNEXT21:
JNC HNEXT22
;小于29,同步头高、低电平时间比太小!错!
JMP HERROR ;上升沿出错处理
HNEXT22:
CJNE R6, #34, HNEXT23
HNEXT23:
JNC HNEXT24
;在29-33之间,属于长同步头124a间歇期(中心值为31)
MOV CNTB, #24 ;接收24位信息码
;装入解码时脉冲头上下限
ANL WUSTU, #78H
ORL WUSTU, #01000101B;进入101态(接收数据码位)
; SETB HEADL ;长同步头标志置位
; CLR HEADM ;中等宽度同步头标志清0
JMP CAEND
HNEXT24:
;大于34,错误
JMP HERROR ;上升沿出错处理
HNEXT2:
CJNE A, #6, HNEXT3
;处于110态,计算码位低电平时间!
; CLR C
MOV A, TIMEL
SUBB A, #140
MOV A, TIMEH
SUBB A, #0 ;假设a在25us~120us(允许存在25%的误差)之间
JNC HNEXT30 ;4a对应上下限140~1102之间,即8CH~44EH
;低电平时间小于(1/11.0592)*6*140,约76us,处于非连续状态。
ANL WUSTU, #0F0H
ORL WUSTU, #100001B ;置为001态(同步头上升沿),清除连续标志
JMP CAEND
HNEXT30:
; CLR C
MOV A, TIMEL
SUBB A, #0EBH
MOV A, TIMEH
SUBB A, #0CH ;12a对应上下限为552~3307,即228H~CEBH
JNC HNEXT3
;处于4a~12a上下限之间,要进一步判别。
MOV R7, #5 ;中心值为3
LCALL CALTIME ;调用双字节除法运算子程序
CJNE R6, #2, HNEXT31
HNEXT31:
JNC HNEXT32
;在0-1之间,当4a处理!
CLR ACC.0
SJMP HNEXT341
HNEXT32:
CJNE R6, #5, HNEXT33
HNEXT33:
JNC HNEXT34
;在2-4之间,当12a处理
SETB ACC.0
HNEXT341:
MOV C, HDATAB
MOV ACC.1, C
ANL A, #03H
CJNE A, #01H, HNEXT342
;处于01态,作“0”码
CLR C
JMP DANEXT1 ;记录数据
HNEXT342:
CJNE A, #02H, HNEXT34
;处于10态,作“1”码
SETB C
JMP DANEXT1 ;记录数据
HNEXT34:
;此外,一律属于错误!
; JMP HERROR ;上升沿出错处理
HNEXT3:
JMP HERROR ;上升沿出错处理
;下沿引起引起
LNEXT:
MOV A, WUSTU
ANL A, #07H
CJNE A, #01H, LNEXT1
;原来处于001态,计算同步头高电平时间
; CLR C
MOV A, TIMEL
SUBB A, #4EH
MOV A, TIMEH
SUBB A, #04H ;4a对应上下限140~1102之间,即8CH~44EH
JNC LERROR ;大于4a上限,错!
;在4a上、下限之间,记录该时间!并作为随后计算的各脉冲宽度比的依据
MOV TIMEBCL, TIMEL
MOV TIMEBCH, TIMEH
ANL WUSTU, #0F8H
ORL WUSTU, #010B ;置为010态
JMP CAEND
LNEXT1:
CJNE A, #03H, LNEXT2
;原来处于011态(高电平时间超出12a的上限),从错误状态返回,作000态
LERROR:
;错误!
ANL WUSTU, #0F0H ;清除连续有效标志,置为000态,等待上升沿到来
JMP RETURN
LNEXT2:
CJNE A, #05H, LERROR
;101态,计算码位高电平时间
; CLR C
MOV A, TIMEL
SUBB A, #0EBH
MOV A, TIMEH
SUBB A, #0CH ;12a对应的读数为2544±30%,1780~3307,即6F4H~CEBH
JNC LERROR
MOV R7, #5 ;中心值为3
LCALL CALTIME ;调用双字节除法运算子程序
CJNE R6, #2, LNEXT31
LNEXT31:
JNC LNEXT32
;在0-1之间,当4处理!
CLR HDATAB ;短的标志
SJMP LRIGET ;正确
LNEXT32:
CJNE R6, #5, LNEXT33
LNEXT33:
JNC LERROR
;在2-4之间,当12a处理
SETB HDATAB ;长的标志
LRIGET: ;正确!
MOV A, CNTB
CJNE A, #1, LNEXT34
;如果是最后一位,则应该考虑是否是最后一帧的最后一位!
MOV C, HDATAB ;直接将HDATAB标志送Cy
ANL WUSTU, #0F8H ;置为000态
SJMP DANEXT2 ;记录数据
LNEXT34:
ANL WUSTU, #0F8H
ORL WUSTU, #110B
JMP CAEND
DANEXT1:
;解数据位过程中升沿设置问题
ANL WUSTU, #0F8H ;置为000态
ORL WUSTU, #101B
DANEXT2:
JNB JIEMA, DANEXT3
;数据有效,不再接收
DJNZ CNTB, CAEND
SJMP RETURN ;继续找脉冲头
DANEXT3:
;保存数据
MOV R0, #BUFF0
MOV R2, #3
DALOOP1:
MOV A, @R0
RRC A
MOV @R0, A
INC R0
DJNZ R2, DALOOP1
DJNZ CNTB, CAEND
;已经收到了一帧信息
JB LXJIE, DANEXT6
;连续解码标志未有效,属于第一次解码有效,数据要搬家
DANEXT60:
MOV R2, #3
MOV R0, #BUFF0 ;解码接收缓冲区首地址送R0
MOV R1, #BUFF0+8 ;解码接收缓冲区首地址+8送R1
DALOOP2:
MOV A, @R0
MOV @R1, A ;回写
INC R0
INC R1
DJNZ R2, DALOOP2
SETB LXJIE ;信息连续标志置1
SJMP RETURN ;等待同步头上升沿
DANEXT6:
;比较相邻居两此的解码结果
MOV R2, #3
MOV R0, #BUFF0 ;解码接收缓冲区首地址送R0
MOV R1, #BUFF0+8 ;解码接收缓冲区首地址+8送R1
DALOOP3:
MOV A, @R0
XRL A, @R1 ;异或
JNZ DANEXT60 ;不同,保留后一次解码结果
INC R0
INC R1
DJNZ R2, DALOOP3
;相邻居两次解码结果相同
SETB JIEMA ;解码有效
SJMP RETURN ;等待同步头上升沿
HERROR:
;上升沿出错
ANL WUSTU, #0F0H
ORL WUSTU, #01H ;清除信息帧连续标志,同时置为001态
CAEND:
MOV TIMEL, R3
MOV TIMEH, R4
RETURN:
POP B
POP ACC
POP PSW
RETI
END
PROC CALTIME ;双字节除法运算
;入口参数:
;被除数(当前脉冲宽度)存放在TIMEH、TIMEL中。
;除数存放在TIMEBCH、TIMEBCL中。
;R7记录减法运算的最大次数
;出口参数:商存放在R6
CALTIME:
MOV R6, #0 ;商清0
CLR C
LOOP1: ;利用减法完成16位除16位运算!
MOV A, TIMEL
SUBB A, TIMEBCL
MOV TIMEL, A ;保存差的低8位
MOV A, TIMEH
SUBB A, TIMEBCH
MOV TIMEH, A ;保存差的高8位
JC EXIT ;不够减退出!
;没有借位,商加1并继续
INC R6 ;商加1
DJNZ R7, LOOP1
EXIT:
RET
END
PROC CAL1 ;当被除数较大时,用多项式除法比较合理
;用时只有减法算法的50%。
CAL1:
MOV R6, #0 ;扩展为24位(16位除16位)
MOV R7, #8 ;已经除数不小于128,再扩展8位即可
LOOP1:
CLR C
MOV A, TIMEL
RLC A
MOV TIMEL, A
MOV A, TIMEH
RLC A
MOV TIMEH, A
MOV A, R6
RLC A
MOV R6, A
MOV F0, C
CLR C
MOV A, TIMEH
SUBB A, TIMEBCL
MOV R1, A
MOV A, R6
SUBB A, TIMEBCH
JNC NEXT1
;有借位继续判别移出的最高位
JB F0, NEXT1
ANL TIMEL, #0FEH
SJMP NEXT2
NEXT1:
MOV R6, A
MOV TIMEH, R1
ORL TIMEL, #01H
NEXT2:
DJNZ R7, LOOP1
MOV R6, TIMEL ;保存结果
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -