编辑:PIC 16F684
好的,我有一个简单的 3 LED 二进制时钟,从 0 到 7 计数,并且希望在每个灯打开之间添加大约 1 秒的延迟。
我发现每个灯都需要处于某种循环中,并且我必须使用计数来测量滴答声和翻转等。
我认为时钟是4MHz,这是手册的屏幕截图:/image/3A3sJ.png
以下是我的代码的相关摘录:
COUNT1 EQU 20h ; Delay counter #1
COUNT2 EQU 21h ; Delay counter #2
...
LOOP0
MOVLW TRIS_D0_D1 ; Move value defined in Constants to TRISA, to switch on LED 0.
TRIS PORTA ;
CLRF PORTA ; Clear all outputs.
MOVLW D0 ; Set the accumulator to the value of D0.
MOVWF PORTA ; Move the accumulator to PORTA, to switch on LED 0.
; Using COUNTs to add a delay
decfsz COUNT1,1 ; Decrease COUNT1 by 1, and skip the next line if the result is 0.
goto LOOP0 ; If COUNT1 is 0, carry on. If not, go to LOOP0.
decfsz COUNT2,1 ; Decrease COUNT2 by 1, and skip the next line if the result is 0.
goto LOOP0 ; If COUNT1 is 0, carry on. If not, go to LOOP0.
但是,我相当确定我搞砸了时间,有人可以帮我吗?
最佳答案
假设:LOOP0
处的代码是您希望每次延迟执行一次的代码,而不是在延迟期间执行尽可能多次的代码。我还假设您将 COUNT1
和 COUNT2
设置为某项 - 您发布的代码声明了两个“变量”,但没有分配它们。
您现在的代码将重复执行 LOOP0
COUNT1
+ COUNT2
次代码。这是因为每个循环都是独立的。这为您提供了 510 个周期的最大延迟。正如其他评论者所说,PIC16 每个周期大约执行一条指令,因此您需要延迟 1,000,000 个周期才能在 4MHz 下等待一秒钟。
如果我们考虑要等待 196392
周期的情况,我们本质上需要实现一个 16 位计数器。我们通过在循环中递减一个计数器来实现这一点。每次循环退出时,我们都会减少另一个计数器。当两个计数器都为零时,循环返回。这是一个例子:
COUNT1 EQU 20h
COUNT2 EQU 21h
LOOP0
;do some stuff here
...
;delay loop starts here:
;assume COUNT1=0 and COUNT2=0
Delay_0
decfsz COUNT1
goto Delay_0
decfsz COUNT2 ;COUNT1 = 0 so 0xff cycles have passed
goto Delay_0
goto LOOP0 ;both COUNT1 and COUNT2 = 0 - 196392 cycles have now passed
分支指令如果不跳过则花费 1 个周期,如果跳过则花费 2 个周期。 goto
始终需要 2 个周期,这意味着完成一次完整计数所需的实际时间是 767 个周期 (255 * 3 + 2)。我们可以将两者所花费的时间计算为 ((255 * 3 + 2) + 3) * 255 + 2。
有一个很棒的 explanation of delay routines结束于 Dos4Ever。这将介绍延迟例程如何工作以及如何计算延迟例程的计数器值和成本。
最后,如果您只想剪切和粘贴延迟例程,Delay routine generator在 PIClist 上已经非常完美了。
关于assembly - 在 20 MHz(?) 时钟上添加 1 秒延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10375034/