我正在尝试创建软件延迟。以下是我正在做的示例程序:
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
答案 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
之类的循环。这在功耗方面节省了更多。