Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Help with interrupts

Status
Not open for further replies.

MrNobody

New Member
Hi.. I came across several ways of writing interrupt and i need some help on it..

Below are some of the interrupts i got from C18 C Compiler User Guide.

1)
#pragma interruptlow low_interrupt_service_routine save=PROD

void low_interrupt_service_routine()
{
}

2)
#pragma interrupt high_interrupt_service_routine save=section("mydata")
void high_interrupt_service_routine()
{
}

3)
#pragma interrupt high_interrupt_service_routine save=section(".tmpdata")
void high_interrupt_service_routine()
{
}


On one website, I came across these
Code:
/**********************************************************************
 * General interrupt vector. Do not modify.
 **********************************************************************/
#pragma code IT_vector_low=0x18
void Interrupt_low_vec(void)
{
   _asm goto InterruptVectorL  _endasm
}
#pragma code

#pragma code IT_vector_high=0x08
void Interrupt_high_vec(void)
{
   _asm goto InterruptVectorH  _endasm
}
#pragma code



/**********************************************************************
 * General ISR router. Complete the function core with the if or switch
 * case you need to jump to the function dedicated to the occuring IT.
 **********************************************************************/
#pragma	code _INTERRUPT_VECTORL = 0x003000
#pragma interruptlow InterruptVectorL save=section(".tmpdata"), PROD
void InterruptVectorL(void)
{
  EnterISR();

  if (INTCONbits.TMR0IF == 1)
    AddOneTick();
/*Here is the next interrupts you want to manage */
/*if (INTCONbits.RBIF == 1)                      */
/*  MyOwnISR();                                  */

  LeaveISR();
}
#pragma	code

And in the same website i found this
Code:
Here is the "fast interrupt" function :

    /* BE CARREFULL : ONLY BSR, WREG AND STATUS REGISTERS ARE SAVED  */
    /* DO NOT CALL ANY FUNCTION AND USE PLEASE VERY SIMPLE CODE LIKE */
    /* VARIABLE OR FLAG SETTINGS. CHECK THE ASM CODE PRODUCED BY C18 */
    /* IN THE LST FILE.                                              */
    #pragma	code _INTERRUPT_VECTORH = 0x003300
    #pragma interrupt InterruptVectorH
    void InterruptVectorH(void)
    {
      if (INTCONbits.INT0IF == 1)
        INTCONbits.INT0IF = 0;
    }
    #pragma	code

The external interrupts INT0 (RB0 pin), INT1 (RB1 pin) and INT2 (RB2 pin) are by default in fast interrupt mode so when an interrupt occurs the current code processing is stopped and the InterruptVectorH() is executed.

Hmm.. after reading about the interrupt, i still dun really get the reason for the extra "save= bla bla bla" after the ISR.. I also don't understand fast interrupt or slow interrupt..

Another thing is when should I use high interrupt and when to use low interrupt..? Lets say, I want to just write an interrupt for Timer2 to read from ADC every 125us, do I need a high interrupt or low interrupt..?
And also, can i leave out the "save=" part when declare the ISR..? Umm.. i am assuming that "#pragma interrupt" is to declare the ISR right..?
 
Oh.. one more thing..
Lets say I am using Timer0 and Timer2. Both timers have its own interrupt flag.

Lets say I declare the interrupt as follow


#pragma interrupt high_interrupt_service_routine

void high_interrupt_service_routine()
{
}

When the interrupt is triggered, how will I know whether the source is from Timer0 or Timer2..

Sorry for such long question on interrupt..

Its my first time touching interrupt in PIC..
Btw, I am still reading on interrupt from Compiler user guide now..
 
I would suggest that you keep to the low interrupt and just poll the relevant interrupt bits.

Code:
#pragma code low_vector=0x18    //setup the ISR vector
void low_interrupt (){
  _asm GOTO low_isr _endasm    //jump to interrupt handler
}
#pragma code

#pragma interruptlow low_isr    //the ISR
void low_isr(){
    if (INTCONbits.TMR0IF == 1){
        //do your Timer 0 stuff here
	INTCONbits.TMR0IF=0;
    }

    if (PIR1bits.TMR2IF == 1){
        //do your Timer 2 stuff here
	PIR1bits.TMR2IF=0;
    }
}

#pragma code
//rest of code

To enable Timer2 interrupts, you would do the following,
Code:
    PIE1bits.TMR2IE=1;           //enable Timer2 interrupt
    INTCONbits.PEIE=1;          //enable peripheral interrupts
    INTCONbits.GIE=1;           //enable glogal interrupts
Note the peripheral and global interrupt bits had to be enabled for timer 2.

You can add as many sections as you have interrupts enabled. So if you had the RS232 receive interrupt enabled then you would add,
Code:
    if (PIR1bits.RXIF == 1){
        //Reading RCREG clears the interrupt flag
	var=RCREG;
    }
In this later case reading the receive register clears the interrupt flag.

HTH

Mike.
 
Last edited:
Pommie said:
I would suggest that you keep to the low interrupt and just poll the relevant interrupt bits.

Code:
#pragma code low_vector=0x18    //setup the ISR vector
void low_interrupt (){
  _asm GOTO low_isr _endasm    //jump to interrupt handler
}
#pragma code

#pragma interruptlow low_isr    //the ISR
void low_isr(){
    if (INTCONbits.TMR0IF == 1){
        //do your Timer 0 stuff here
	INTCONbits.TMR0IF=0;
    }

    if (PIR1bits.TMR2IF == 1){
        //do your Timer 2 stuff here
	PIR1bits.TMR2IF=0;
    }
}

#pragma code
//rest of code
Thanks..

Hmm..
What does the section below do..?
Code:
#pragma code low_vector=0x18    //setup the ISR vector
void low_interrupt (){
  _asm GOTO low_isr _endasm    //jump to interrupt handler
}
#pragma code
I mean, why need to begin with "#pragma code low_vector=0x18" and end with "#pragma code". Is it to indicate that the following section contains executable code..? Umm.. i know that the low interrupt address is 0x18, however, i do not know what "_asm GOTO low_isr _endasm" does. It states that it is to goto some part of the code.. What I am trying to say is that, is that something that we have to follow, kind of like the format..? Will it still work if we ignore the first part and only put as follow

Code:
#pragma interruptlow low_isr    //the ISR
void low_isr(){
    if (INTCONbits.TMR0IF == 1){
        //do your Timer 0 stuff here
	INTCONbits.TMR0IF=0;
    }

    if (PIR1bits.TMR2IF == 1){
        //do your Timer 2 stuff here
	PIR1bits.TMR2IF=0;
    }
}
#pragma code

Regarding the #pragma code, I have read the compiler user guide on #pragma but i still don't get the hang of it.. Can you please explain more of it to me..? I mean, i am still puzzled because normally, so far, i have never used #pragma code for example

Code:
#pragma code
void main()
{

}
#pragma code

Instead, i straight away write void main() etc..

Please explain more on it.. thanks..
 
Pragma's are used to tell the compiler stuff that isn't standard C. The _asm goto xxx _endasm is just placing a jump instruction at the interrupt vector so that it jumps to the actual code (the vector area is small). The actual interrupt code has a pragma to tell the compiler that this is interrupt code and it should take necessary precautions and return in the appropriate manner.

As you say, the best way to think of it is as a format that we have to follow.

You may find it useful to read through this thread. It has simple code to move a servo and then the code is changed to work with an interrupt.

Mike.
 
Hi,
Below is the code to generate a square wave of around 8kHz. After simulating it in Proteus, the square wave generated is correct. However i also receive messages that say
"[PIC18 MEMORY] PC=0x005A. Write 0x00 (0) to unimplemented memory address 0x0E0C does nothing".
Actually, there are thousands of them with different hexadecimal values. Below is my coding.
Anybody knows why those messages r generated in Proteus..? Thanks.

Code:
#include <p18f4620.h>
#include <delays.h>
#include <usart.h>
#include <stdio.h>
#include <timers.h>

#pragma config OSC=HSPLL 
#pragma config PWRT=ON
#pragma config BOREN=OFF
#pragma config WDT=OFF
#pragma config MCLRE=ON
#pragma config PBADEN=OFF
#pragma config LVP=OFF
#pragma config XINST=OFF
#define CLOCK_FREQ		(40000000ul)      // Hz 

/////////////////////////////////////
// FUNCTION PROTOTYPE
/////////////////////////////////////
void low_isr();
void InitInterrupt();
void InitTimer2();
void Test();

/////////////////////////////////////
// SETUP ISR VECTOR
/////////////////////////////////////
#pragma code low_vector=0x18    //setup the ISR vector
void low_interrupt ()
{
    _asm GOTO low_isr _endasm    //jump to interrupt handler
}
#pragma code

/////////////////////////////////////
// ISR
/////////////////////////////////////
#pragma interruptlow low_isr    //the ISR
void low_isr()
{
    if (PIR1bits.TMR2IF == 1)
    {
        PIR1bits.TMR2IF=0;
        Test();
    }
}
#pragma code

void main()
{
    InitInterrupt();
    InitTimer2();
    TRISB = 0x00;
    while (1)
    {
    
    }
}

void InitInterrupt()
{
    PIE1bits.TMR2IE = 1;	//enable Timer2 interrupt
    INTCONbits.PEIE = 1;    //enable peripheral interrupts
    INTCONbits.GIE = 1;     //enable glogal interrupts
    IPR1bits.TMR2IP = 0;	// low priority
}	

void InitTimer2()
{
    T2CON = 0b01001001;
    PR2 = 124;				// 125 counts including 0
    T2CONbits.TMR2ON = 1;
}	

void Test()
{
    PORTB = 0xFF;
    Delay10TCYx(25);
    PORTB = 0x00;
    Delay10TCYx(25);
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top