带键盘和中断的 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
现在代码可以用了,谢谢大家的帮助
我目前正在编写一个汇编代码,它将倒计时 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
现在代码可以用了,谢谢大家的帮助