对于运行频率为16MHz的芯片,online delay loop generator给出了运行时间为0.5s的延迟循环。
我的想法是:
如何计算开头加载的值?
ldi r18, 41
ldi r19, 150
ldi r20, 128
L1: dec r20
brne L1
dec r19
brne L1
dec r18
brne L1
答案 0 :(得分:2)
如何计算开头加载的值?
计算总循环次数=> 0.5s * 16000000 = 8000000
知道r20和r19循环的总周期(从零到零),AVR寄存器为8位,因此完整循环为256次(dec 0 = 255
)。 dec
是1个周期。条件(分支)发生时brne
为2个周期,不发生时为1个周期。
所以最内在的循环:
L1: dec r20
brne L1
从零到零(r20=0
):255 *(1 + 2)+ 1 *(1 + 1)= 767个循环(分支的255倍,经过1次)。< / p>
使用r19
的第二个包裹循环是:255 *(767 + 1 + 2)+ 1 *(767 + 1 + 1)= 197119个周期
分支时的单r18
循环则为197119 + 1 + 2 = 197122个循环。 (197121当没有采取分支=延迟循环的最终退出时,我将在下一步中通过一个技巧避免这个-1。)
现在这几乎足以计算初始r18
,让我们先用O(1)代码调整总周期,这是ldi
指令的三倍,需要1个周期:total2 = 8000000 - (1 + 1 + 1)+ 1 = 7999998 ...等等,那里的最后一个+1是什么?这个假的额外周期延迟,使最终r18
循环假装它与非最终成本相同,即197122个周期。
就是这样,最初的r18
必须足以等待至少 7999998个周期:r18 = (7999998 + 197122 - 1) div 197122 = 41
。 &#34; + 197122 - 1&#34;部分将确保丰富的周期符合约束:0 <= abundant_cycles < 197122
(剩余的197122除法)。
41 * 197122 = 8082002
...这太多了,但现在我们可以通过将r19
和r20
设置为特定值来减少额外周期,以微调延迟。那么剃掉多少钱? 8082002 - 7999998 = 82004
个周期。
单个r19
循环在分支时需要770个循环,在退出时需要769个循环,所以再次让我们通过将82004调整为仅82003来避开769循环。 82003 div 770 = 106
:可以跳过106 r19
个循环,r19 = 256 - 106 = 150
。现在这将削减81620个周期,因此82003 - 81620 = 383个周期将被削减。
单个r20
循环在分支时需要3个循环,在退出时需要2个循环。我将再次考虑退出循环只有2个循环 - &gt; 383 =&gt; 382刮胡子。并且382 div 3 = 127
,余数为1. r20 = 256 - 127 = 129
并且少做一次以减少额外的3个周期(以覆盖剩余部分)= 128.然后2个周期(3-1)等待失败使其达到完整的8mil
所以:
ldi r18, 41
ldi r19, 150
ldi r20, 128
L1: dec r20
brne L1
dec r19
brne L1
dec r18
brne L1
根据我的计算,应该等待8000000-2个周期(如果没有被其他东西打断)。
让我们尝试验证:
初始r20
:127 * 3 + 1 * 2 = 383个周期
初始r19
:1 *(383 + 1 + 2)+ 148 *(767 + 1 + 2)+ 1 *(767 + 1 + 1)= 115115个周期
(该初始r20
个未完成周期一次,然后是149次全时r20
周期,最后一个因为退出brne
而为-1
总共r18
:1 *(115115 + 1 + 2)+ 39 *(197119 + 1 + 2)+ 1 *(197119 + 1 + 1)= 7999997个周期。
三个ldi
是+3个周期= 7999997 + 3 = 80000000。
缺少的两个周期无处可见,所以我犯了一个错误。
正如你所看到的,背后的数学相当简单,但手工做的很平凡,容易出错......
啊,我想我知道我犯了哪个错误。当我刮掉丰富的循环时,不涉及终止循环(这是实际延迟过程的一部分),因此我不应该将to_shave_off循环调整为-1。然后在r19 = 106
之后,我仍然需要削减384个周期,并且正好是384/3 = 128个循环从r20 = 256-128 = 128
中剃掉。没有剩余,没有遗漏周期,完美的8mil。
如果您无法遵循此反向计算,请尝试其他方式,想象2位寄存器(仅限0..3值),并在纸上进行类似的循环,其中r18 = r19 = r20 = 2,并计算循环次数手动查看它是如何演变的。 ..即3x ldi = + 3,dec r20,brne,dec r20,brne(skip)= +5个循环,dec r19,brne = + 3,......等。
编辑:以前Jester在他的链接中解释过这个问题。而且我懒得把它清理成一些简单的公式来创建你自己的在线计算器。