1

我真的完全不明白。我在评论中以某种方式在网上看到的所有代码都有随机数,说明它为什么要执行这么多循环,但实际上没有解释为什么做什么或在哪里做什么。我真的不知道。

例如:

cblock  
Delay1  
Delay2  
Delay3  
endc  

Start:  

.  
.  
.  

Delay  
movlw .2  
movwf Delay1  ;&&&&
movlw .3  
movwf Delay2  
movlw .4       <------ Important note here. For some reason it loops back to the
movwf Delay3   <------ "&&&&" mark when it reads this piece of code. NO IDEA why

DelayLoop  
decfsz Delay1,f    <----- Explain what this does. Where does it get the time from?
goto   DelayLoop   <----- Thanks
decfsz Delay2,f    <-----
goto   DelayLoop  

end

任何帮助都会很棒。

4

3 回答 3

4

“我真的完全不明白。我在网上看到的所有代码都以某种方式在评论中包含随机数,说明为什么它会执行这么多循环,但实际上并没有解释为什么什么做什么或在哪里做什么。我真的不知道。”

“我明白这一点,但我喜欢,不知道你从哪里得到确切的时间。你是如何计算的?这些数字是从哪里来的。如果我将 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 个周期。

于 2011-02-12T05:44:53.507 回答
3

延迟循环背后的想法是燃烧一定数量的与一定时间相关的周期。每个周期的时间量取决于 PIC CPU 的时钟频率。

您发布的是类似于此处生成的三阶段延迟循环: http ://www.piclist.com/techref/piclist/codegen/delay.htm

第一个指令块用计数器加载三个内存位置。使用上面的程序找到产生所需延迟的最佳值。

第二组指令是实际延迟。"decfsz VAR,f" 将 VAR 减 1;如果 VAR 为零,则跳过下一条指令。因此在上述情况下,decfsz 将一直运行到 Delay1 为零,然后跳过“goto DelayLoop”并启动“decfsz Delay2,f”。

我建议阅读此页面: http ://www.mstracey.btinternet.co.uk/pictutorial/progtut4.htm

还有这个页面: http ://www.piclist.com/techref/microchip/PIC16DelayTutorial.htm

有关 decfsz 和 goto 如何工作的更多帮助。

于 2011-02-12T03:05:21.617 回答
1

内置 RC 振荡器的频率决定了时钟周期,而时钟周期又决定了速度。

于 2012-07-13T12:54:38.403 回答