CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Help with int_EXT

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rina_1220



Joined: 02 Oct 2007
Posts: 20

View user's profile Send private message

Help with int_EXT
PostPosted: Fri Jul 18, 2008 7:50 am     Reply with quote

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

View user's profile Send private message

Re: Help with int_EXT
PostPosted: Fri Jul 18, 2008 9:53 am     Reply with quote

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







PostPosted: Fri Jul 18, 2008 10:00 am     Reply with quote

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. Smile

Best Wishes
rina_1220



Joined: 02 Oct 2007
Posts: 20

View user's profile Send private message

PostPosted: Mon Jul 21, 2008 8:02 am     Reply with quote

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! Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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