Interrupts and ISRs in PIC18F2520 using microC

Discussion in 'Embedded Systems and Microcontrollers' started by pyridot, Jun 30, 2010.

  1. pyridot

    Thread Starter New Member

    Jun 11, 2010
    7
    0
    Hi Guys!

    I am extremely confused as to how interrupts and ISRs work. I have never worked with interrupts and have just begun with PICs. I am using microC for programming. The following questions may sound very lame, but please do help me out.

    1. interrupts are written like any other function. am I correct? or do they have to be in the function void interrupt()?

    2. checking of flags should be done in void interrupt()? and should this function be a part of main()? if yes then am i not wasting processing time?

    3. if i do check flag outside of main() but in interrupt()....how is this function invoked?

    4. how do i invoke handlers?

    5. I understand that there are many pre defined interrupts in PIR1 and 2. Can I have software interrupts too?

    If there is a tutorial on the same pls do share it with me. I havent been able to find one answering the above questions.

    Thanks in advance :)

    Regards,
    pyridot
     
  2. Vaughanabe13

    Active Member

    May 4, 2009
    102
    5
    1. An interrupt is written as any other function, and can have any name you give it. The only catch is you need to specifically tell the PIC how to load the program counter on the event of an interrupt. There are specific code locations in the PIC called "interrupt vectors" and when an interrupt occurs, the PC of the CPU will get loaded with the interrupt vector. So, you need one line of assembly after the interrupt vector that instructs the CPU to go to your interrupt service routing. Here is an example for the high-priority interrupt vector:

    Code ( (Unknown Language)):
    1. #pragma code highVector=0x08
    2. void atHighVector(void)
    3. {
    4.      _asm GOTO HiPriISR _endasm
    5. }
    6. #pragma code
    Then you would write your ISR like this:
    Code ( (Unknown Language)):
    1. #pragma interrupt HiPriISR      // High-priority interrupt service routine
    2. void HiPriISR(void)
    3. {
    4. }
    2. You should always check your interrupt flags inside the interrupt service routine. Your ISR should be a function that is NOT in main. This way it will never get executed unless an interrupt occurs

    3. To check an interrupt flag you do not need to call a function. Each interrupt has a specific flag bit associated with it in one of the special function registers. You simply poll this bit and if the bit is a "1" you know the interrupt was triggered, so you can execute code accordingly. For example, if you want an interrupt to trigger on a Timer0 overflow, the TMR0IF bit (Timer 0 interrupt flag) will be set in the INTCON register.

    4. Not sure what you mean. Generally you should not call external functions inside of your ISR. An ISR is meant to be very quick.

    5. There are many many kinds of interrupts, which could be triggered from internal events like an expired watchdog timer or a timer overflow, or they could be triggered from external events, such as a falling edge on pin RB0/INT0. Check your PIC's datasheet for specific info.
     
  3. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Interrupt handling is very much compiler specific. Each compiler has its own way of doing it and each compiler is different so read your compiler manual.
    The procedure outlined by Vaughanabe13 will most likely work for his compiler but it will not work for yours.

    For MicroC it seems that the interrupt ISR must be a function called interrupt(), it must not return any value (must be void) and it must not accept and parameters. In other words it must be "void interrupt(void);"
    Your compiler puts an instruction into the interrupt vector address (the address that the program goes to on interrupt) to call the interrupt() function.

    When an interrupt occurs the PIC turns off global interrupts and pushes the program counter onto the stack it then load the program counter with the value of the interrupt vector which in turn calls the interrupt() function.

    Most C compilers automatically save registers that may be altered in the interrupt routine on the stack and restore them when they exit the interrupt function but yet again check your manual to see what is and what isn't saved.

    In the interrupt function your first task is to determine what caused the interrupt by checking the interrupt flags. Then do whatever needs to be done. You can call other functions from inside the interrupt() function if you want but keep in mind that you should spend as little time as possible servicing the interrupt.

    Finally before you leave the interrupt() function you must clear the flag that caused the interrupt to occur. If you forget to do this you will jump straight back into the interrupt routine.

    Exiting the interrupt automatically re-enables interrupts, restores any saved registers and pulls the program counter off the stack so that the program takes up where it left off when the interrupt happened.

    PIC interrupts happen in response to hardware or peripheral changes of state (I/O pins changing state, timers overflowing, USART buffer state etc) but unlike many microprocessors they do not have any means to initiate a software interrupt.

    The links below give a fairly good tutorial on interrupts. It covers it using assembler but that is not too bad as it give you an insight into what goes on inside the PIC during an interrupt. Also treating it in C would be difficult as every version of C does it differently.

    http://www.phanderson.com/PIC/16C84/interrupts/interrupt_1.html
    http://www.phanderson.com/PIC/16C84/interrupts/interrupt_change.html
    http://www.phanderson.com/PIC/16C84/interrupts/interrupt_1a.html
     
  4. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Yes, you just write
    Code ( (Unknown Language)):
    1. void interrupt(){
    2. .......
    3. .......
    4. }
    Yes, like:
    Code ( (Unknown Language)):
    1. [B]void[/B] interrupt() {
    2.   [B]if[/B] (INTCON.TMR0IF) {
    3.     .........
    4.     INTCON.TMR0F = 0;
    5.   }
    6.   [B]else if[/B] (INTCON.RBIF) {
    7.     .........
    8.     INTCON.RBIF = 0;
    9.   }
    10. }[I]//~
    11. [/I]
    Hope this helps.
    Tahmid.
     
  5. rajbex

    New Member

    Nov 2, 2009
    22
    0
Loading...