【问题标题】:PIC Assembly Language - decfsz loopPIC 汇编语言 - decfsz 循环
【发布时间】:2020-01-07 14:25:10
【问题描述】:

我正在使用 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,它也会递减,直到它达到零(这里是主信号生成程序,每次递减操作都重复),在这种情况下,程序返回。

有人可以告诉我我是否走在正确的轨道上吗?


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

    ```

【问题讨论】:

  • 如果我正确理解了您的问题,也许我没有正确理解,但是您在这里要做的是有两个循环,一个在另一个循环中,例如 255/256 限制,您可以用一个计数循环来包装该循环到 20 有效地给出 20*256。
  • @old_timer。是的,这就是我要找的。抱歉,英语不是我的母语。
  • 嗯,这就是你要做的有一个内部循环变量/寄存器,如果需要,这将是一个紧密的循环,也许是一个 nop。然后是一个外循环。您经常会看到内部循环初始化为零,因此它递减到 0xFF,然后递减到 0x00,因此您通过循环获得 256 次,不超过作为 decfsz 一部分的比较。然后是一个包裹那个的外循环。如果你真的需要长计数,你可以继续包装。使用计时器也很好,但是对于图片和其他一些指令执行时间非常可预测的情况,这很常见。
  • @old_timer 非常感谢您的帮助!真的帮助我理解了。我会接受你的回答,但我不能,因为你在 cmets 上发布了这个。

标签: loops assembly pic microchip


【解决方案1】:

一般建议是使用定时器来消耗时间,有些人认为中断有可能使芯片处于低功耗模式。但是对于像 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 时调整 IP,因此不同芯片中的相同内核(例如 cortex-m0+ rev x.y)确实不一定表现相同)。

【讨论】:

    【解决方案2】:

    另一种方法是使用值为 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)。

    【讨论】:

      猜你喜欢
      • 2015-02-13
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多