Z80软件延迟

时间:2015-03-21 16:12:01

标签: z80

我正在尝试创建软件延迟。以下是我正在做的示例程序:

    Address  Data   Opcode  Comment    
    1800      06    LD, B   Load register B with fix value
    1801      “ “           Fixed value
    1802      05    DEC, B  Decrement value in register B
    1803      C2    JP cc   Jump to 1802 if value is not 0
    1804      02    -       Address XX
    1805      18    -       Address XX

我的问题是如何计算加载到寄存器B所需的固定值,以便将值递减到0的过程需要2秒?

在我的手册中,运行指令的时间基于4MHz CPU,但我使用的Z80 CPU的速度为1.8MHz。知道如何计算这个吗?谢谢。 P.S这里是手册中的减量(DEC)和跳跃(JP cc)指令:

Instruction    M Cycles    T states   4 MHz E.t
DEC r             1           4         1.00
JP cc             3       10 (4,3,3)    2.50

2 个答案:

答案 0 :(得分:3)

如果1.8MHz意味着正好是1,800,000赫兹,那么为了获得2秒的延迟,你需要延迟3,600,000个T状态。您当前的延迟循环每次迭代需要14个T状态,这意味着B的初始值必须为3600000/14 == 257143,这显然不适合一个字节。

您可以使用8位寄存器指定的最大迭代次数为256,并且要达到3,600,000个具有256次迭代的T状态,每次迭代必须采用14,062个T状态。这是一个循环体。

如果我们使用16位计数器,事情开始变得更易于管理。在65,536次迭代中,我们每次迭代仅需要55个T状态以达到总共3,600,000个T状态。下面是一个示例:

    ; Clobbers A, B and C
    ld      bc,#0
1$:
    bit     #0,a    ; 8
    bit     #0,a    ; 8
    bit     #0,a    ; 8
    and     a,#255  ; 7
    dec     bc      ; 6
    ld      a,c     ; 4
    or      a,b     ; 4
    jp      nz,1$   ; 10, total = 55 states/iteration
    ; 65536 iterations * 55 states = 3604480 states = 2.00248 seconds

答案 1 :(得分:2)

我是一个优化怪物,所以这里是我使用我最熟悉的语法(来自TASM汇编程序和类似):

Instruction   opcode    timing
ld bc,$EE9D   ;01EE9D   10cc
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
djnz $        ;10FA     13cc*(256C+B) - 5*C
dec c         ;0D       4*C
jr nz,$-3     ;20F7     12*C-5

此代码为12个字节和3600002个时钟周期。

编辑:似乎我的答案的一部分已经消失了!为了更好地回答您的问题,您的Z80可以在一秒钟内处理1800000个时钟周期,因此您需要两倍(3600000)。如果你把我的代码中给出的时间加起来,你会得到:

= 10 +(256C + B)(19×4 + 13)+ -5℃4C + 12C-5

= 5 +(256C + B)89 + 11C

= 5 + 22795C + 89B

因此代码时序在很大程度上依赖于C. 3600000/22795约为157,因此我们用157(0x9D)初始化C.将其重新插入,我们得到的B大约为237.9775,因此我们将其舍入到238(0xEE)。将这些插入到我们的最终时间为3600002cc或大约2.000001秒。这假设处理器正好以1.8MHz运行,这是不太可能的。

同样,如果您可以使用中断,请大致计算出每秒触发的次数并使用halt \ djnz $-1 之类的循环。这在功耗方面节省了更多。