为什么我的汇编程序子例程没有被执行?

Why My Assembler Subroutine doesn't get executed?

提问人:JophMax 提问时间:10/25/2023 更新时间:10/27/2023 访问量:54

问:

我目前正在创建代码以开始一个序列,每当我按下按钮时点亮 10 个 LED。但是,当我应用我的 BTFSS 并开始在 Proteus 上进行模拟时,即使我按下按钮,一切都保持不变。

以下是该程序的代码:

include <p16f877a.inc>
list p=16f877a

A EQU 0x20
N EQU 0x21
M EQU 0x22

BSF STATUS,5
MOVLW B'11111111'
MOVWF TRISA
CLRF TRISB
CLRF TRISD
BCF STATUS,5
MOVLW D'7'
MOVWF CMCON
CLRF PORTA
CLRF PORTB
CLRF PORTD

INICIO
BTFSS PORTA,0
GOTO INICIO
CALL RUTINA_1
GOTO INICIO

RUTINA_1
CALL ANTI_REBOTE
;10
CLRF TRISB
MOVLW B'00000010'
MOVWF PORTD
MOVLW D'200'
MOVWF A
CALL RETARDO
;9
MOVLW B'00000001'
MOVWF PORTD
MOVLW D'200'
MOVWF A
CALL RETARDO
;8
CLRF PORTD
MOVLW B'10000000'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;7
MOVLW B'01000000'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;6
MOVLW B'00100000'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;5
MOVLW B'00010000'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;4
MOVLW B'00001000'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;3
MOVLW B'00000100'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;2
MOVLW B'00000010'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
;1
MOVLW B'00000001'
MOVWF PORTB
MOVLW D'200'
MOVWF A
CALL RETARDO
GOTO RUTINA_1

ANTI_REBOTE
BTFSC PORTA,0
GOTO ANTI_REBOTE
RETURN

RETARDO
TRES
    MOVLW D'80'
    MOVWF M
DOS
    MOVLW D'25'
    MOVWF N
UNO
    NOP
    NOP
    DECFSZ N,1
    GOTO UNO
    DECFSZ M,1
    GOTO DOS
    DECFSZ A,1
    GOTO TRES
RETURN
END

我在 MPLAB 中使用了 animate 选项以及将 RA0 端口设置为高电平的刺激,但仍然什么也没发生。

程序集 序列 PIC 子例程

评论


答:

1赞 Kozmotronik 10/26/2023 #1

PIC16F877A的模拟控制寄存器不是CMCON寄存器,而是ADCON1寄存器。根据 PIC16F877A 的数据,第 4.1 节:

在上电复位时,这些引脚配置为模拟输入,读取为“0”。
比较器处于关闭(数字)状态

因此,无需配置 CMCON,因为它默认配置为关闭。

您需要配置的是 ADCON1 寄存器,因为 PORTA 具有模拟输入(ANx 引脚)。默认情况下,这些引脚配置为模拟引脚,因此始终读取为 0。这就是为什么当您按下 RA0 引脚上的输入按钮时没有任何反应。

这是因为这些端口与多种内部硬件(如ADC、比较器和数字缓冲器)进行多路复用。您需要选择正确的硬件来连接到输入引脚,因此它是您想要的数字缓冲器。

综上所述,将 RA0 引脚用作数字输入并将所有模拟引脚用作数字 IO 的正确设置如下:

include <p16f877a.inc>
list p=16f877a

A EQU 0x20
N EQU 0x21
M EQU 0x22

    ORG 0 ; <-- Reset vector
; Setup code starts from the reset vector (program memory adress 0)
BCF     STATUS,RP0
BCF     STATUS,RP1  ; Bank0
CLRF    PORTA       ; Clear garbage on IO buffers
CLRF    PORTB       ; It is a good practice to reset all used output ports 
CLRF    PORTD       ; since their values on reset is unknown.
BSF     STATUS,RP0  ; Bank1
MOVLW   D'6'        ; Configure all ANx pins as digital IO
MOVWF   ADCON1
MOVLW   B'11111111' ; Set all pins of PORTA as input
MOVWF   TRISA
CLRF    TRISB       ; Set all PORTB pins as output
CLRF    TRISD       ; Set all PORTD pins as output

INICIO
BTFSS   PORTA,0
GOTO    INICIO
CALL    RUTINA_1    ; You better debounce the button press before proceeding
GOTO    INICIO