Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Interrupt Service Routine for PIC16f877

Status
Not open for further replies.

eefinni

Newbie level 3
Joined
Jun 12, 2011
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,326
Hi all, I had tried all means to exit the ISR but it seems impossible.. I'd read about RETFIE but it is for ASM. I had also read about instructions set for RETFIE but I don't know how to implement it.

Is there anyway to exit from the ISR?

Here is my code:

PHP:
//Define compiler error message.
#ifndef __CPU_16F877__
#error "This program is tailored for PIC16F877 controller"
#endif

//Include required header file.
#include "io16f877.h" //the hardware register defination file.
#include "USART.h"
#include "DELAYS.h"

//List out all inputs and outputs

#define LED_1 RA0
#define LED_2 RA1
#define LED_3 RA2

#define IR RC1

#define RED RB5
#define Yellow RB6

volatile unsigned int DataCount;
volatile unsigned char DATA[3];

/**********************************************************************
This function initializes the IO ports. 
**********************************************************************/

void initialize_IO_ports(void)
{
//set the digital IO ports as per requirement.

ADCON1 = 0x07; //set PortA as digital I/O
TRISA = 0x00; //PortA as output.
TRISB = 0x00;
TRISC = 0x8F;
//clear the output ports at the beginning.
PORTA = 0x00;
PORTC=0x00;
PORTB=0x00;

}

#pragma vector=0x04
__interrupt void isr(void)
{
        //if(DataCount==0)
        //  PCL=PCLATH;
        //if(RCIF)
        //{  
        RCIE=0;
        DATA[DataCount]=RCREG;
        if(DataCount!=2)
        DataCount++;
        CREN=0;
        RCIF=0;
        //}
	if(DATA[0]=='0')
	  LED_1=1;
	if(DATA[1]=='1')
	  LED_2=1;
	if(DATA[2]=='2')
	  LED_3=1;

	//if(DataCount==2)
        //  PCLATH=(PCL+1);
	  
          //if(DataCount==2)
        //if(DataCount==2)
        
        //GIE=0;
        //RCIF=1;
        //STATUS=0x009;
        //DelayUs(1);
        
        //DelayUs(1);
        Yellow=1;
        DelayMs(100);
        Yellow=0;
        RCIE=1;
        //INDF=0x009;
        //DelayMs(100);
        //GIE=1;
        return;
        //break;
}

// define the main function

void main()
{
int i,k=0;
char send[3];
RCIF=0;
GIE=1;
PEIE=1;
send[0]='0';
send[1]='2';
send[2]='2';
// initialization of the peripherals to be used by 
 // calling the respective initialization functions.
 initialize_IO_ports();
 init_uart();
 

 while(1)
 {
	if(IR==1)
	{
		k++;
		RED=1;
		}
	   
	   if(k==1)
	   {
		GIE=1;
		for(i=0;i<3;i++)
        {
			CREN=1;
          	while(TXIF==0);
			TXREG=send[i];
			DelayMs(10);
		}
	}
	if(k==2)
	{
		GIE=1;
		send[0]='0';
		send[1]='1';
		send[2]='2';
		for(i=0;i<3;i++)
		{
			CREN=1;
			  
			while(TXIF==0);
			TXREG=send[i];
			DelayMs(10);
		}
	}

	if(k==3)
	{
		GIE=1;
		k=0;
		Yellow=1;
		send[0]='1';
		send[1]='1';
		send[2]='2';
		for(i=0;i<3;i++)
		{
			CREN=1;
			  
			while(TXIF==0);
			TXREG=send[i];
			DelayMs(10);
		}
		
	}
	/*
	if(DATA[0]=='0')
	  LED_1=1;
	if(DATA[1]=='1')
	  LED_2=1;
	if(DATA[2]=='2')
	  LED_3=1;
	  */
	DelayMs(100);
 } //endWhile.
}//endmain
 

I just figured that out. Unfortunately, it looks like IAR no longer supports their PIC compilers. I couldn't find a user manual for the PIC16 version of their compiler on their website.

---------- Post added at 11:08 ---------- Previous post was at 10:46 ----------

Just briefly looking over your code and without studying it thoroughly. It looks like you're not testing to see what exactly triggered the interrupt, therefore you're not resetting or disabling that particular interrupt. So when you exit the ISR the global interrupt flag is reenable and BINGO you're right back in the ISR.

So you are basically stuck in the interrupt service routine.

You should be able to run the program in debug mode and figure out what exactly is triggering the interrupt.

My suggestion would be test for the actual interrupt and clear it.

If I sound like I'm babbling it is due to the fact it's 4AM here.
 

I just figured that out. Unfortunately, it looks like IAR no longer supports their PIC compilers. I couldn't find a user manual for the PIC16 version of their compiler on their website.

---------- Post added at 11:08 ---------- Previous post was at 10:46 ----------

Just briefly looking over your code and without studying it thoroughly. It looks like you're not testing to see what exactly triggered the interrupt, therefore you're not resetting or disabling that particular interrupt. So when you exit the ISR the global interrupt flag is reenable and BINGO you're right back in the ISR.

So you are basically stuck in the interrupt service routine.

You should be able to run the program in debug mode and figure out what exactly is triggering the interrupt.

My suggestion would be test for the actual interrupt and clear it.

If I sound like I'm babbling it is due to the fact it's 4AM here.

Wow.. You should seriously get some sleep! Really grateful for your replies!

I'm actually making a small program to test its interrupt. Basically I wired the chip to send and receive to itself. When triggered, the interrupt that caused by RCIF, will start the ISR. I did try to clear & set RCIF, GIE and even PEIE! Non did work..

I'm trying to use the instruction set of the PIC. The 14bit word which specifies the instruction type or operands.. Do you know which register I should write the instruction set to perform the RETFIE function?
 

Now that I've had three hours of sleep, let me see if I can convey my thoughts a little clearer.

In regards to the RETFIE instruction, all it does is GIE=1 and set PC to its prior value. So embedding the RETFIE instruction is not really going to help matters.

What I believe is happening, I take a more thorough look at your code shortly, is that an interrupt you were not expecting is triggered, calling your ISR which is not prepared to handle this unexpected interrupt. Because it is not prepared for this particular interrupt, it doesn't reset its interrupt flag. Therefore, once the ISR is exited and the GIE is again set, BINGO you're right back in the ISR again and the vicious cycle starts all over again.

If you can debug your program, set a breakpoint inside the ISR. Then run the program and when you hit the breakpoint, check all the interrupt flags to determine which interrupt is calling the ISR.

Also, you could and should disable any maskable interrupts you do not intend to service. I'll check your program shortly and let you know what else I find.
 
Really grateful to you!

I've tried to run it on the debugger. I couldn't set my cursor to the main. It kept looping to the initialization part of the code! Not even to the ISR!!

But most importantly, You are right! I saw in asm that there is a RETFIE in my ISR! Do you know of any free debugger software where I could run my code to check which interrupt triggers the ISR and did not manage to clear when it ends?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top