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.

[SOLVED] Using external interrupt on RB0 C 16f877

Status
Not open for further replies.

WStevens_sa

Member level 2
Joined
Jan 5, 2011
Messages
47
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
South Africa
Activity points
1,695
Hi all

Please can you help me with the following. I am newbie to MCU's and C. I am familiar with programming ASP.NET, VB, C# and Java as a Microsoft developer. I have read the datasheet and I cannot figure it out.

I have the following project. PORTA flashes LEDS all outputs. I want to interrupt this and output to PORTD and delay for 2 sec and then return to PORTA flashing. Is the code below correct.

void interrupt(void) {

if(INTCON.INTF == 1)
{
PORTD = 0x01; //To see if interrupt is triggered
Delay_ms(2000);
INTCON.INTF = 0; //You HAVE to clear interrupt flag
}
}

void main()
{
INTCON.GIE = 1; //Enable Global Interrupt
INTCON.INTE = 1; //Enable RB0/INT external Interrupt
INTCON.PEIE = 0; //Disable all unmasked peripheral interrupt
OPTION_REG.INTEDG = 1; //Interrupt on rising edge

PORTA = 0x00; /*set RA0-RA5 low */
TRISA = 0x00; /*set PORTA to output*/
TRISD = 0x00; /*set PORTD to output*/

do{ //Flash all LED's

PORTA = ~PORTA;
Delay_ms(100);

}while(1);

}
 

Hi,
Here's the fixed code:
Code:
void interrupt(void) {

if(INTCON.INTF == 1)
{
PORTD = 0x01; //To see if interrupt is triggered
Delay_ms(2000);
INTCON.INTF = 0; //You HAVE to clear interrupt flag
}
}

void main()
{
INTCON.GIE = 1; //Enable Global Interrupt
INTCON.INTE = 1; //Enable RB0/INT external Interrupt
INTCON.PEIE = 0; //Disable all unmasked peripheral interrupt
OPTION_REG.INTEDG = 1; //Interrupt on rising edge

PORTA = 0x00; /*set RA0-RA5 low */
TRISA = 0x00; /*set PORTA to output*/
PORTA = 0; //Clear initial PORTA state
ADCON1 = 7; //Disable ADC so that PORTA can be used for digital purpose
//CMCON = 7; //Disable comparator      --------> Only for 16F877A not 877
TRISD = 0x00; /*set PORTD to output*/
PORTD = 0; //Clear initial PORTD state

TRISB0_bit = 1; // set RB0 to input


do{ //Flash all LED's

PORTA = ~PORTA;
Delay_ms(100);

}while(1);

}

The problems are:
Code:
ADCON1 = 7; //Disable ADC so that PORTA can be used for digital purpose

This line must be added to disable the ADC so that PORTA can be used for digital purpose.

Code:
TRISB0_bit = 1; // set RB0 to input

This line must be added. It makes RB0 input so that interrupt can be triggered.

Hope this helps.
Tahmid.

---------- Post added at 17:47 ---------- Previous post was at 17:44 ----------

Just as a tip (I assume you're using mikroC):
Code:
INTCON.INTF
can be written as
Code:
INTF_bit
Code:
OPTION_REG.INTEDG
can be written as
Code:
INTEDG_bit

And so, you can write
Code:
GIE_bit = 1; //Enable Global Interrupt
INTE_bit = 1; //Enable RB0/INT external Interrupt
PEIE_bit = 0; //Disable all unmasked peripheral interrupt
INTEDG_bit = 1; //Interrupt on rising edge

Hope this helps.
Tahmid.
 
Hi Tahmid

I copied the code as is from here and tried it but it did not work. Yes I am using MikroC and I am also using Real Pic Simulator to test with and i am using a simulated push button to trigger RB0. So I am not sure where the problem is.

I did change the code to simplify it See below
Code:
int i = 0;
void interrupt(void) {

if(INTCON.INTF == 1)
{
 for(i=0;i<10;i++) // A loop for creating a trigger response
   {
   RD0_bit=1;
   Delay_ms(1000);
   RD0_bit=0;
   Delay_ms(1000);
   }
   INTF_bit=0; // Reset the external interrupt flag
}
}

void main()
{
TRISA=0; // Set PORT A as an OUTPUT
TRISB=0; // Set PORT B as an OUTPUT
TRISC=0; // Set PORT C as an OUTPUT
TRISD=0;
PORTC=0; // Set the value of PORT C to 0

GIE_bit = 1; //Enable Global Interrupt
INTE_bit = 1; //Enable RB0/INT external Interrupt
PEIE_bit = 0; //Disable all unmasked peripheral interrupt
INTEDG_bit = 1; //Interrupt on rising edge

ADCON1 = 7; //Disable ADC so that PORTA can be used for digital purpose
TRISB0_bit = 1; // set RB0 to input


do{ //Flash all LED's

   PORTA++;

   Delay_ms(200);

   RB0_bit =1;

}while(1);

}
 

Hi,
The code I gave should work fine as I've tested it in Proteus and it's fine. The problem with your code is the ISR is so long. I'll fix it and then post it here in a while.

Tahmid.

---------- Post added at 19:58 ---------- Previous post was at 19:49 ----------

Your ISR is 20 seconds long. That's the problem. I'll fix the code and post it here.

---------- Post added at 20:18 ---------- Previous post was at 19:58 ----------

First, you have to clarify what you want. Your code is fine if what you want is - increment the value of PORTA but stop doing so, when interrupt is triggered, and then blink the LED on and off 10 times (20 seconds approximately) then restart incrementing the value of PORTA.
 
Last edited:

Hi Tahmid

How do you know what the Interrupt Service Routine time is?

Edit
Okay Sorry my stupidity. I see I am running a for loop 10 x plus total of 2 second delay every loop = 20 seconds. Is this correct in saying so. What I cannot understand that if I run the code in debug mode and go line by line it does not trigger and goto the interrupt functions
 
Last edited:

Hi,
I don't know where you're debugging, but in Proteus it runs fine. Have you set the circuit properly? Are you sure your simulator simulates interrupts properly?
Yes, you're correct in your calculation. Of course, I didn't take into the other instructions that take up a few microseconds.
 

I have checked everything I can think of. The Mikroc compiler has an option to run a debug where you can go line by line execution in your code. The program executes exactly how it should however even if i set the RB0 intput to 1 it does not trigger the ISR it stays in the while loop. It should allow me to continue debugging line by line inside the ISR. The code compiles with no problems. It is as if the interrupt function does not exist or is ignored.
 

Hi,
I don't think mikoC simulates interrupts. That maybe your problem.

mikroC's debugger is just an "Instruction Set Simulator". That's why it can execute the individual instructions of PIC core but it has no understanding of PIC's peripherals like the Timer you are trying to simulate.

You must manually enter in interrupt function with the key F2.

Or with menu -> Run -> Jump to interrupt.

You have to simulate this with some other simulator that can simulate interrupts.

Hope this helps.
Tahmid.
 
Hi,

Do not put delays in your interrupt routine ...

void interrupt(void) {

if(INTCON.INTF == 1)
{
PORTD = 0x01; //To see if interrupt is triggered
//Delay_ms(2000);
INTCON.INTF = 0; //You HAVE to clear interrupt flag
}
}
 
Thanks Hugo.
The only reason I put it there was to see the trigger effect in real pic simulator

Hi Tahmid

When i am in debug mode and I press F2 it jumps to my ISR. If I remove ISR completely and debug it then jumps to a list file which shows

"0x0007 0x0820 MOVF ___DoICPAddr, 0"

Okay

I made a break through. Firstly you are correct Tahmid. The debug mode does not allow line by line debugging to the ISR. Second Problem was my simulator's push button was not set to RB0. The code now does the following in the simulator.

The counter on PORTA starts counting. When I apply the signal to RB0 it turns on RD0 however it only goes on if I remove the "Delay_ms(500); and RD0_bit=0; so I cannot get it to flash before PORTA count starts again. The other thing is it does not stop PORTA's count unless it is so fast I do not see it.

Once I reset the simulator and try again it does not work. So in other words it only triggers 1 time. I am resetting the flag in the ISR. I would like RD0 to flash twice before continuing.

Code:
int i = 0;
void interrupt(void) {
if(INTCON.INTF)
{
RD0_bit=1;
INTCON.INTF=0; // Reset the external interrupt flag
}
}

void main()
{

TRISA=0; // Set PORT A as an OUTPUT
TRISD=0; // Set PORT A as an OUTPUT
PORTC=0; // Set the value of PORT C to 0
TRISB=0x00;

INTCON.GIE=1; // Global interrupt enable
INTCON.INTE=1; // Enable external interrupts from RB0
INTCON.INTF=0; // Reset the external interrupt flag

PEIE_bit = 0; //Disable all unmasked peripheral interrupt
OPTION_REG.INTEDG = 1; //Interrupt on rising edge

ADCON1 = 7; //Disable ADC so that PORTA can be used for digital purpose
TRISB0_bit = 1; // set RB0 to input

while(1){ //Counter

   PORTA++;

   Delay_ms(200);
   
};
}
 

hi Guys

Thanks for all the help. Problem(s) solved. Real Pic Simulator ver1.1 has bugs. Version 1.3 works. This solved the problem with only triggering 1 time.

The code below works and might help someone else one day.

Compiled with MikroC Pro
Saved HEX using PICKFlash built in to MikroC
Simulated with Real Pic Simulator 1.3

Code below works

Code:
int i = 0;
int x = 0;
void interrupt(void) {
     if(INTCON.INTF)
     {
          for(i=0;i<65000;i++) // A loop for creating a flash
          {
          RD0_bit=1; /// for testing if ISR is triggered
          }
     RD0_bit=0;
     INTCON.INTF=0; // Reset the external interrupt flag
     }
}

void main()
{

TRISA=0; // Set PORT A as an OUTPUT
TRISD=0; // Set PORT A as an OUTPUT
PORTC=0; // Set the value of PORT C to 0
TRISB=0x00;

INTCON.GIE=1; // Global interrupt enable
INTCON.INTE=1; // Enable external interrupts from RB0
INTCON.INTF=0; // Reset the external interrupt flag

PEIE_bit = 0; //Disable all unmasked peripheral interrupt
OPTION_REG.INTEDG = 1; //Interrupt on rising edge

ADCON1 = 7; //Disable ADC so that PORTA can be used for digital purpose
TRISB0_bit = 1; // set RB0 to input

while(1){ //Counter

     if (  RD0_bit==1){

           RD0_bit=1;
     }

   PORTA++;

   Delay_ms(100);

};
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top