16F690 One interrupt 2 routines

Author
Laury
Junior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2012/08/27 20:15:19
  • Location: Nashville, TN
  • Status: offline
2013/01/28 20:03:32 (permalink)
0

16F690 One interrupt 2 routines

16F690, MPLAB 8.87,  Hi-Tech (PRO Mode)  V9.83
 
Hi all:
I've got a problem with 2 interrupt routines working together.
Each routine works perfectly individually. The first routine falls through
to the second routine and services it if it called the interrupt The second
routine will fall through to the end if it was the first routine that needed
attention. First routine toggles an LED, Second routine reads an encoder.
I have left off the main code for simplicity.
When I have the 2 routines together, It hangs. Is there a better
way to handle 2 interrupts?  Also am I ending the interrupt properly?
The data sheet mentions RETFIE but I'm not sure how to use it.
 
Any Help appreciated
RonL
 
Here's the routines:
 
/************************************************************************************/
/*                                                         Interrupt occurred. This is what happens next                                  */
/************************************************************************************/
  
void interrupt ISR_Handlers(void)        //One interrupt, 2 Routines
{
   
/*********************************Read switch & de-bounce, Toggle LED*********************/
   
    if (RB5 == 0)        //If switch not pressed code falls through to 2nd interrupt
    {
    pause(35);            // Pause for debounce
    }   
   
    if (RB5 ==0)        // Check if switch is still pressed
    {
    RC4 =(RC4 ^ 1);        // TOGGLE LED
    }
    while (RB5 == 0);    // Wait here until switch is released

/*************************************End first Interrupt **********************************/
   
   
/**********************************Second Interrupt starts here*****************************/
   
       
 ENC_NEW = PORTA;                         // Get new position & mask the results
 ENC_NEW = (ENC_NEW & 0b00110000);

 TEMP = ENC_NEW;                           // Copy new position to temp
(TEMP = (TEMP ^ ENC_OLD));
 
 if (TEMP != 0)                            // Compare new position with old 
{
   (TEMP = ENC_NEW);                          // Get new reading
   (TEMP = (TEMP >>1);                         // Shift right
   (TEMP = (TEMP ^ ENC_OLD));            // XOR again
   (TEMP = (TEMP & 0b00010000));       // Mask for RA4
      
 if (TEMP > 0)                            //Check rotation
 {
     COUNT --;                            //Encoder was CCW <---          
 }
 
 else
 {
      COUNT ++;                            //Encoder was CW --->
 }
 
 ENC_OLD = ENC_NEW;              //Update ENC_OLD for next time
 
 
 if (COUNT > 255)                        //Limit COUNT to < 255
 {
 (COUNT = 255);
 }
 
 if (COUNT < 0)                            //Limit COUNT to > 0
 {
 (COUNT = 0);
 }
 
    }     //end if
 
                    

    
 
    PORTA;                         //Read PORTS to end mismatch
    PORTB;                         //Read PORTS to end mismatch
    RABIF = 0;                    //Clear interrupt flag
                                        //Return frm interrupt
          
    }    //end isr   
#1

3 Replies Related Threads

    WaltR
    Super Member
    • Total Posts : 3759
    • Reward points : 0
    • Joined: 2003/11/07 12:38:21
    • Status: offline
    Re:16F690 One interrupt 2 routines 2013/01/28 20:31:31 (permalink)
    +2 (1)
    The C compiler uses a retfie to end the ISR so do not add it. It is only needed if the code is in assembler.
     
    Indent the code to show what is inside if statements will help you see the code flow.
    Also, try stepping through the ISR in the MPLAB Simulator, using the Stimulus for pin inputs. Then you'll see why it hangs on this line:
    while (RB5 == 0);    // Wait here until switch is released
     
    A typical ISR for PICs when test which interrupt trigger the ISR. For your 1st section (which I think is from an IOC, test whether the IOC is active. Then test for the PORTA interrupt.
    Also, be sure to test whether that interrupt is enabled. Example:
    if( RABIF && RABIE ) {
                    // IOC interrupt handler
    }
     
    Look through the forums and other code for more examples.
    post edited by WaltR - 2013/01/28 20:36:09
    #2
    Laury
    Junior Member
    • Total Posts : 95
    • Reward points : 0
    • Joined: 2012/08/27 20:15:19
    • Location: Nashville, TN
    • Status: offline
    Re:16F690 One interrupt 2 routines 2013/01/29 19:57:31 (permalink)
    0
    Thanks for the response Walt. I've been working with this most of today and now have it working.
    It seems that toggling the LED RC4 was causing the problem. I moved the LED to RB7 and it works
    perfectly. PORTC is being used by the LCD as 4 bit data. When it does an LCD_WRITE RC0<> RC3 it clears RC4.
    This corrupted the system.
    I found this out with the simulator.    Thanks for the suggestion!
    I'm not sure where to put the  "if( RABIF && RABIE )" ? Should it be at the start of my interrupt handler?
    My question on this is, If the was no IOC that happended, how did the PC (program counter) get there in the first place?
     
    Thanks for your valuable help
     
    RonL
     
    WaltR

    The C compiler uses a retfie to end the ISR so do not add it. It is only needed if the code is in assembler.

    Indent the code to show what is inside if statements will help you see the code flow.
    Also, try stepping through the ISR in the MPLAB Simulator, using the Stimulus for pin inputs. Then you'll see why it hangs on this line:
    while (RB5 == 0);    // Wait here until switch is released

    A typical ISR for PICs when test which interrupt trigger the ISR. For your 1st section (which I think is from an IOC, test whether the IOC is active. Then test for the PORTA interrupt.
    Also, be sure to test whether that interrupt is enabled. Example:
    if( RABIF && RABIE ) {
                   // IOC interrupt handler
    }

    Look through the forums and other code for more examples.


    #3
    WaltR
    Super Member
    • Total Posts : 3759
    • Reward points : 0
    • Joined: 2003/11/07 12:38:21
    • Status: offline
    Re:16F690 One interrupt 2 routines 2013/01/30 09:36:18 (permalink)
    0
    I'm not sure where to put the  "if( RABIF && RABIE )" ? Should it be at the start of my interrupt handler?
    My question on this is, If the was no IOC that happended, how did the PC (program counter) get there in the first place?

     
    Yes, the "if( RABIF && RABIE )" goes in the ISR after context saving (auto-generated by the C compiler) and encloses any handler for that interrupt.
     
    Due to the PIC having only one interrupt Vector the standard procedure is to always check which interrupt triggered. If there are not other interrupts active then this really isn't needed but its better to be sure.
    That if statement also ensure that the interrupt is actually enabled since if a different interrupt is the triggered the xxxIF bit can be set without the xxxIE enabled.
     
    Good you got this figured out with the Simulator. I get about 90% of code I write debugged with the Sim.
    #4
    Jump to:
    © 2017 APG vNext Commercial Version 4.5