我目前正在为8051 IC(特别是AT89C4051(实现串行例程,而我剩下的堆栈空间或内存不多,为了让我实现不错的baud在串行端口(38K或更高(上的速率,我需要进行高速案例构造,因为在我的串行端口中断程序中,我正在构建数据包并检查有效性。
假设我们在串行中断中,R0是要接收数据的内存空间的地址。假设开始地址为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
首先,上面的代码可能是实用的,但是随着数据包中的当前字节增加增加,例程每次运行2个时钟周期,因为额外的" CJNE"指令处理。例如,如果我们处于第七字节,那么" 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值每个循环每个周期为10个周期总计(包括还原旧值(。/p>
是否有一种更快的方法来处理8051汇编代码中的案例构造,以使我的串行例程更快地处理?
如果可能的话,请勿在ISR中运行逻辑。如果您坚持认为,您也许可以将DPTR分配给ISR,并且仅在非常短的常规代码中使用中断。另外,推动 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