⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 实验十五(自适应软件解码程序).asm

📁 基于51单片机的 自适应软件解码程序
💻 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 + -