PIC 汇编语言 - decfsz 循环
PIC Assembly Language - decfsz loop
我正在使用 Microchip 的 PIC 18F 微控制器连续生成矩形信号。信号本身的代码位于 label5
.
我需要生成此信号的 255*20 个脉冲。所以基本上,我需要将标签 5 前 4 行的说明重复 255*20 次。因为我不能有大于 2^8 的数字,所以我需要这样写数字。
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
在下面的代码中,我试图实现这种行为。我给 variable1
值 255,然后我从这个值开始递减,直到 variable1
为零,在这种情况下,我在 label2
处返回并重新启动程序。每次我递减 variable1
我调用 label4
。类似的事情发生在 label4
。这里我有另一个变量,variable2
,它也递减直到它达到零(这里是主信号生成程序,每次递减操作都会重复),在这种情况下,程序 returns.
有人可以告诉我我的方向是否正确吗?
label2 movlw .255
movwf variable1
label3 call label4
decfsz variable1,1
goto label3
goto label2
; """"""""""""""
label4 movlw .20
movwf variable2
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
decfsz variable2,1
goto label5
return
end
```
一般建议是使用定时器来燃烧时间,有些人会争辩说中断有可能将芯片置于低功耗模式。但是对于像 PIC18 这样的处理器,您可以在其中计算指令并非常准确地从中确定执行时间,以使用简单的循环来消耗时间。
有两种方法可以使循环花费更长的时间,而且我对 PIC 编码很生疏,所以请考虑这个伪代码:
variable2 = 0
label:
decfsz variable2,1
goto label
那基本上是 256 个循环是吗?你可以计算指令,包括额外的时钟或任何时间为零的指令...
variable2 = 0
label:
nop
nop
decfsz variable2,1
goto label
添加 nop 可以消耗更多时间(是的,我可能仍然不明白你是在消耗时间还是只是想要更多循环)。
或者,如果你想让它有更多的循环,而你只有 8 位可以计算,那么嵌套循环
variable1 = 20
variable2 = 0
outer:
inner:
; other stuff goes here?
decfsz variable2,1
goto inner
decfsz variable1,1
goto outer
内循环将计数 256 次,外循环将计数 20 次,因此总共循环 20*256 次
我已经使用这种方法来生成非常准确的信号,而通过使用带有此处理器的计时器无法生成更高效的指令集,并且需要使用更快的处理器来完成同样的事情如果可能的话,用一个计时器。但是你会买一个有定时器外围设备的产品,它可以做你想做的事情或它的一部分,例如红外线遥控器,你可以获得一些 ST 产品,这些产品有两个定时器输出,并且在芯片中有和门,所以你可以有一个硬件生成的载波信号和一个硬件生成的门,但是通过软件生成门的持续时间。对于这张照片,我只是用了一些小循环来做同样的事情,而且都是通过计数指令来计时的。
我不会在 cortex-m、msp430、avr 上使用这种方法,但不是流水线的东西,也不是从别人那里购买 IP 的东西(arm 不制造芯片,st 和 nxp和其他人制造芯片并简单地从 arm 购买 IP,而芯片的大部分其余部分都不是 arm IP,每个供应商都可以在获得它时调整 ip,以便使用相同的内核(cortex-m0+ rev x.y for示例)在不同芯片中的行为不一定相同)。
另一种方法是使用值为 255*20 的 16 位循环计数器。
像这样:
;
;
;
TIMER1_CODE code
timer1:
return
;
;
;
TIMER2_CODE code
timer2:
return
;
; main application
;
MAIN_CODE code
main:
bcf TRISD,5 ; make RD5 an output
ProcessLoop:
movlw D'255' ; Compute loop count
movwf PRODL
movlw D'20'
mulwf PRODL ; PRODH:PRODL = 255*20 = 5100
OutBitLoop:
movlw 0xFF ; Decrement loop count
addwf PRODL,F
addwfc PRODH,F
bnc Stop ; Stop when done enough loops
bsf LATD,5 ; Set output bit high
call timer1
BCF LATD,5 ; Set output bit low
call timer2
bra OutBitLoop
bra ProcessLoop
Stop:
bra Stop
end
请注意,您发布的代码使用 PORTD 寄存器通过执行读取-修改-写入的操作码来设置或清除输出位。这是一个糟糕的选择。
对于 PIC18F,在更改输出位的状态时始终使用输出锁存寄存器 (LATD)。
我正在使用 Microchip 的 PIC 18F 微控制器连续生成矩形信号。信号本身的代码位于 label5
.
我需要生成此信号的 255*20 个脉冲。所以基本上,我需要将标签 5 前 4 行的说明重复 255*20 次。因为我不能有大于 2^8 的数字,所以我需要这样写数字。
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
在下面的代码中,我试图实现这种行为。我给 variable1
值 255,然后我从这个值开始递减,直到 variable1
为零,在这种情况下,我在 label2
处返回并重新启动程序。每次我递减 variable1
我调用 label4
。类似的事情发生在 label4
。这里我有另一个变量,variable2
,它也递减直到它达到零(这里是主信号生成程序,每次递减操作都会重复),在这种情况下,程序 returns.
有人可以告诉我我的方向是否正确吗?
label2 movlw .255
movwf variable1
label3 call label4
decfsz variable1,1
goto label3
goto label2
; """"""""""""""
label4 movlw .20
movwf variable2
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
decfsz variable2,1
goto label5
return
end
```
一般建议是使用定时器来燃烧时间,有些人会争辩说中断有可能将芯片置于低功耗模式。但是对于像 PIC18 这样的处理器,您可以在其中计算指令并非常准确地从中确定执行时间,以使用简单的循环来消耗时间。
有两种方法可以使循环花费更长的时间,而且我对 PIC 编码很生疏,所以请考虑这个伪代码:
variable2 = 0
label:
decfsz variable2,1
goto label
那基本上是 256 个循环是吗?你可以计算指令,包括额外的时钟或任何时间为零的指令...
variable2 = 0
label:
nop
nop
decfsz variable2,1
goto label
添加 nop 可以消耗更多时间(是的,我可能仍然不明白你是在消耗时间还是只是想要更多循环)。
或者,如果你想让它有更多的循环,而你只有 8 位可以计算,那么嵌套循环
variable1 = 20
variable2 = 0
outer:
inner:
; other stuff goes here?
decfsz variable2,1
goto inner
decfsz variable1,1
goto outer
内循环将计数 256 次,外循环将计数 20 次,因此总共循环 20*256 次
我已经使用这种方法来生成非常准确的信号,而通过使用带有此处理器的计时器无法生成更高效的指令集,并且需要使用更快的处理器来完成同样的事情如果可能的话,用一个计时器。但是你会买一个有定时器外围设备的产品,它可以做你想做的事情或它的一部分,例如红外线遥控器,你可以获得一些 ST 产品,这些产品有两个定时器输出,并且在芯片中有和门,所以你可以有一个硬件生成的载波信号和一个硬件生成的门,但是通过软件生成门的持续时间。对于这张照片,我只是用了一些小循环来做同样的事情,而且都是通过计数指令来计时的。
我不会在 cortex-m、msp430、avr 上使用这种方法,但不是流水线的东西,也不是从别人那里购买 IP 的东西(arm 不制造芯片,st 和 nxp和其他人制造芯片并简单地从 arm 购买 IP,而芯片的大部分其余部分都不是 arm IP,每个供应商都可以在获得它时调整 ip,以便使用相同的内核(cortex-m0+ rev x.y for示例)在不同芯片中的行为不一定相同)。
另一种方法是使用值为 255*20 的 16 位循环计数器。
像这样:
;
;
;
TIMER1_CODE code
timer1:
return
;
;
;
TIMER2_CODE code
timer2:
return
;
; main application
;
MAIN_CODE code
main:
bcf TRISD,5 ; make RD5 an output
ProcessLoop:
movlw D'255' ; Compute loop count
movwf PRODL
movlw D'20'
mulwf PRODL ; PRODH:PRODL = 255*20 = 5100
OutBitLoop:
movlw 0xFF ; Decrement loop count
addwf PRODL,F
addwfc PRODH,F
bnc Stop ; Stop when done enough loops
bsf LATD,5 ; Set output bit high
call timer1
BCF LATD,5 ; Set output bit low
call timer2
bra OutBitLoop
bra ProcessLoop
Stop:
bra Stop
end
请注意,您发布的代码使用 PORTD 寄存器通过执行读取-修改-写入的操作码来设置或清除输出位。这是一个糟糕的选择。
对于 PIC18F,在更改输出位的状态时始终使用输出锁存寄存器 (LATD)。