每次按下按钮时增加 pic 程序集中的二进制值

问题描述 投票:0回答:1

每次按下按钮时,尝试将输出到 LED 的值递增 1。到目前为止我写的代码如下:

    LIST P=16F84A
    INCLUDE <P16F84A.INC>

    ; Set configuration bits
    __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

; Main Program ------------------------------------------------------------
code1    EQU    0x2
Start
                bsf STATUS, RP0         ;Go to bank 1
                movlw b'11111111'       ;
                movwf TRISA             ;Set the port pin types of the RA

                movlw b'00000000'       ;
                movwf TRISB             ;Set the port pin types of the RB
                bcf STATUS, RP0         ;Go to bank 0
MainLoop
                btfss PORTA,4
                goto Button_Is_Off

Button_Is_On
                movlw d'0'              ; binary value to output on PORTB
                movwf PORTB             ; output the binary value on PORTB
                goto MainLoop

Button_Is_Off
                movlw code1+1           ; binary value to output on PORTB
                movwf PORTB             ; output the binary value on PORTB
                goto MainLoop
      
    end                                 ; end of program

我将如何修改它(我相信

movlw code1+1
行)以正确增加值?目前该值增加 1 一次,而不是每次按下按钮。

谢谢

assembly pic
1个回答
2
投票

在汇编语言中,每个操作都是使用相关体系结构指令集的指令指定的,在您的情况下是 8 位 PIC 体系结构。
因此,C 语言中的

a = a+1;
a++;
之类的操作可以仅使用一条指令完成:汇编语言中的
incf a, F
,这要归功于底层寄存器的同步加/减计数器特性。使用此指令,CPU 读取
a
的实际值,然后递增该值(向上计数),最后将更新后的值写入
a
,因为我们已经使用了
F
标志或位,它告诉 CPU 将更新后的值保存到变量本身(顺便说一句,变量是内置 RAM 的通用寄存器 (GPR) 中的分配位置)。如果我们将
W
标志而不是
F
,CPU 会将更新后的值保存在 W(工作)寄存器中。

但是,如果您使用 1 以外的值来递增变量,例如

a = a + 5
,那么指令将在汇编语言中发生变化,因为没有一个特定的指令可以像前面的示例那样执行这个简单的数学运算。汇编中的操作如下:

movlw   5
addwf   a, F

在这段代码中,CPU会执行以下步骤:

  • 文字值 5 将从程序存储器加载到 W 寄存器
  • 然后CPU会把这个值加到
    a
  • 运算结果会保存到
    a
    变量中

在简要介绍了 PIC 汇编中的值如何递增之后,您必须了解熟悉每条指令的作用对于能够在汇编中编写代码是多么重要。现在让我们回到您现有的代码并根据您希望它执行的所需操作对其进行更新。
据我了解,您希望它在每次按下和释放按钮时都一一计数。但是等待按钮释放来更新输出会有点烦人。这就是为什么我们理想地在检测到按钮按下时立即更新输出,然后等待另一次按下。然而,要做到这一点,还需要按钮释放的知识。为此,我们需要在每个循环中扫描按钮以确定按钮状态,然后相应地更新输出。如您所见,我们正在将问题分解为更小的问题,以逐个或逐步地处理每个问题。这样做,可以更轻松地为每个小问题编写代码,而不是试图一次解决所有问题。

我们遇到的问题:

  • 正确扫描按钮而不会误触发
  • 根据按钮的状态更新输出

如果需要,我们甚至可以进一步分解它们。例如,按钮的扫描需要分几步完成。因此,让我们使用伪算法指定步骤:

  • 正确扫描按钮而不会误触发
    1. 读取实际输入状态
    2. 使用小延迟滤除输入噪声*
    3. 确认输入状态稳定
    4. 进入新的输入状态

现在我们设计了一个伪程序流程,我们可以用代码来实现它:

    LIST P=16F84A
    INCLUDE <P16F84A.INC>

    ; Set configuration bits
    __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

; Main Program ------------------------------------------------------------
Start:
    bsf STATUS, RP0         ;Go to bank 1
    movlw b'11111111'       ;
    movwf TRISA             ;Set the port pin types of the RA

    movlw b'00000000'       ;
    movwf TRISB             ;Set the port pin types of the RB
    bcf STATUS, RP0         ;Go to bank 0

MainLoop:
    ; Wait for a button press
    btfss   PORTA, 4    ; Read the actual input state
    goto    MainLoop
    ; A button press is detected
    call    delay_50ms  ; TODO filter the noise out
    btfss   PORTA, 4    ; confirm that the press is stable
    goto    MainLoop    ; wait for a stable press
    ; button press is stable, proceed
    
    ; update the output
    incf    PORTB, F    ; increment the value of port B
    
    ; Now wait for button to be released
waitForButtonRelease:
    btfsc   PORTA, 4
    goto    waitForButtonRelease
    call    delay_50ms  ; TODO filter the noise out
    btfsc   PORTA, 4    ; confirm the release is stable
    goto    waitForButtonRelease
    ; button release is stable, loop back to the main and wait for
    ; a new button press
    goto    MainLoop
    
delay_50ms:
    ; TODO you are encouraged to implement this 50ms delay
    return
    
    END

我鼓励您将这个延迟程序实施 50 毫秒。这就是为什么我会把它留空。它可以正常工作,但会立即返回,没有任何延迟(实际上它会产生大约 4 个指令周期的延迟,但这不足以滤除输入噪声)。您可以在谷歌上搜索 pic assembly delay 或使用以下谷歌搜索在 Stackoverflow 中搜索它:pic assembly delay site:stackoverflow.com。你会看到有很多关于这方面的信息。
尝试理解程序流程和逻辑,在 MPLABX 模拟器中逐步模拟它以更好地理解事物。最后,如果您有什么不清楚的地方,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.