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)。