2
\$\begingroup\$

I am using PIC18F26K83 and I want to use interrupts for a switch that will be connected to one of the pins of my PIC. So I have some related questions:

  1. There are 2 interrupt options in PIC18F26K83: IOC vs INT. What is the difference? I heard that is quite easy to miss edges with IOC though. Can I use both of them at the same time?
  2. Other question is related to interrupt function. If I have 2 interrupt functions : interrupt i1(void) and interrupt i2(void), in case of any interrupt, does the software enters all the interrupts one by one? If not how does it get which function is related to coming interrupt? For example I am using CANBus interrupt, I2C interrupt, timer interrupt and one external interrupt coming from a switch. If I press the switch, how will software know which interrupt function is related to switch? Thanks beforehand.
\$\endgroup\$
  • 2
    \$\begingroup\$ I don't really understand why the bouncing time is related to the human factor, maybe you need to rethink it a bit, or maybe it works in your application. The problem with switch bounce is that you will get maybe 6 key presses when the user presses the key once. \$\endgroup\$ – pipe Apr 15 at 12:29
  • \$\begingroup\$ Ah yes I thought that if user presses the switch twice in this bouncing time it will not recognise the second press. I am going to fix this part. You are completely right. \$\endgroup\$ – Günkut Ağabeyoğlu Apr 15 at 12:31
  • 1
    \$\begingroup\$ Interrupts are best reserved for servicing events that must be attended to very promptly (nanoseconds to microseconds). If it’s a manual pushbutton and you have milliseconds, polling via a periodic interrupt is usually a much better way to go. \$\endgroup\$ – Spehro Pefhany Apr 15 at 12:38
4
\$\begingroup\$

There is an interrupt flag associated with the interrupt you choose to use. That will tell you which pin was responsible when you service the interrupt (it is set automatically by the pin change). You will reset it in your ISR. That ensures you won't miss an pin change interrupt if your ISR is properly written.

But if the switch is bouncing you'll get additional interrupts when the interrupts have been re-enabled. Maybe sometimes, maybe not other times depending on what the processor is doing. Maybe you'll reset the flag and it will immediately be set again by the hardware before you even exit the ISR, then the interrupt will occur immediately when you exit. You could put a (blocking) delay routine in your ISR but I think most real-time programming folks would be nauseous or possibly physically ill by that point.

Generally manual switches should not be serviced by interrupt routines. Institute a periodic interrupt (typically no faster than 1kHz, and maybe a bit slower depending on the switch- you can also check every n'th time through with a 1kHz interrupt) and you can check and debounce the switch input by polling. You would have the current state of the switch, the previous state and the previous stable state. If you have two readings the same (in a row) that differ from the previous stable state you know you have an edge, and you can discard the polarity of edge you're not interested in (say the release of the switch).

\$\endgroup\$
  • \$\begingroup\$ Do I need to store previous values for the switch? I can set the timer interrupt and check if the related pin is 0 and 1. What is the point of storing the previous state? \$\endgroup\$ – Günkut Ağabeyoğlu Apr 15 at 13:18
  • 1
    \$\begingroup\$ The purpose of storing the previous state is debouncing. The purpose of storing the previous stable state is edge detection. You may not need to do this in certain specific cases, but it does not harm and if you need a chunk of code that executes exactly once per switch press (and maybe another chunk that executes on release) this is a workable approach. The periodic interrupt also lends itself to timing switch presses etc. which may be useful in more complex situations. \$\endgroup\$ – Spehro Pefhany Apr 15 at 13:45
  • \$\begingroup\$ But how will it do debouncing? Let's say I am storing previous state. How will I do debouncing without a timer interrupt? \$\endgroup\$ – Günkut Ağabeyoğlu Apr 15 at 13:52
  • \$\begingroup\$ Periodic interrupt = timer interrupt . \$\endgroup\$ – Spehro Pefhany Apr 15 at 14:14
2
\$\begingroup\$
  1. According to Datasheet some of Pins can be configured for both types of interrupts - it is your choice.

  2. When you will compile your code in it's output data will be a portion of data called an Interrupt Vector Table where are store what function to call for which interrupt.
    Processor will carry out the priority and sequence of execution of Interrupt Service Routines.

Update

I have just installed MPLAB X IDE and there are embedded examples for PIC18 processors with interrupt.c file:

/* High-priority service */

#if defined(__XC) || defined(HI_TECH_C)
void interrupt high_isr(void)
#elif defined (__18CXX)
#pragma code high_isr=0x08
#pragma interrupt high_isr
void high_isr(void)
#else
#error "Invalid compiler selection for implemented ISR routines"
#endif

{

      /* This code stub shows general interrupt handling.  Note that these
      conditional statements are not handled within 3 seperate if blocks.
      Do not use a seperate if block for each interrupt flag to avoid run
      time errors. */

#if 0

      /* TODO Add High Priority interrupt routine code here. */

      /* Determine which flag generated the interrupt */
      if(<Interrupt Flag 1>)
      {
          <Interrupt Flag 1=0>; /* Clear Interrupt Flag 1 */
      }
      else if (<Interrupt Flag 2>)
      {
          <Interrupt Flag 2=0>; /* Clear Interrupt Flag 2 */
      }
      else
      {
          /* Unhandled interrupts */
      }

#endif

}
\$\endgroup\$
  • \$\begingroup\$ For the 2. part, by using interrupt vector table I can assign interrupts to high or low priority. What I wonder is, can I assign an interrupt function to specific interrupt, if yes how will I do that? Does the software do it by itself? \$\endgroup\$ – Günkut Ağabeyoğlu Apr 15 at 12:58
  • \$\begingroup\$ I don't know what tolls you will use, but in Arduino Environment there are exist special function attachInterrupt. You must call it once at program start. \$\endgroup\$ – Alexander Apr 15 at 13:13
  • \$\begingroup\$ You can add a vector interrupt function to TMR0 for example with the following code void __interrupt(irq(TMR0), base(0x4008)) TMR0_ISR(void) { /* code in here */ } \$\endgroup\$ – pm101 Apr 25 at 9:26
0
\$\begingroup\$

The PIC 18 has just two interrupt vectors, one for high and one for low priority interrupts. You had to assign the correct interrupt by your own in software.

e.g.

void interrupt tc_int(void)             // High priority interrupt
{
    if (TMR1IE && TMR1IF)
    {
        TMR1IF=0;
        ++tick_count;
        TRISC=1;
        LATCbits.LATC4 = 0x01;
    }
}

void interrupt low_priority   LowIsr(void)    //Low priority interrupt
{
    if(INTCONbits.T0IF && INTCONbits.T0IE)  // If Timer flag is set & Interrupt is enabled
    {                               
        TMR0 -= 250;                    // Reload the timer - 250uS per interrupt
        INTCONbits.T0IF = 0;            // Clear the interrupt flag 
        ADCON1=0x0F;
        TRISB=0x0CF;
        LATBbits.LATB5 = 0x01;          // Toggle a bit 
    }
    if (TMR1IE && TMR1IF)
    {
        TMR1IF=0;
        ++tick_count;
        TRISC=0;
        LATCbits.LATC3 = 0x01;
    }
}

That's different compared to the greater PIC24 which has one vector for each interrupt.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.