带键盘和中断的 PIC16F84A 组件

PIC16F84A Assembly with keypad and interrupt

我目前正在编写一个汇编代码,它将倒计时 BCD 计数器(通过 7 段显示)。当按下一个键时,计数器将被键盘值覆盖,然后继续倒计时。例如,如果当前计数器值为“8”,然后按键 5 覆盖,则计数器设置为“5”,然后递减计数。计数器永久倒计时,只要按下键盘上的键,计数器就会被覆盖。

这是我的电路

这是我目前编写的代码:

    COUNT EQU 0CH

    ORG 000H                                       ; reset vector
    GOTO MAIN                                      ; jump to label main during reset or startup
    ORG 004H                                       ; interrupt vector
    GOTO INT_RTN                                   ; jump to label INT_RTN or the interrupt service routine

    ;set up
    MAIN BSF STATUS, RP0 
         CLRF TRISA 
         MOVLW 0F1H
         MOVWF TRISB
         MOVLW 0DH
         MOVWF OPTION_REG
         BCF STATUS, RP0

         BSF OPTION_REG, 6                         ; interrupt event during rising edge
         BCF INTCON, INTF                          ; clear the RB0/INT interrupt flag
         BSF INTCON, INTE                          ; unmask (enable) RB0/INT interrupt source
         BSF INTCON, GIE                           ; enable all unmasked interrupt
         GOTO START

    ;Interrupt-----------------------------------------------------------
    INT_RTN BCF INTCON, GIE                        ; disable all unmasked interrupt to prevent interrupt overriding
            BTFSS INTCON, INTF                     ; check the RB0/INT interrupt flag is ‘1’ (interrupt source from RB0/INT)
            GOTO EXIT                              ; exit ISR if not RB0/INT interrupt

    ;interrupt code      
            CLRW
            BTFSC PORTB, 4
            ADDLW 01H
            BTFSC PORTB, 5
            ADDLW 02H
            BTFSC PORTB, 6
            ADDLW 04H
            BTFSC PORTB, 7
            ADDLW 08H
            CALL KEY_VAL                          ; call the array KEY_VAL
            MOVWF COUNT
            INCF COUNT
            BCF INTCON, INTF
            BSF INTCON, GIE
            GOTO CDOWN  

    EXIT  BSF INTCON, GIE                         ; enable all unmasked interrupt
          RETFIE                                  ; return from interrupt routine

    ;Program Start--------------------------------------------------------------------------------------------
    START MOVLW 0AH
          MOVWF COUNT
          MOVLW 09H 

    CDOWN MOVWF PORTA
          SLEEP
          DECFSZ COUNT, 1
          GOTO DOWN
          GOTO START

    DOWN DECF PORTA, 0
         GOTO CDOWN

    ;End of Start-----------------------------------------------------------
    KEY_VAL ADDWF PCL, F
            RETLW 01H ; returns 01H for key 1 (addr 00H)
            RETLW 02H ; returns 02H for key 2 (addr 01H)
            RETLW 03H ; returns 03H for key 3 (addr 02H)
            RETLW 00H ; returns 00H for key A (addr 03H)
            RETLW 04H ; returns 04H for key 4 (addr 04H)
            RETLW 05H ; returns 05H for key 5 (addr 05H)
            RETLW 06H ; returns 06H for key 6 (addr 06H)
            RETLW 00H ; returns 00H for key B (addr 07H)
            RETLW 07H ; returns 07H for key 7 (addr 08H)
            RETLW 08H ; returns 08H for key 8 (addr 09H)
            RETLW 09H ; returns 09H for key 9 (addr 0AH)
            RETLW 00H ; returns 00H for key C (addr 0BH)
            RETLW 00H ; returns 00H for key * (addr 0CH)
            RETLW 00H ; returns 00H for key 0 (addr 0DH)
            RETLW 00H ; returns 00H for key # (addr 0EH)
            RETLW 00H ; returns 00H for key D (addr 0FH)

     END

所以 bcd 自然会倒计时,按下按钮时会发生中断,读取 RB4 中的输入 - RB7 在 KEY_VAL 中给出的地址中找到数据并将其加载到 PORTA

但是,我的问题是,当我按下键盘上的一个按钮并启动中断时。当我阅读时,引脚 RB4-RB7 以获取 IC 给出的地址。我得到的都是高,所以我总是得到 15(D 的地址)。

如果我不按下按钮,MM74c922的引脚A B C D自然为高电平,当按下键盘中的按钮时,ic的引脚12变为高电平并将地址发送到rb4-7。问题是我认为 pic 控制器无法读取 rb4-7 中的移位,所以它总是在中断之前读取数据,中断总是很高,所以我无法获得我想要的地址。

我尝试将中断设置为在下降沿期间切换,但同样的事情发生在我的想法之外,我需要帮助

如果有帮助,这是按钮的地址

    Address: 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 0BH 0CH 0DH 0EH 0FH
    Key: 1 2 3 A 4 5 6 B 7 8 9 C * 0 # D

您的中断例程看起来有点疯狂。试试这样的:

; Save Data Space
Bank_shr   udata_shr   0x70
W_safe          RES 1
S_safe          RES 1

.....
;Interrupt-----------------------------------------------------------
INT_RTN 
    MOVWF    W_safe
    SWAPF    STATUS, W
    BCF      STATUS, RP0
    MOVWF    s_safe
Interrupt_code
    .......

Interrupt_End
    SWAPF    s_safe, w
    MOVWF    STATUS
    SWAPF    w_safe, F
    SWAPF    w_safe, w
    RETFIE                               ;GIE will set automatically 

请查看数据表中的更多详细信息,其中有一些示例

使用 GOTO 从中断返回是不明智的。当你进入中断时,它会发送它要堆栈的位置,当你 return 和 goto PC 不使用堆栈的那个 lvl 并直接跳转到标记为 GOTO 的标签时。

你能试试吗

RETFIE

而不是

BCF INTCON, INTF
BSF INTCON, GIE
GOTO CDOWN

如果有任何变化请告诉我

显然我找到了答案,而且非常简单,我在 bank 0 中编辑了选项 reg,使中断在下降沿开始时无用。

修复是

MAIN BSF STATUS, RP0 
     CLRF TRISA 
     MOVLW 0F1H
     MOVWF TRISB
     MOVLW 0DH
     MOVWF OPTION_REG
     BSF OPTION_REG, 6   --move this line here--  ; interrupt event during rising edge
     BCF STATUS, RP0

     BCF INTCON, INTF                          ; clear the RB0/INT interrupt flag
     BSF INTCON, INTE                          ; unmask (enable) RB0/INT interrupt source
     BSF INTCON, GIE                           ; enable all unmasked interrupt
     GOTO START

现在代码可以用了,谢谢大家的帮助