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

Can't wakeup PIC16F882 from sleep!

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



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

Can't wakeup PIC16F882 from sleep!
PostPosted: Thu Jul 14, 2011 3:08 pm     Reply with quote

PIC16F882
MPLAB: 8.66
CCS: 4.122

With a push button connected RB1 and Vdd. From a scope, it is always from low to high when pushing on it. But this never wake up this chip from sleep. What is wrong?

Code:

#include <16F882.h>

#use delay(clock=4M, crystal)
#fuses HS,MCLR,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NOCPD

int sleepFlag = 1;

//external IO is connected to port B RB1 pin
#INT_RB
void PushButtonISR(void)
{
   if(sleepFlag)
      sleepFlag = 0;
   else
      sleepFlag = 1;
   
}

void main (void)
{
   enable_interrupts(INT_RB);
   ext_int_edge(L_TO_H);      // init interrupt triggering for button press
   enable_interrupts(GLOBAL);
   while(1)
   {
      delay_ms(100);
      if(sleepFlag)
         sleep();
     
      output_toggle(PIN_C6);   
   }
   
}

Please help.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 3:50 pm     Reply with quote

You have to read Port B inside the #int_rb routine, to clear the "change"
condition, which clears the source of the interrupt. This is in the PIC data
sheet, in the Interrupt-On-Change section. (Or you could read the RB1 pin).

If you don't read Port B in the isr, you will get the interrupt continuously
and the program will spend nearly all of its time executing the isr over
and over again.
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 4:39 pm     Reply with quote

PCM programmer wrote:
You have to read Port B inside the #int_rb routine, to clear the "change"
condition, which clears the source of the interrupt. This is in the PIC data
sheet, in the Interrupt-On-Change section. (Or you could read the RB1 pin).

If you don't read Port B in the isr, you will get the interrupt continuously
and the program will spend nearly all of its time executing the isr over
and over again.


Thanks PCM.
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

Made some changes and result is same
PostPosted: Thu Jul 14, 2011 6:05 pm     Reply with quote

PCM programmer wrote:
You have to read Port B inside the #int_rb routine, to clear the "change"
condition, which clears the source of the interrupt. This is in the PIC data
sheet, in the Interrupt-On-Change section. (Or you could read the RB1 pin).

If you don't read Port B in the isr, you will get the interrupt continuously
and the program will spend nearly all of its time executing the isr over
and over again.


Following your suggestion and made following changes. The result is same.
From the scope, C7 was never become high but B1 was changing between 0-5V every time when the button was pushed.

Code:

#include <16F882.h>

#use delay(clock=4M, crystal)
#fuses HS,MCLR,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NOCPD

int sleepFlag = 1;

//external IO is connected to port B RB1 pin
#INT_RB
void PushButtonISR(void)
{
   int theByte;

   output_toggle(PIN_C7);
   theByte = input_change_b( );
   if(sleepFlag)
      sleepFlag = 0;
   else
      sleepFlag = 1;
   
}

void main (void)
{
   enable_interrupts(INT_RB);
   ext_int_edge(L_TO_H);      // init interrupt triggering for button press
   enable_interrupts(GLOBAL);

   output_low(PIN_C7); //make sure C7 is low for next interrupt
   while(1)
   {
      delay_ms(100);
      if(sleepFlag)
         sleep();
     
      output_toggle(PIN_C6);   
   }
   
}


Thanks for helps.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 6:28 pm     Reply with quote

Try it with a program that doesn't use sleep. See if it works on your
hardware. This program only enables interrupt-on-change on pin B1.
So I think it is more limited and has a better chance to work.
Code:

#include <16F882.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define SW_PIN   PIN_B1
#define LED_PIN  PIN_C7

#int_rb
void rb_isr(void)
{
int8 value;

output_toggle(LED_PIN);
delay_ms(10);

value = input(SW_PIN);
}

//============================
void main()
{
int8 temp;

output_low(LED_PIN);

temp = input(SW_PIN);
clear_interrupt(INT_RB);
enable_interrupts(INT_RB1);
enable_interrupts(GLOBAL);

while(1);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19339

View user's profile Send private message

PostPosted: Fri Jul 15, 2011 2:26 am     Reply with quote

Also note PCM leaving out the ' ext_int_edge' command. This is not available on INT_RB. It is for the INT_EXT (hence 'ext' in the command).

INT_RB, is called whenever a port pin changes. No 'direction' control (there is direction control on some chips, but not your's, and not using this command....).

As a comment, if you are only wanting to use RB1, then enable the interrupt with:
enable_interrupts(INT_RB1);

which will only enable them on this one pin.

Also using the 'input_change_b' function is rather pointless, since the fact the interrupt has been called, says 'there has been a change'. What you will need to work out is the direction, so:
Code:

#INT_RB
void PushButtonISR(void) {
   int8 current_value;

   output_toggle(PIN_C7);
   current_value = input_b( );
   if (bit_test(current_value,1)==1) {
      //Change must be low to high, since pin is now high
      //Only correct if INT_RB1 alone selected.
      if(sleepFlag)
         sleepFlag = 0;
      else
         sleepFlag = 1;
   }
}


Best Wishes
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

The problem is solved. Great. Thanks for everyone's helps.
PostPosted: Fri Jul 15, 2011 11:22 am     Reply with quote

Thanks for everyone's help. The problem is solved. See code below.

Code:

#include <16F882.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define SW_PIN   PIN_B1
#define LED_PIN  PIN_C7

int8 sleepFlag = 1;

#int_rb
void rb_isr(void)
{
   int8 value;
   
   output_toggle(LED_PIN);
   delay_ms(10);
   
   value = input(SW_PIN);
   if(value)
   {
      if(sleepFlag)
         sleepFlag = 0;
      else
         sleepFlag = 1;
   }
}

//============================
void main()
{
   int8 temp;
   
   output_low(LED_PIN);
   
   temp = input(SW_PIN);
   clear_interrupt(INT_RB);
   enable_interrupts(INT_RB1);
   enable_interrupts(GLOBAL);

   while(1)
   {
      delay_ms(100);
      if(sleepFlag)
         sleep();
      output_toggle(PIN_C6); 
   }
}
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