Interrupt on change problem

Discussion in 'Embedded Systems and Microcontrollers' started by Peytonator, Sep 28, 2009.

  1. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    Hi there,

    Using the PIC16F690, I am having a problem with the following interrupt code which should toggle RC0 upon a button press:

    Code ( (Unknown Language)):
    1. org 0x04
    2. ;    Dobounce the switch by adding ~5ms delay
    3.     movlw    .255
    4.     movwf    Count1
    5.     movlw    .7
    6.     movwf    Count2    
    7. Loop:
    8.     decfsz    Count1, f
    9.     goto    Loop
    10.     decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    11.     goto    Loop
    12.  
    13. ;    clear flag and check for double interrupts
    14.     movlw    0x00
    15.     movf    PORTA, w             ; read PORTA to w (end mismatch condition)
    16.     bcf        INTCON, RABIF    ; clear flag
    17.     btfsc    PORTA, 3             ; Check for double interrupt (i.e. button released)
    18.     retfie
    19.  
    20. ;    toggle port and set return/retfie
    21.     movlw    b'00000001'
    22.     xorwf    PORTC, f        ; toggle the LED
    23.     btfsc    PORTC, 0        ; alternate between retfie and return (to test WDT)
    24.     retfie
    25.     return
    It interrupts fine, but using the stimulus tool, when I get to line

    Code ( (Unknown Language)):
    1.     movf    PORTA, w        ; read PORTA to w (end mismatch condition)
    I see that 1111 is moved into wreg (even though PORTA was clear!) and the flag is not cleared thereafter.

    Please could you help?
     
    Last edited: Sep 28, 2009
  2. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi,
    I am not understanding your Code. Please give your whole program, so that help can be provided to you. This should not be a difficult program,I think. Hope to help you.Thanks.
     
    Last edited: Sep 29, 2009
  3. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    Ok, here is all the code. The code is meant to interrupt when the button on RA3 is pressed and toggle an LED on RC0. Every second button press it must return, not retfie (don't worry why).

    Code ( (Unknown Language)):
    1. #include<p16f690.inc>
    2.  
    3. INT_VAR    UDATA_SHR
    4.  
    5. Display        RES 1
    6. Count1         RES 1
    7. Count2        RES 1
    8.  
    9. org 0x00
    10.     goto init
    11.  
    12. ;=======================================================
    13. ;                    Interrupt on Change
    14. ;=======================================================
    15. org 0x04
    16. ;    Dobounce the switch by adding ~5ms delay
    17.     movlw    .255
    18.     movwf    Count1
    19.     movlw    .7
    20.     movwf    Count2    
    21. Loop:
    22.     decfsz    Count1, f
    23.     goto    Loop
    24.     decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    25.     goto    Loop
    26.  
    27. ;    clear flag and check for double interrupts
    28.     movlw    0x00
    29.     movf    PORTA, w        ; read PORTA to w (end mismatch condition)
    30.     bcf        INTCON, RABIF    ; clear flag
    31.     btfsc    PORTA, 3        ; Check for double interrupt (i.e. button released)
    32.     retfie
    33.  
    34. ;    toggle port and return/retfie
    35.     movlw    b'00000001'
    36.     xorwf    PORTC, f        ; toggle the LED
    37.     btfsc    PORTC, 0        ; alternate between retfie and return
    38.     retfie
    39.     return
    40.  
    41. ;=======================================================
    42. ;                    Initialisation
    43. ;=======================================================
    44. init:
    45.     ;--set up PORTS--
    46.     banksel TRISC
    47.     clrf TRISC                ; PORTC output
    48.     movlw 0xFF
    49.     movwf TRISA                ; PORTA input
    50.     banksel    ANSEL
    51.     movlw 0x00
    52.     movwf ANSEL                ; Change to digital I/O
    53.     movwf ANSELH
    54.  
    55.     banksel    PORTC
    56.     clrf    Display
    57.     clrf    PORTC            ; clear RC0
    58.    
    59.     ;--interrupts--
    60. ;    bsf     INTCON, PEIE        ; Enables all unmasked peripheral interrupts (bit 6)
    61.     bsf     INTCON, GIE            ; Enables all unmasked interrupts (bit 7)
    62.     bsf        INTCON, RABIE        ; Enables the PORTA/PORTB change interrupt
    63.     banksel    IOCA
    64.     bsf        IOCA, 3                ; Enble interrupt-on-change on RA3
    65.  
    66.  
    67. ;=====================================================
    68. ;                    Main Loop
    69. ;=====================================================
    70.  
    71. Main:
    72.     nop
    73.     goto Main
    74.    
    75.     END
    Thanks :)
     
  4. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    But I do worry why!

    Returning from an interrupt with with a 'return' will disable all further interrupts unless you re-enable global interrupts somewhere else in your main routine, which you don't appear to be doing.
     
  5. munawar2050

    New Member

    Sep 30, 2009
    1
    0
    hello dear friends i m new member on the site so please guide me better
     
  6. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    My new code (without the retfie/return business) is:

    Code ( (Unknown Language)):
    1. #include<p16f690.inc>
    2.  
    3. INT_VAR    UDATA_SHR
    4. Display        RES 1
    5. Count1         RES 1
    6. Count2        RES 1
    7. Shadow        RES 1
    8.  
    9. org 0x00
    10.     goto init
    11.  
    12. ;=======================================================
    13. ;                    Interrupt on Change
    14. ;=======================================================
    15. org 0x04
    16. ;    Dobounce the switch by adding ~5ms delay
    17.     movlw    .255
    18.     movwf    Count1
    19.     movlw    .7
    20.     movwf    Count2    
    21. Loop:
    22.     decfsz    Count1, f
    23.     goto    Loop
    24.     decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    25.     goto    Loop
    26.  
    27. ;    clear flag and check for double interrupts
    28.     banksel    PORTA
    29.     movf    PORTA, w        ; read PORTA to w (end mismatch condition)
    30.     banksel    INTCON
    31.     bcf        INTCON, RABIF    ; clear flag
    32.     btfsc    PORTA, 3        ; Check for double interrupt (i.e. button released)
    33.     retfie
    34.  
    35. ;    toggle port and return/retfie
    36.     movf    PORTC, w
    37.     movwf    Shadow
    38.     movlw     0x01
    39.     xorwf     Shadow, f        ; toggle the LED
    40.     movf     Shadow, w
    41.     banksel    PORTC
    42.     movwf    PORTC
    43. ;    btfsc    PORTC, 0        ; alternate between retfie and return
    44. ;    retfie
    45.     retfie
    46.  
    47. ;=======================================================
    48. ;                    Initialisation
    49. ;=======================================================
    50. init:
    51.     ;--set up PORTS--
    52.     banksel TRISC
    53.     clrf     TRISC                ; PORTC output
    54.     movlw     0xFF
    55.     banksel    TRISA
    56.     movwf     TRISA                ; PORTA input
    57.     banksel    ANSEL
    58.     movlw     0x00
    59.     movwf     ANSEL                ; Change to digital I/O
    60.  
    61.     banksel    PORTC
    62.     clrf    PORTC            ; clear RC0
    63.     clrf    Shadow
    64.    
    65.     ;--interrupts--
    66. ;    bsf     INTCON, PEIE        ; Enables all unmasked peripheral interrupts (bit 6)
    67.     bsf     INTCON, GIE            ; Enables all unmasked interrupts (bit 7)
    68.     bsf        INTCON, RABIE        ; Enables the PORTA/PORTB change interrupt
    69.     banksel    IOCA
    70.     bsf        IOCA, 3                ; Enble interrupt-on-change on RA3
    71.  
    72.  
    73. ;=====================================================
    74. ;                    Main Loop
    75. ;=====================================================
    76.  
    77. Main:
    78.     nop
    79.     goto Main
    80.    
    81.     END
    I checked pin RA3 with a multimeter - I get a high when the button is not pressed and a low when pressed. Thus I check for a "double interrupt" when RA3 goes high again after releasing the button.

    Yet, the LED still doesn't toggle :confused: and I'm totally stuck.
     
    Last edited: Sep 30, 2009
  7. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Is port RA3 set up as an I/O port or is it still acting as a MCLR pin?
    I see nothing in your code to set up the configuration bits to make RA3 an ordinary I/O port.
     
  8. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    It's in the initialisation:

    Code ( (Unknown Language)):
    1.     banksel    ANSEL
    2.     movlw     0x00
    3.     movwf     ANSEL                ; Change to digital I/O
     
  9. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi Peytonator,
    What Language and what compiler have you used? I am not acquainted with this type of Language. You have not given Configuration Bit settings, Not declared Variables used in the Program. I don't understand your program. The Aim of your Code is to Interrupt on change with a Button. That is a very easy program and if you want I can make a fresh program for you as it seems very difficult for me to understand your Language/Code.
     
  10. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    Hi Tahmid,

    Yes, I would be interested to see your version of the program. Could you do that please?

    I am using normal assembly language and the MPLAB IDE.
     
  11. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    That sets portA as a digital port but you still have to set up the config bits to turn RA3 into a general I/O pin line rather than a reset pin (which is its default state).

    While you are about it you may as well do things such as select the oscillator type, disable the watchdog timer etc.

    Something like
    Code ( (Unknown Language)):
    1.  __config _HS_OSC & _WDT_OFF & _MCLRE_OFF
    2.  
     
  12. Peytonator

    Thread Starter Active Member

    Jun 30, 2008
    105
    3
    Yayyyyy! Thanks Alex :) At last it works!
     
  13. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi,
    Good that with the help of AlexR your code works. From your post, I also learned new way of declaration of Variables in MPLAB. Usually we used to declare Variables in old fashion with CBlock declaration. Thanks.
     
Loading...