Change On Interrupt, PIC16F884


Closed Thread
Results 1 to 18 of 18

Hybrid View

  1. #1
    Join Date
    Apr 2005
    Location
    Virginia
    Posts
    65


    Did you find this post helpful? Yes | No

    Default Solved!



    Bruce,

    Thank you! I completely forgot about bank switching! Here is the revised code if it helps anyone. I assume I don't need to worry about bank switching for the config settings.

    INCLUDE "modedefs.bas"
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low

    asm ; The following code is assembly, not Basic
    __CONFIG _CONFIG1, _INTOSCIO & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
    ; Use internal oscillator & make both, OSC pins I/Os, turn off watchdog timer, enable Power-up timer,
    ; code protection off, brown-out off, disable switch over mode, turn off failsafe monitor,
    ; low voltage programming off
    endasm ' End assembly code

    ADCON0.0 = 0 ; Make all analog pins digital I/Os
    CM1CON0.7 = 0 ; Disable comparator C1
    CM2CON0.7 = 0 ; Disable comparator C2
    OSCCON.6 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.5 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.4 = 1 ; Set the internal oscillator to 8MHz
    WDTCON.0 = 0 ; Disable the watchdog timer
    ANSEL = %00000000 ; Set all analog pins on port a to digital I/O
    ANSELH = %00000000 ; Set all analog pins on port b to digital I/O

    define OSC 8 ' Tell the program the oscillator is running at 8 MHz
    TRISA = %00000000 ' Make all port a pins outputs
    TRISB = %00001111 ' Make port b pins 0-3 inputs and the rest as outputs
    TRISC = %00000000 ' Make all port c pins outputs
    TRISD = %00000000 ' Make all port d pins outputs
    TRISE = %00000000 ' Make all port e pins outputs
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low
    'Variables**************************************** ************************************************** *
    b0 VAR byte ' Required byte variable for toggle button
    '************************************************* ************************************************** *
    INITIALIZE: ' Initialize Routine
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    On Interrupt goto Halt ' Once an active interrupt port is enabled, go to the Halt routine
    INTCON.7 = 1 ' Enable global interrupts
    IOCB = %00000001 ' Enable interrupt-on-change on RB0-RB3
    INTCON.3 = 1 ' Enable interrupt-on-change on Port b
    GOTO MAIN ' Go to Main routine
    '************************************************* ************************************************** *
    MAIN:
    ' PORTB = $00 ' Set all port b pins to low
    b0 = PORTB ' temp is some variable
    HIGH PORTE.0
    PAUSE 500
    LOW PORTE.0
    PAUSE 500
    GOTO MAIN
    '************************************************* ************************************************** ***
    DISABLE ' Disable all interrupts
    Halt: ' Halt Routine
    HIGH PORTE.1
    LOW PORTE.0
    b0 = PORTB ' temp is some variable
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    RESUME Done ' Go to Main routine
    ENABLE ' Enable all active interrupts
    '************************************************* ************************************************** ***
    Done:

    END

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    This can cause a lot of headaches sometimes due to read-modify-write;

    HIGH PORTE.1 ' reads whole port, flips this bit, writes whole port
    LOW PORTE.0 ' same, but if RE1 isn't high yet, RE1 is read & writen back as 0

    Try just toggling the LED on RE1 to verify that you're entering the interrupt routine.

    Another potential show-stopper is directing RESUME to Done, which halts everything.

    Try something like this;
    Code:
    INITIALIZE:  ' Initialize Routine
        IOCB = %00000001   ' Enable interrupt-on-change on RB0
        INTCON = %10001000 ' Global & interrupt-on-change on Port b enabled
    '************************************************* 
    On Interrupt goto Halt ' on interrupt go to the Halt routine
    
    MAIN:
        HIGH PORTE.0
        PAUSE 500
        LOW PORTE.0
        PAUSE 500
        GOTO MAIN
    '************************************************* 
        DISABLE       ' do NOT place interrupt checking code below
    Halt:             ' Halt Routine
        WHILE PORTB.0=0 ' wait for button release & end mismatch condition on portb 
        WEND          
        TOGGLE PORTE.1
        INTCON.0 = 0  ' Clear the interrupt-on-change flag
        RESUME        ' Go to Main routine
        ENABLE        ' Enable all active interrupts
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    Join Date
    Apr 2005
    Location
    Virginia
    Posts
    65


    Did you find this post helpful? Yes | No

    Default

    Bruce,

    Thank you. It acts a little flaky, e.g., sometimes the LED on porte.1 would stay on two consecutive button presses or off, due to debounce. I looked at some other threads and found a 50ms pause. Here is the code again with the debounce which is working like a charm. Thank you for your help.

    INCLUDE "modedefs.bas"
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low

    asm ; The following code is assembly, not Basic
    __CONFIG _CONFIG1, _INTOSCIO & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
    ; Use internal oscillator & make both, OSC pins I/Os, turn off watchdog timer, enable Power-up timer,
    ; code protection off, brown-out off, disable switch over mode, turn off failsafe monitor,
    ; low voltage programming off
    endasm ' End assembly code

    ADCON0.0 = 0 ; Make all analog pins digital I/Os
    CM1CON0.7 = 0 ; Disable comparator C1
    CM2CON0.7 = 0 ; Disable comparator C2
    OSCCON.6 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.5 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.4 = 1 ; Set the internal oscillator to 8MHz
    WDTCON.0 = 0 ; Disable the watchdog timer
    ANSEL = %00000000 ; Set all analog pins on port a to digital I/O
    ANSELH = %00000000 ; Set all analog pins on port b to digital I/O

    define OSC 8 ' Tell the program the oscillator is running at 8 MHz
    TRISA = %00000000 ' Make all port a pins outputs
    TRISB = %00001111 ' Make port b pins 0-3 inputs and the rest as outputs
    TRISC = %00000000 ' Make all port c pins outputs
    TRISD = %00000000 ' Make all port d pins outputs
    TRISE = %00000000 ' Make all port e pins outputs
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low
    'Variables**************************************** ************************************************** *
    b0 VAR byte ' Required byte variable for toggle button
    '************************************************* ************************************************** *
    INITIALIZE: ' Initialize Routine
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    On Interrupt goto Halt ' Once an active interrupt port is enabled, go to the Halt routine
    INTCON = %10001000 ' Enable global interrupts, Enable interrupt-on-change on Port b
    IOCB = %00000001 ' Enable interrupt-on-change on RB0-RB3
    PORTE.1 = 0 ' Make sure LED on PORTE.1 is off
    GOTO MAIN ' Go to Main routine
    '************************************************* ************************************************** *
    MAIN:
    HIGH PORTE.0
    PAUSE 500
    LOW PORTE.0
    PAUSE 500
    GOTO MAIN
    '*************************************************
    DISABLE ' do NOT place interrupt checking code below
    Halt: ' Halt Routine
    WHILE PORTB.0=0 ' wait for button release & end mismatch condition on portb
    WEND
    PAUSE 50 ' Debounce delay
    TOGGLE PORTE.1 ' Toggle LED on PORTE.1
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    RESUME ' Go to Main routine
    ENABLE ' Enable all active interrupts

  4. #4
    Join Date
    Apr 2005
    Location
    Virginia
    Posts
    65


    Did you find this post helpful? Yes | No

    Default Detecting Multiple Switches with Interrupt-On-Change

    One more question: How about detecting multiple switches with interrupt-on-change? I've tried the modified code below as well as the commented out code on its own. This works, but not reliably. I'm using those momentary red square switches from RadioShack and the LEDs only change about half the time, i.e., the program isn't detecting the button press. I've tried pressing the switches hard (fully down) quickly, but with the same hit rate of half. If I press and hold each button for a second or two, it works fine, but I don't want to force the user to press and hold a switch to do something. I tried playing with the debounce times and even adding a ceramic capacitor, 0.1uF and 0.01uF across the switch contacts with no luck. I tried searching the forum, but the only interrupt examples I've come across are for single button applications. Any suggestions?

    INCLUDE "modedefs.bas"
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low

    asm ; The following code is assembly, not Basic
    __CONFIG _CONFIG1, _INTOSCIO & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
    ; Use internal oscillator & make both, OSC pins I/Os, turn off watchdog timer, enable Power-up timer,
    ; code protection off, brown-out off, disable switch over mode, turn off failsafe monitor,
    ; low voltage programming off
    endasm ' End assembly code

    ADCON0.0 = 0 ; Make all analog pins digital I/Os
    CM1CON0.7 = 0 ; Disable comparator C1
    CM2CON0.7 = 0 ; Disable comparator C2
    OSCCON.6 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.5 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.4 = 1 ; Set the internal oscillator to 8MHz
    WDTCON.0 = 0 ; Disable the watchdog timer
    ANSEL = %00000000 ; Set all analog pins on port a to digital I/O
    ANSELH = %00000000 ; Set all analog pins on port b to digital I/O

    define OSC 8 ' Tell the program the oscillator is running at 8 MHz
    TRISA = %00000000 ' Make all port a pins outputs
    TRISB = %00001111 ' Make port b pins 0-3 inputs and the rest as outputs
    TRISC = %00000000 ' Make all port c pins outputs
    TRISD = %00000000 ' Make all port d pins outputs
    TRISE = %00000000 ' Make all port e pins outputs
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low
    'Variables**************************************** ************************************************** *
    b0 VAR byte ' Required byte variable for toggle button
    '************************************************* ************************************************** *
    INITIALIZE: ' Initialize Routine
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    On Interrupt goto Halt ' Once an active interrupt port is enabled, go to the Halt routine
    INTCON = %10001000 ' Enable global interrupts, Enable interrupt-on-change on Port b
    IOCB = %00000011 ' Enable interrupt-on-change on RB0-RB3
    PORTE.1 = 0 ' Make sure LED on PORTE.1 is off
    PORTE.2 = 0 ' Make sure LED on PORTE.2 is off
    GOTO MAIN ' Go to Main routine
    '************************************************* ************************************************** *
    MAIN:
    HIGH PORTE.0
    PAUSE 500
    LOW PORTE.0
    PAUSE 500
    GOTO MAIN
    '*************************************************
    DISABLE ' do NOT place interrupt checking code below
    Halt: ' Halt Routine
    IF PORTB.0 = 0 THEN
    WHILE PORTB.0=0 ' wait for button release & end mismatch condition on portb
    WEND
    PAUSE 20 ' Debounce delay
    HIGH PORTE.1
    LOW PORTE.2
    ENDIF
    IF PORTB.1 = 0 THEN
    WHILE PORTB.1=0 ' wait for button release & end mismatch condition on portb
    WEND
    PAUSE 20 ' Debounce delay
    LOW PORTE.1
    HIGH PORTE.2
    ENDIF

    ' IF PORTB.0 = 0 THEN
    ' ' PAUSE 20
    ' ' IF PORTB.0 = 0 THEN
    ' HIGH PORTE.1
    ' LOW PORTE.2
    ' ' ENDIF
    ' ENDIF
    '
    ' IF PORTB.1 = 0 THEN
    ' ' PAUSE 20
    ' ' IF PORTB.1 = 0 THEN
    ' LOW PORTE.1
    ' HIGH PORTE.2
    ' ' ENDIF
    ' ENDIF

    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    RESUME ' Go to Main routine
    ENABLE ' Enable all active interrupts

  5. #5
    Join Date
    Apr 2006
    Location
    New Hampshire USA
    Posts
    298


    Did you find this post helpful? Yes | No

    Smile Just an idea...

    Hi elec_mech,
    Posting code directly into the text portion of the forum makes it difficult to follow.
    Quote Originally Posted by Mister_e
    [code] paste your code here [/code]
    One step better but a lot more work:
    Quote Originally Posted by Darrel Taylor View Post
    Show us your Colors.
    Quote Originally Posted by elec_mech View Post
    define osc 8 ' tell the program the oscillator is running at 8 mhz
    Quote Originally Posted by PBP 2.50 manual
    4.16. DEFINE may be used to change the predefined oscillator value...
    These definitions must be in all upper case, exactly as shown.
    If not, the compiler may not recognize them.
    No error message will be produced for defines the compiler does not recognize.
    Code:
    DEFINE OSC 8
    -Adam-
    Last edited by Pic_User; - 13th November 2008 at 17:20. Reason: Changing formatting
    Ohm it's not just a good idea... it's the LAW !

  6. #6
    Join Date
    Apr 2005
    Location
    Virginia
    Posts
    65


    Did you find this post helpful? Yes | No

    Default

    Adam,

    I see what you mean with the DEFINE, oops! Thanks for the catch. I see what you mean with colors. Is this better?
    INCLUDE "modedefs.bas"
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low

    asm ; The following code is assembly, not Basic
    __CONFIG _CONFIG1, _INTOSCIO & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
    ; Use internal oscillator & make both, OSC pins I/Os, turn off watchdog timer, enable Power-up timer,
    ; code protection off, brown-out off, disable switch over mode, turn off failsafe monitor,
    ; low voltage programming off
    endasm ' End assembly code

    ADCON0.0 = 0 ; Make all analog pins digital I/Os
    CM1CON0.7 = 0 ; Disable comparator C1
    CM2CON0.7 = 0 ; Disable comparator C2
    OSCCON.6 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.5 = 1 ; Set the internal oscillator to 8MHz
    OSCCON.4 = 1 ; Set the internal oscillator to 8MHz
    WDTCON.0 = 0 ; Disable the watchdog timer
    ANSEL = %00000000 ; Set all analog pins on port a to digital I/O
    ANSELH = %00000000 ; Set all analog pins on port b to digital I/O

    DEFINE OSC 8 ' Tell the program the oscillator is running at 8 MHz
    TRISA = %00000000 ' Make all port a pins outputs
    TRISB = %00001111 ' Make port b pins 0-3 inputs and the rest as outputs
    TRISC = %00000000 ' Make all port c pins outputs
    TRISD = %00000000 ' Make all port d pins outputs
    TRISE = %00000000 ' Make all port e pins outputs
    PORTA = $00 ' Set all port a pins to low
    PORTB = $00 ' Set all port b pins to low
    PORTC = $00 ' Set all port c pins to low
    PORTD = $00 ' Set all port d pins to low
    PORTE = $00 ' Set all port e pins to low
    'Variables**************************************** ************************************************** *
    b0 VAR byte ' Required byte variable for toggle button
    '************************************************* ************************************************** *
    INITIALIZE: ' Initialize Routine
    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    On Interrupt goto Halt ' Once an active interrupt port is enabled, go to the Halt routine
    INTCON = %10001000 ' Enable global interrupts, Enable interrupt-on-change on Port b
    IOCB = %00000011 ' Enable interrupt-on-change on RB0-RB3
    PORTE.1 = 0 ' Make sure LED on PORTE.1 is off
    PORTE.2 = 0 ' Make sure LED on PORTE.2 is off
    GOTO MAIN ' Go to Main routine
    '************************************************* ************************************************** *
    MAIN:
    HIGH PORTE.0
    PAUSE 500
    LOW PORTE.0
    PAUSE 500
    GOTO MAIN
    '*************************************************
    DISABLE ' do NOT place interrupt checking code below
    Halt: ' Halt Routine
    IF PORTB.0 = 0 THEN
    WHILE PORTB.0=0 ' wait for button release & end mismatch condition on portb
    WEND
    PAUSE 20 ' Debounce delay
    HIGH PORTE.1
    LOW PORTE.2
    ENDIF
    IF PORTB.1 = 0 THEN
    WHILE PORTB.1=0 ' wait for button release & end mismatch condition on portb
    WEND
    PAUSE 20 ' Debounce delay
    LOW PORTE.1
    HIGH PORTE.2
    ENDIF


    ' IF PORTB.0 = 0 THEN
    ' ' PAUSE 20
    ' ' IF PORTB.0 = 0 THEN
    ' HIGH PORTE.1
    ' LOW PORTE.2
    ' ' ENDIF
    ' ENDIF
    '
    ' IF PORTB.1 = 0 THEN
    ' ' PAUSE 20
    ' ' IF PORTB.1 = 0 THEN
    ' LOW PORTE.1
    ' HIGH PORTE.2
    ' ' ENDIF
    ' ENDIF

    INTCON.0 = 0 ' Clear the interrupt-on-change flag
    RESUME ' Go to Main routine
    ENABLE ' Enable all active interrupts

  7. #7
    Join Date
    Apr 2006
    Location
    New Hampshire USA
    Posts
    298


    Did you find this post helpful? Yes | No

    Thumbs up the real question

    Quote Originally Posted by elec_mech View Post
    Adam,
    I see what you mean with the DEFINE, oops! Thanks for the catch. I see what you mean with colors. Is this better?
    It is better! But the idea is to copy from your editor, paste into a code box. So the indents and formatting look more like the original. Sometimes the forum changes the formatting. I was not sure the lowercase define was in your original or being changed by the forum. It changes a lot of things “for you” I wish I knew more about PBP to really help you on your real question.
    -Adam-
    Ohm it's not just a good idea... it's the LAW !

Similar Threads

  1. A Simple IOC Routine (Interrupt On Change)
    By lugo.p in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 8th March 2010, 19:53
  2. Won't go back to SLEEP after 1st Interrupt
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 32
    Last Post: - 29th June 2009, 09:00
  3. Can't ID interrupt source with this IntHandler??
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 3rd June 2009, 02:35
  4. NEWBIE: Some basic questions using interrupts
    By JackPollack in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 8th March 2006, 02:59
  5. USART interrupt not interrupting right
    By Morpheus in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 6th March 2005, 01:07

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts