高速案例构造汇编器 + 快速加载 DPTR - 8051

high-speed case construct assembler + load DPTR fast - 8051

我目前正在为 8051 IC(特别是 AT89C4051)实现串行例程,我没有太多堆栈 space 或剩余内存,为了让我在串行端口(38K 或更高),我需要制作一个高速案例构造,因为在我的串行端口中断例程中,我正在构建一个数据包并检查其有效性。

假设我们在串行中断中,R0 是要接收数据的内存地址space。假设起始地址是 40h

所以我们来进行一些比较:

通过多次比较进行分支

serial:
    mov A,SBUF
    mov @R0,A
    mov A,R0
    anl A,#07h ;our packet is 8 bytes so get current packet # based on what we stored so far
    cjne A,#0h,nCheckMe ;this gets scanned if A=7... waste 2 clock cycles
        //We're working on first byte 
        ajmp theend
    nCheckMe:    
    cjne A,#1h,nCheckThem ;this gets scanned if A=7... waste 2 clock cycles
        //We're working on second byte 
        ajmp theend
    nCheckThem:    
    ...
    cjne A,#7h,nCheckEnd
        //We're working on last byte 
        ajmp theend
    nCheckEnd:    
    theend:
    inc R0
reti

上面的代码一开始可能是实用的,但随着要处理的数据包中当前字节的增加,由于额外的 "cjne" 指令处理,例程每次运行速度都会慢 2 个时钟周期。例如,如果我们在第 7 个字节上,那么 "cjne" 会发生很多次,因为它必须扫描每个案例,这会增加速度。

跳转分支

现在我想只使用一个跳转,但我不知道如何高速加载 DPTR,因为即使其他进程正在使用 DPTR 的值,中断也会被调用。

我想到了这段代码:

serial:
    mov A,SBUF
    mov @R0,A
    mov A,R0
    anl A,#07h ;our packet is 8 bytes so get current packet # based on what we stored so far
    swap A ;multiply A times 16 and
    rr A ;divide A by 2 so we get address times 8 since each block uses 8 bytes of code space.

    mov R3,DPH ;save DPTR high byte without breaking stack
    mov R6,DPL ;save DPTR low byte
    mov dptr,#table
    jmp @A+DPTR
    theend:
    mov DPL,R6 ;restore DPTR low byte
    mov DPH,R3 ;restore DPTR high byte
    inc R0     ;move on to next position
reti
table:
;insert 8 bytes worth of code for 1st case
;insert 8 bytes worth of code for 2nd case
;insert 8 bytes worth of code for 3rd case
...
;insert unlimited bytes worth of code for last case

在我的代码中,R3 和 R6 是空闲的,所以我用它们来存储旧的 DPTR 值,但是那些 mov 指令以及加载新的 DPTR 值每个需要 2 个周期,总共 10 个周期(包括恢复旧值) .

是否有更快的方法来处理 8051 汇编代码中的 case 构造,以便我的串行例程处理速度更快?

如果可能,不要运行 ISR 中的逻辑。如果您坚持,您可以将 DPTR 分配给 ISR,并且只在非常短的正常代码段中使用它,并禁用中断。或者,可以使用 PUSH+RET 技巧。

这是一种链式方法,其中每个处理的字符只是设置下一步的地址。如果您可以确保这些步骤在同一个 256 字节块内,则您只需要更新低字节。总开销为 8 个周期,但您还为算术节省了 4 个周期,因此它是 6 个周期的胜利。

.EQU PTR, 0x20  ; two bytes of SRAM

; Initialize PTR to address of step1 

serial:
    push PTR
    push PTR+1
    ret

step1:
    ; do stuff
    mov PTR, #low8(step2)
    reti

last_step:
    ; do stuff
    mov PTR, #low8(step1)
    reti