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.

[PIC] External Interrupt for PIC16F882 (Working on Simulation(Proteus) but not in Hardwar )

Status
Not open for further replies.

sanjusony

Newbie level 5
Joined
Dec 2, 2015
Messages
8
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Location
Kerala. India
Activity points
1,368
// Program(For PIC16F882 MP lab X IDE) is not working on Hardware even though its working in simulation.:bang::bang::bang::bang:
Description


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//*********************************************************************************************************//
/* 
* File : ExtIntrToggle.c
*
* IDE : MPlab X IDE
/* 
 
// Program to check led toggle on external interrupt on RB0 using push button and 
// led at RC1 
 
 
 
#include <pic.h> //Use this to include the device header for your PIC.
//In our case, this will include pic16882.h.
 
 
 
#define _XTAL_FREQ 20000000 //20MHz, which is default
//This is used by the compiler to calculate how many
//instructions to delay in the calls to __delay_ms().
 
#define LED1 PORTCbits.RC3 //Normal led blinking check
#define LED1_TRIS TRISCbits.TRISC3
#define LED2 PORTCbits.RC1 // Interrupt Led blinking check
#define LED2_TRIS TRISCbits.TRISC1
 
void interrupt isr()
{
if(INTCONbits.INTF == 1)
{
// //reset the interrupt flag
INTCONbits.INTF = 0;
 
LED2 = ~LED2; //flip the bit
//The ~ (tilde) is the complement operator
}
} 
 
int main()
{
TRISA = 0xFF; //set all digital I/O to inputs
TRISB = 0xFF;
TRISC = 0x00;
 
ANSEL = 0x00; //disable all analog ports
ANSELH = 0x00;
 
WPUB = 0x00;
IOCB = 0X00;
 
LED1_TRIS = 0; //LED1 is an output
LED2_TRIS = 0; //LED2 is an output
 
INTCONbits.INTF = 0; //reset the external interrupt flag
OPTION_REGbits.INTEDG = 1; //interrupt on the rising edge
INTCONbits.INTE = 1; //enable the external interrupt
INTCONbits.GIE = 1; //set the Global Interrupt Enable
 
///////////////////////
// Main Program Loop //
///////////////////////
while(1)
{
LED2 = 1; //Flash LED1
__delay_ms(500);
LED2 = 0;
__delay_ms(500);
}
 
return 0;
}
 
//*********************************************************************************************************//

 

Which compiler?
What are the config settings
What actually is "not working"? We need a far more detailed description of what you have done, what should be happening but isn't, what is happening but shouldn't.
Typically the places to look at are the hardware, config and software settings.
For the hardware, you need to make sure that all bypass capacitors are in place, the power supply is applied to all pins, \MCLR\ is pulled high (through a resistor) and that any external oscillator components are connected.
We you don't show the config settings, if you leave them to the default settings then you will be using the RC clock which needs the correct components. As you say you are using a 20MHz clock source, I assume however that you are using either EC mode with an external clock source or a 20MHz crystal in HS mode that is set via the Config register. If so then be careful of using a breadboard as the 20MHz clock signal can be a bit distorted by the parasitic capacitance between the tracks if you don't have the clock source close to the device pins.
Susan
 

share your circuit diagram with the code
 

The circuit is attached
Capture.PNG

Code for those.....

MPLAB X C8 Compiler

Code:
#include <xc.h>   
					

#define _XTAL_FREQ 20000000 
#define LED1           PORTCbits.RC3      
#define LED1_TRIS   TRISCbits.TRISC3
#define LED2           PORTCbits.RC1
#define LED2_TRIS   TRISCbits.TRISC1

void interrupt isr()
{
    if(INTCONbits.INTF == 1)
    {
        //  //reset the interrupt flag
        INTCONbits.INTF = 0;

    LED2 = ~LED2;   //flip the bit
                    //The ~ (tilde) is the complement operator
    }
}    

int main()
{
    TRISA = 0xFF;   //set all digital I/O to inputs
    TRISB = 0xFF;
    TRISC = 0x01;

    ANSEL = 0x00;   //disable all analog ports
    ANSELH = 0x00;
 
    WPUB = 0x00;
    IOCB = 0X00;
    
    LED1_TRIS = 0;      //LED1 is an output
    LED2_TRIS = 0;      //LED2 is an output

    INTCONbits.INTF = 0;        //reset the external interrupt flag
    OPTION_REGbits.INTEDG = 1;  //interrupt on the rising edge
    INTCONbits.INTE = 1;        //enable the external interrupt
    INTCONbits.GIE = 1;         //set the Global Interrupt Enable
    LED2 = 0;
    ///////////////////////
    // Main Program Loop //
    ///////////////////////
    while(1);
    {
        LED1 = 1;           //Flash LED1
        __delay_us(5000);
        LED1 = 0;
        __delay_us(5000);
    }

    return 0;
}
 
Last edited by a moderator:

The code looks OK to me but you must add a resistor in series with the LED. If you have it wired as in the schematic, the LED current will be far too high and it might be resetting the PIC.

Does 'LED1' (with a series resistor) flash continuously while you are waiting for the interrupt?

Brian.
 

In Actual hardware I used 330ohms resistor series with LED2 and LED1.

There is no problem with simulation. LED2 will blink only at button press. LED1 blink continuously(In this code I stopped using "while(1);")

But when it comes to hardware there is no response at LED2(In Interrupt). the configuration I used " 00D2 0700"
 

OK, LED1 flashing tells us the program is really running but for some reason either the INT isn't recognised or LED2 isn't being driven.

I'm going to guess the problem is LED2 isn't being driven and the reason is what we call an RMW (Read Modify Write) issue. The instruction to toggle the LED output may not be doing what you expect because of the way the 16F series ports work. To toggle the bit, the whole port has to be read in and then the bit toggled then the whole port written out again. It is possible while doing that for any stray charge left on the port pin to be mistaken for the signal you want to change. Your real intention is to write a value to the port which alternates between RC1 being high and RC1 being low, what you are actually doing is reading the present state of RC1 as an input then writing it as an output so if the input signal isn't as expected, the output will be wrong too.

The best cure for this kind of problem is to shadow the port, in other words create a variable in which you toggle the bit and write the variable to the port so you don't read the port at all. However, try this first:

Change the 'toggle' line to 'LED2 ~= LED2;'

If that doesn't work do this:

Create a variable, lets call it 'ShadowPortC'
In the ISR, replace the toggle line with these two lines
ShadowPortC ^= 0x02;
PORTC = ShadowPortC;

See if that works.

Brian.
 

Also you should debounce the push button. Connecting a push button to an external interrupt is is generally not a good idea. Better is to use a timer to sample the input port pin every (say) 5 millisecond and flag the button push/release when (say) 4 consecutive samples are the same.
Susan
 

Dears ,

Thanks your prompt replies.:thumbsup:

I checked the program using bellow changes.
Code:
         unsigned char X=0;

         inside ISR

         X=~X;

         LED2 =X;

Then also I'm getting same output(no blinking);

Instead of push button , I check with zero crossing output from optocoupler (50 iteration for 50Hz) . then also i getting no blinking form LED2


I am using controller PIC16F882 ,is there any additional configuration needed for any SFR register??
 

The RB0/INT pin needs a pullup or pull-down resistor to properly work.
 

Either it has a debounce problem...
You could increase the on/off time to get to know better.
The code looks good enough.

Also check if peripheral interrupt is enabled in program.
That could be a small yet vital problem.
 

Change this

Code:
if(INTCONbits.INTF == 1)
    {
        //  //reset the interrupt flag
        INTCONbits.INTF = 0;

    LED2 = ~LED2;   //flip the bit
                    //The ~ (tilde) is the complement operator
    }

to

Code:
if(INTCONbits.INTF == 1)
    {
        //  //reset the interrupt flag
        

    LED2 = ~LED2;   //flip the bit
INTCONbits.INTF = 0;
                    //The ~ (tilde) is the complement operator
    }
 

Since the question came up but I didn't see an answer, does LED2 work? Add/Change the LED1 blink loop to LED2 to verify the LED and driver, etc. work. You may also want to change the interrupt edge to falling since the pin is pulled high initially on reset. You may also need to add some kind of de-bounce detection in the ISR. Also, don't re-enable the interrupts until you are ready to leave the service routine.
 

If you change the value of a variable inside an ISR and also use the value of the variable outside it, then the variable needs to be declared as 'volatile'.
As you only show a snippet of pseudo-code in port #9, it is hard to tell if this is the case or not.
By the way, can you confirm that you have made the wiring suggestions from my post #2 on th eactual circuit? They are not shown in the schematic (which mightr be OK for the simulator) but they are essential for the real hardware.
@Okada (re Post #12): whether you clear the IF flag at the start or end of the ISR should not matter in this case as we have been told the triggers occur at 50Hz. Unless there is something extremely wrong, the ISR will execute much faster than 20mSec and so the flag will always be cleared before the next interrupt.
Susan
 
The debounce problem wont stop it working although the result may look random.
The edge detected wont make a difference either as both will occur as the button is pressed then released.
It already has a pull-up resistor on the INT pin (there is an internal one too)
Peripheral interrupts are not used, the INT is one of the core sources controlled only by the INTCON register.

I'm still suspicious of the LED2 = ~LED2, please try it as I suggested, the changes you have listed are not the ones I asked you to try.

Brian.
 
I dont think that might work,
because if once it gets into a loop the program is going to complete all instructions without being affected by the sequence....
 

Please check datasheet and see if your PIC16F has LATx registers. I have seen some PIC16F's that has LATx registers for output. if it has LATx registers then you have to change PORTxvits.Rxy to LATxbits.LATxy in the #defines.
 

16F882 is an old device Okada. No LAT registers,
Aussie Susan is right about declaring variables used both inside and outside an ISR as 'volatile' but I doubt this is the problem you see at the moment. It is either RMW, especially as the main loop is also reading and writing the same port or the instruction is just wrong. Try the modification I suggested in post #7. Even XORing the single port bit is preferable to inverting all the port contents then writing some of it back.

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top