|
|
View previous topic :: View next topic |
Author |
Message |
rina_1220
Joined: 02 Oct 2007 Posts: 20
|
Help with int_EXT |
Posted: Fri Jul 18, 2008 7:50 am |
|
|
Hey all. I am having a problem with my external interrupt. I want it to put the processor to sleep once a button is pressed and to wake up as the same button is pressed again. I don't know what happens that if I press the button once, the processor goes to sleep and it's fine. But if I want to wake it up, I have to press the button twice. And I just don't know what's wrong with it. Here's the code of the interruption:
Code: | int sleepMode,
#int_EXT
EXT_isr()
{
delay_ms(50);
DISABLE_INTERRUPTS(INT_RB);
if(sleepMode==0)
{
sleepMode = 1;
clear_interrupt(int_EXT);
sleep();
}
else
{
sleepMode = 0;
clear_interrupt(int_RB);
enable_interrupts(INT_RB);
clear_interrupt(int_EXT);
return;
}
} |
I know it's working fine. All I need is to know why I need to press the button twice in order to "fully" wake the processor. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: Help with int_EXT |
Posted: Fri Jul 18, 2008 9:53 am |
|
|
The reason it takes two button presses is that the EXT_isr() has an implicit clear_interrupt(int_EXT) that works independently of your explicit call. It think the implicit one is executed upon exit from the routine. Therefore when the first wake-up button press wakes up from the sleep() command, the interrupt routine returns with sleepMode=1 and the external interrupt that caused the wake-up is already cleared. Therefore it takes a second external interrupt to re-enter the interrupt routine and change sleepMode=1 into sleepMode=0. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah Guest
|
|
Posted: Fri Jul 18, 2008 10:00 am |
|
|
Multiple possible things.
The most likely one is bounce.
When the processor goes to sleep, the _next_ instruction, is 'pre-fetched'. Certain instructions won't actual do what is expected in this case. Now the next instruction at this point, will be the 'clear' for INT_EXT, that the compiler automatically adds at the exit of the routine. So, you push the button and go to sleep. You press the button again, and actually wake up. However because the 'clear' is pre-fetched, the routine is immediately called again. Since the sleepmode variable is now 1, the routine changes this back to 0, putting you back to sleep again, since the key has some bounce...
There are quite a few scenarios round this possibility, but I would think this is where the problem lies.
As a 'comment', you _cannot_ just clear 'INT_RB'. If this has become set, it implies the input latch does not match the port. To clear this, you _must_read the latch first.
So, I'd expect to have to do something like:
Code: |
#if defined (__PCH__)
#byte INTCON=0xFF2
#else
#byte INTCON=0x8B
#endif
#bit EXTIF=INTCON.1
#define BUTTON_ON (1) //Need to define this to match your logic.
#int_EXT
void EXT_isr(void) {
int dummy;
DISABLE_INTERRUPTS(INT_RB);
//Though I hate delaying in interrupts, you really need to ensure
//the button has released, and debounced the release.
while (input(PIN_B0)==BUTTON_ON); //Wait for button to release
while (EXTIF) {
EXTIF=0;
delay_ms(10);
} //This will loop, till the interrupt flag remains 'unset' for 10mSec
//Hopefully the button is then released and debounced...
sleep();
delay_cycles(1); //put a _dummy_ instruction after the sleep
//You now need to wait again, for the button to release
while (input(PIN_B0)==BUTTON_ON);
while (EXTIF) {
EXTIF=0;
delay_ms(10);
} //Again insure bounce on release has finished
//Now read port B
dummy=input_b();
clear_interrupt(int_RB); //This can now work!...
enable_interrupts(INT_RB);
//clear_interrupt(int_EXT); /No point in this, the compiler does it for you.
}
|
Hopefully approaching working.
Best Wishes |
|
|
rina_1220
Joined: 02 Oct 2007 Posts: 20
|
|
Posted: Mon Jul 21, 2008 8:02 am |
|
|
Hey, Ttelmah and RLScott. Thank you for your help. I could not make it work the way Ttelmah said. I was still having to press the button twice even with that code. What solved my problem was this:
Code: | #int_EXT
EXT_isr()
{
DISABLE_INTERRUPTS(INT_RB);
//wait for button to be released
while(!input(PIN_B0)); //it has to be !input(PIN_B0)
//cause I'm working with high to low edge detection
if(sleepMode==0)
{
sleepMode = 1;
clear_interrupt(int_EXT);
sleep();
}
//wait for button to be released
while(!input(PIN_B0));
if(sleepMode==1)
{
sleepMode = 0;
clear_interrupt(int_RB);
enable_interrupts(INT_RB);
return;
}
} |
Now it's fine. Thank you for your help! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|