2

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

enter image description here

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
Mike
  • 4,041
  • 6
  • 20
  • 37
JezT
  • 57
  • 8
  • From the datasheet, I see that they suggest to choose Ckbm = 10 * Cosc (section "Typical applications" in http://web.mit.edu/6.115/www/document/d74c922.pdf, page 7 and 8). However you dimension them as Ckbm = Cosc = 0.1µF. Which yields Fscan = 600Hz and a debounce time of only 1ms, which is shorter than the cycle time of Fscan. In my understanding the debounce time should be much longer than the scan time. Did you check the output of the 74C922 with a scope / logic analyzer? – Adrian W Jun 30 '18 at 18:45
  • I tried changing ckbm to 10uF following the equation ckbm=10*cos(c). I also check the outputs with a scope and since my interrupt was set into rising edge I looked at the first rising edge of the scope and saw that the DA rises first then the outputs. However it looks like in my case it would be better if the outputs trigger first then DA. I only used the simulators Osci, so i cant really get very accurate readings – JezT Jul 01 '18 at 08:10
  • i tried connecting one output pin to interrupt and viola it works! problem is since i connected the 1st bit of the output only outputs that uses the lsb works but now i know its not a code problem but a hardware one. Perhaps I can alter my code to compensate for the difference in the late output since i cant change my circuit for it is a requirement that the circuit stays the same. since our professor did it. also i was mistaken in the capacitor part ckbm should be 0.1uf and c is 0.01uf – JezT Jul 01 '18 at 08:31
  • By the way, in your interrupt routine missing "Context Saving" part! Check datasheet 6.9 "Context Saving During Interrupts". – GJ. Jul 01 '18 at 09:27

3 Answers3

1

Your Interruptroutine looks a little bit crazy. Try someting like:

; 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 

Please have a look for more details in the datasheet, there are some examples

Mike
  • 4,041
  • 6
  • 20
  • 37
1

Returning from a interrupt with GOTO isnt wise man. When u get in the interrupt it send the location where it was to stack and when u return with goto PC doesnt use that lvl of stack and direcly jump to GOTO marked Label.

Can u try

RETFIE

instead of

BCF INTCON, INTF
BSF INTCON, GIE
GOTO CDOWN

let me know if there is any change

  • I did and still it yields the same result. However i have found the answer, instead of adding the values in each bit. I used swap and got the values on the high nibble and sent it to wreg and used refie. Now the system works :) – JezT Jul 03 '18 at 10:13
0

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

JezT
  • 57
  • 8