“我真的完全不明白。我在网上看到的所有代码都以某种方式在评论中包含随机数,说明为什么它会执行这么多循环,但实际上并没有解释为什么什么做什么或在哪里做什么。我真的不知道。”
“我明白这一点,但我喜欢,不知道你从哪里得到确切的时间。你是如何计算的?这些数字是从哪里来的。如果我将 VAR1 设置为 15,会发生什么,会发生什么变化。如果我设置三个延迟变量到 4、16、12,时间从何而来?这些数字会发生什么导致循环成为特定时间?谢谢 – Jimmy Page"
如果我理解你的问题,那么:
16F690 数据表说:
一个指令周期由四个振荡器周期组成,振荡器频率为 4 MHz,这给出了 1 μs 的正常指令执行时间。所有指令都在一个指令周期内执行,除非条件测试为真,或者程序计数器因指令而改变。发生这种情况时,执行需要两个指令周期,第二个周期作为 NOP 执行。
所以假设 Delay1 的值为 3,我们有这个循环:
最佳
decfsz 延迟 1,f
转到顶部
每次我们执行 decfsz 时,我们都会获得一个周期的库存。如果 f 为零并且我们必须跳过,那么它就变成了一个两周期指令。每次我们执行 goto 时,pc 都会发生变化,因此它是一个 2 周期指令。所以如果我们走循环,我用格式展示这个
指令前的延迟 1 值、指令、用于执行的周期、总周期
3,decfsz,1,1
2,转到,2,3
2,decfsz,1,4
1,转到,2,6
1,decfsz,2,8
因此,如果我们以 4mhz 运行,延迟 1 从 3 开始的循环本身需要 8 个周期或 8us。首先计算周期很重要,然后调整部件的时钟速率,相同的代码在 2mhz 运行时可能是 16us,在 1mhz 运行时可能是 32us。
因此,通过检查我们可以看到,对于非 1 的 f 值,decfsz+goto 对是 2+1=3 个周期。一次我们使用值为 1 的 decfsz 将是 2 个周期。因此,从 3 的 Delay1 开始,将有 2 个非一个条目值 (3,2)。最后一次点击 decfsz 并跳过时添加 2 个周期,总周期 ((3-1)*3)+2=8。
如果我们在 Delay1 设置为 11 的情况下进入此循环,则将是 ((11-1)*3)+2=32 个周期,7 将是 20 个周期。
如果你走得更远,将一个 decfsz 循环包裹在另一个循环上,你将继续乘以执行的循环数。如果Delay1 是一个3 进入并且Delay2 是一个2
最佳
decfsz 延迟 1,f
转到顶部
decfsz 延迟2,f
转到顶部
然后第一次通过Delay1 decfsz,goto循环我们知道是8个周期。第一个 decfsz Delay2,f 因为 Delay2 不是 1 是 1 的循环,所以我们总共最多 9 个。goto 还有 2 个,总共 11 个。假设 f 内存是 8 位,那么我们第二次进入延迟 1 循环时,我们输入 0,将其视为 0x100 或 256,因为数学给了我们 ((256-1) 3)+2=767 更多周期, 到目前为止共有 778 个。Delay2 现在是 1,所以这是最终的 decfsz Delay2,f,因此我们花费了 2,总共 780 个周期。我们可以想出一个算法来计算接近 ((Delay2-1) (((256-1)*3)+2))+((((Delay1)-1)*3)+ 2)+((延迟2-1)*3)+2个周期。
虽然我的循环比你的小一个 decfsz 循环,但如果你让我的循环与你的相似,它会从其他一些指令开始:
入口
movlw .3
movwf 延迟1
movl2 .2
movwf 延迟2
最佳
decfsz 延迟 1,f
转到顶部
decfsz 延迟2,f
转到顶部
我们需要为两个 movlw's 和两个 movwf's 添加 4 个循环到要执行的循环数的整体方程。
因此,从字面上看,有一个解释为什么它要执行这么多周期。该解释在该设备的数据表中。
让我们更进一步。让我们获取 patrickmdnet 链接到的代码生成器以生成 780 个周期:
; 延迟 = 780 个指令周期
; 时钟频率 = 4 MHz
; 实际延迟 = 0.00078 秒 = 780 个周期
; 误差 = 0 %
块
d1
d2
结束
;778 个循环
movlw 0x9B
movwf d1
movlw 0x01
movwf d2
延迟_0
decfsz d1, f
转到 $+2
decfsz d2, f
转到延迟_0
;2 个周期
转到 $+1
这个循环的架构有点不同。
我们从加载 f 寄存器的 4 个周期开始,然后到达 Delay_0
内部 decfsz 循环 goto 不会直接分支到 Delay_0,因为您的问题中的代码和我上面的解释,这个跳过了 decfsz d2,f。因此,对于非一个通过该循环的对象,decfsz 有 1 个周期,goto $+2 有 2 个周期,goto Delay_0 有 2 个周期,每个非 1 d1 总共有 5 个周期。并且在 d1 为 1 时再添加两个。这给了我们 ((0x9B-1)*5)+2 = 772 个周期,加上之前的 4 个周期,我们最多有 776 个周期。
有趣的是,最后一个 decfsz d1,f 命中了一个 d2 设置为 0x01 的 decfsz d2,f ,这意味着它可以保证跳过。它是 2 个周期,一个 goto $+2 和另一个 goto $+1 而不是加载 d2 的 movlw/movwf 会做同样的事情。无论如何,这条 2 个周期的单条指令使我们总共有 778 个周期
我们还需要两个周期才能达到 780,这是通过 goto $+1 完成的,goto 修改 pc,因此它们始终是 2 个周期。我们有我要求程序生成的 780 个周期。