I am currently writing an assembly code that will count down a BCD counter (through the 7-segment display). When a key is pressed, the counter will be overridden by the key pad value then the count down continues. For example if the current counter value is ‘8’ then overridden by pressing key 5, the counter sets to ‘5’ then counts down. The counter counts down perpetually and will be overridden anytime a key is pressed on the keypad.
Here is my circuit
And here is the code i've currently written:
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
So naturally the bcd counts down, and when a button is pressed the interrupt occurs, reads the input in RB4 - RB7 finds the data in the address given in KEY_VAL and loads it to PORTA
However, my problem is, When i press a button in the keypad and the interrupt is started. When i read, pin RB4-RB7 to get the address given by the IC. All i get is all high so i always get 15 (address for D).
If i dont press a button, pin A B C D of MM74c922 is naturally high and when a button is pressed in the keypad, pin 12 of the ic turns high and the address is sent to rb4-7. The problem is i think the pic controller cannot read the shift in rb4-7 and so it always reads the data before the interrupt which is always high so i cant get the address i want.
I tried setting the interrupt to toggle during falling edge but the same thing occurs im out of ideas and i need help
if it helps this is the address for the buttons
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
So apparently I found the answer and it was very simple, I edited option reg in bank 0 making the interrupt start at the falling edge useless.
The fix was
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
now the code works, thank you all for helping me