|
|
View previous topic :: View next topic |
Author |
Message |
kongfu1
Joined: 26 Apr 2010 Posts: 56
|
Can't wakeup PIC16F882 from sleep! |
Posted: Thu Jul 14, 2011 3:08 pm |
|
|
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
|
|
Posted: Thu Jul 14, 2011 3:50 pm |
|
|
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
|
|
Posted: Thu Jul 14, 2011 4:39 pm |
|
|
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
|
Made some changes and result is same |
Posted: Thu Jul 14, 2011 6:05 pm |
|
|
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
|
|
Posted: Thu Jul 14, 2011 6:28 pm |
|
|
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: 19506
|
|
Posted: Fri Jul 15, 2011 2:26 am |
|
|
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
|
The problem is solved. Great. Thanks for everyone's helps. |
Posted: Fri Jul 15, 2011 11:22 am |
|
|
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);
}
}
|
|
|
|
|
|
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
|