Interrupt on change problem

Thread Starter

Peytonator

Joined Jun 30, 2008
105
Hi there,

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

Rich (BB code):
org 0x04
;    Dobounce the switch by adding ~5ms delay
    movlw    .255
    movwf    Count1
    movlw    .7
    movwf    Count2    
Loop:
    decfsz    Count1, f
    goto    Loop
    decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    goto    Loop

;    clear flag and check for double interrupts
    movlw    0x00
    movf    PORTA, w             ; read PORTA to w (end mismatch condition)
    bcf        INTCON, RABIF    ; clear flag
    btfsc    PORTA, 3             ; Check for double interrupt (i.e. button released)
    retfie

;    toggle port and set return/retfie
    movlw    b'00000001'
    xorwf    PORTC, f        ; toggle the LED
    btfsc    PORTC, 0        ; alternate between retfie and return (to test WDT)
    retfie
    return
It interrupts fine, but using the stimulus tool, when I get to line

Rich (BB code):
    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:

Tahmid

Joined Jul 2, 2008
343
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:

Thread Starter

Peytonator

Joined Jun 30, 2008
105
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).

Rich (BB code):
#include<p16f690.inc>

INT_VAR    UDATA_SHR

Display        RES 1
Count1         RES 1
Count2        RES 1

org 0x00
    goto init

;=======================================================
;                    Interrupt on Change
;=======================================================
org 0x04
;    Dobounce the switch by adding ~5ms delay
    movlw    .255
    movwf    Count1
    movlw    .7
    movwf    Count2    
Loop:
    decfsz    Count1, f
    goto    Loop
    decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    goto    Loop

;    clear flag and check for double interrupts
    movlw    0x00
    movf    PORTA, w        ; read PORTA to w (end mismatch condition)
    bcf        INTCON, RABIF    ; clear flag
    btfsc    PORTA, 3        ; Check for double interrupt (i.e. button released)
    retfie

;    toggle port and return/retfie
    movlw    b'00000001'
    xorwf    PORTC, f        ; toggle the LED
    btfsc    PORTC, 0        ; alternate between retfie and return
    retfie
    return

;=======================================================
;                    Initialisation
;=======================================================
init:
    ;--set up PORTS--
    banksel TRISC
    clrf TRISC                ; PORTC output
    movlw 0xFF
    movwf TRISA                ; PORTA input
    banksel    ANSEL
    movlw 0x00
    movwf ANSEL                ; Change to digital I/O
    movwf ANSELH

    banksel    PORTC
    clrf    Display
    clrf    PORTC            ; clear RC0
    
    ;--interrupts--
;    bsf     INTCON, PEIE        ; Enables all unmasked peripheral interrupts (bit 6)
    bsf     INTCON, GIE            ; Enables all unmasked interrupts (bit 7)
    bsf        INTCON, RABIE        ; Enables the PORTA/PORTB change interrupt
    banksel    IOCA
    bsf        IOCA, 3                ; Enble interrupt-on-change on RA3


;=====================================================
;                    Main Loop
;=====================================================

Main:
    nop
    goto Main
    
    END
Thanks :)
 

AlexR

Joined Jan 16, 2008
732
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).

Thanks :)
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.
 

Thread Starter

Peytonator

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

Rich (BB code):
#include<p16f690.inc>

INT_VAR    UDATA_SHR
Display        RES 1
Count1         RES 1
Count2        RES 1
Shadow        RES 1

org 0x00
    goto init

;=======================================================
;                    Interrupt on Change
;=======================================================
org 0x04
;    Dobounce the switch by adding ~5ms delay
    movlw    .255
    movwf    Count1
    movlw    .7
    movwf    Count2    
Loop:
    decfsz    Count1, f
    goto    Loop
    decfsz    Count2, f        ; outer loop 7 times (~5.5 ms)
    goto    Loop

;    clear flag and check for double interrupts
    banksel    PORTA
    movf    PORTA, w        ; read PORTA to w (end mismatch condition)
    banksel    INTCON
    bcf        INTCON, RABIF    ; clear flag
    btfsc    PORTA, 3        ; Check for double interrupt (i.e. button released)
    retfie

;    toggle port and return/retfie
    movf    PORTC, w
    movwf    Shadow
    movlw     0x01
    xorwf     Shadow, f        ; toggle the LED
    movf     Shadow, w
    banksel    PORTC
    movwf    PORTC
;    btfsc    PORTC, 0        ; alternate between retfie and return
;    retfie
    retfie

;=======================================================
;                    Initialisation
;=======================================================
init:
    ;--set up PORTS--
    banksel TRISC
    clrf     TRISC                ; PORTC output
    movlw     0xFF
    banksel    TRISA
    movwf     TRISA                ; PORTA input
    banksel    ANSEL
    movlw     0x00
    movwf     ANSEL                ; Change to digital I/O

    banksel    PORTC
    clrf    PORTC            ; clear RC0
    clrf    Shadow
    
    ;--interrupts--
;    bsf     INTCON, PEIE        ; Enables all unmasked peripheral interrupts (bit 6)
    bsf     INTCON, GIE            ; Enables all unmasked interrupts (bit 7)
    bsf        INTCON, RABIE        ; Enables the PORTA/PORTB change interrupt
    banksel    IOCA
    bsf        IOCA, 3                ; Enble interrupt-on-change on RA3


;=====================================================
;                    Main Loop
;=====================================================

Main:
    nop
    goto Main
    
    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:

AlexR

Joined Jan 16, 2008
732
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.
 

Tahmid

Joined Jul 2, 2008
343
INT_VAR UDATA_SHR
Display RES 1
Count1 RES 1
Count2 RES 1
Shadow RES 1
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.
 

Thread Starter

Peytonator

Joined Jun 30, 2008
105
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.
 

AlexR

Joined Jan 16, 2008
732
It's in the initialisation:

Rich (BB code):
    banksel    ANSEL
    movlw     0x00
    movwf     ANSEL                ; Change to digital I/O
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
Rich (BB code):
 __config _HS_OSC & _WDT_OFF & _MCLRE_OFF
 

Tahmid

Joined Jul 2, 2008
343
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.
 
Top