Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Wake-up from sleep mode using PORTB change

Status
Not open for further replies.

GreenBeret

New Member
Hi All,

I am facing problem in waking up from sleep mode in PIC 16F72. I have connected main power voltage to RB7 pin. Whenever main power goes down, i am putting PIC to sleep mode. Just before putting to sleep mode, i am enabling the RBIE enabling bit to 1. And i have interrupt service routine code which checks for the status of RBIF. Whenever main power comes, there will be a voltage in RB7 and hence the port change should happen and my interrupt service routine should work.. But it seems like the interrupt service routine is not working.. What could be the reason... ?

Below is the code snipet.

/*
Interrupt routine.
*/
void interrupt
isr( void )
{
// Checking for whether timer1 interrupt.
if ( TMR1IF )
{
timerTick = 1; // Setting flag used by main function.
TMR1H |= 0b11000000; // Making Timer1 a 14bit counter.
TMR1IF = 0; //Clearing the interrupt flag.
}
if ( RBIF )
{
sleep = 0;
RBIF = 0;
RA0 = 1;
showNumber ( &count );
temp = PORTB;
RBIE = 0;
}
}


Below is the control register values i am setting in my program:
TMR1H |= 0b11000000; // Making Timer1 a 14bit counter.
T1CON = 0B001111;
OPTION = 0B10000000;
TMR1IE = 1;
GIE = 1; // enable global interrupts
PEIE = 1; // peripheral interrupt enabled.

Any help is greatly appreciated.
 
I am setting RBIE = 1; before calling SLEEP();
I hope setting is enough. Please let me know if anything else is required to do..
Thanks for ur reply...
 
Well, u didn't indicate that in your code.. How would anyone know what you have/haven't done..? Can you post the complete code instead of letting people guess what you have done and are trying to do..?
Do you happen to have a debugger? If you have then try to step through your coding to see what/where the PIC is stuck.
If you don't have then you could use MPLAB's built-in Simulator to debug your code and find that out.
 
Last edited:
I got tired of trying to guess the problem because a code snippet is posted rather than compilable code.

Mike.
 
Below is the complete source code...


//include file
#include <pic.h>

__CONFIG ( XT & UNPROTECT );

volatile unsigned char sleep = 0;
//main function
void main ( void )
{
RBIE = 1;
PEIE = 1;
GIE = 1;

TRISB = 0xF0;

while ( 1 )
{
if ( sleep != 0 )
{
RA0 = 1;
PORTC = 0b11111100;
}
}
}

/*
Interrupt routine.
*/

unsigned char prev_portb=0;

static void interrupt
isr( void )
{
if ( RBIF )
{
sleep = 1;
RBIE = 0;
RBIF = 0;
prev_portb=PORTB;
}
}
 
Having a variable called sleep will not put the pic to sleep. You need to execute a sleep instruction in assembly by doing,
Code:
    RBIF=0	//clear interrupt
    dummy=PORTB	//read port b to clear missmatch
    #asm
        sleep	//sleep
        nop	//will execute before interrupt
    #endasm

You also need the other code to make sure it doesn't wake up immediately.

Mike.
 
GreenBeret:
There you go.. Your questions answered.. It would have been alot quicker if you had posted the complete code in your first post..

In addition to what Mike had written, since you are using Hi-Tech compiler, you can do everything in C by typing

SLEEP();
NOP();

However, if you intend to switch compiler later on, I think its better to do it as what Mike has done as I'm not sure other compiler will support SLEEP() and NOP() or not.
 
Thanks for your support... I am aware of SLEEP() instruction to put the PIC to sleep mode. I have done it, but i was actually trying to wake up the PIC from sleep using PORTB change on interrupt. It was not happening... so i wrote the above sample code for just testing PORTB change on interrupt.

The above sample is to test only the port change interrupt. It works in a way that when i start, no display will come (displays are connected to PORTC). Whenever a voltage comes to PORTB RB7, (i have connected a swith to RB7) i am expecting the ISR will execute and change the value of sleep variable so that from the main() it will show the display connected to PORTC.

Please let me know if u need more explanation...
 
Where did you put the sleep instruction..?
Is it in the isr..? (refer to the code below).

static void interrupt
isr( void )
{
if ( RBIF )
{
sleep = 1;
SLEEP(); <----- is it here??
RBIE = 0;
RBIF = 0;
prev_portb=PORTB;
}
}

It is not possible for me or anyone to 'reproduce' the error to troubleshoot it if you leave those information out..

The purpose of you posting your code is so that we get the FULL picture and are able to reproduce your problem so that we can 'fix' it if need to..

So please fill in the blanks starting with where you place your SLEEP() instruction so that I can open up my Hi-Tech compiler, paste your code into it and run it if I need to.
 
Last edited:
OK. Leave everything...
What i am trying to do is to provide a backup power to my digital clock.

I have connected main power voltage to RB7 pin. Whenever RB7 goes down, i am enabling RBIE ( portb change-on-interrupt) and putting the PIC to sleep mode using SLEEP() instruction. Whenever power comes back, PIC will get a voltage on RB7. I am expecting a interrupt at this time. But this interrupt routine is not calling.

So I tested only this interrupt feature using below sample code.

//include file
#include <pic.h>

__CONFIG ( 0x3FB1 );

volatile unsigned char temp, value = 0;
unsigned char alarm = 0;

void showNumber ( unsigned char num );

//main function
void main ( void )
{
PEIE = 1;
GIE = 1;

TRISA = 0x0;
TRISC = 0x0;
TRISB = 0x0;
PORTB = 0;
PORTA = 0b00000001;

TRISB = 0b10000000;
temp = PORTB;
RBIF = 0;
RBIE = 1;
while ( 1 )
{
if ( value != 1 )
{
PORTC = 0b11111100;
}
else
{
PORTC = 0b00011000;
}
}
}

/*
Interrupt routine.
*/
void interrupt
isr( void )
{
if ( RBIF )
{
value = 1 - value; // Toggle value
temp = PORTB;
RBIF = 0;
}
}

Description of the test program:
For this test pgm, To portb RB7 pin I have connected a on/off switch which gives a +5V when its in ON condition. When i start the circuit, the value of variable value is 0 then it should display value 0 in the 7-segment-display using PORTC. When i turn on the switch, it should generate a portB change-on-interrupt and toggle the value of variable value to 1. This will inturn change the display value to 1 in the main program.

But what is actually happening is when the switch is in OFF condition, the interrupt routine is keep on calling. When switch is in ON condition, the interrupt is not calling. What actually i want here is to get only 1 intterrupt when any change in RB7 happens instead of continues intterrupts. Why the interrupt is not working when RB7 pin changes from 0 to 1?
 
My guess would be that when the switch is in the off position the pin is floating and picking up mains hum. Try putting a 10k resistor from RB7 to Ground.

Mike.
 
I guess i faced with this interrupt problem in MikroC on PIC16F690. Put the below code after checking RBIF flag in your ISR. It will reload PORTB with itself.

asm {
MOVF PORTB,1 ;Reload PORTB
BCF INTCON,0 ;Clear RBIF
}
 
Hey Pommie, your guess is absolutely correct, when when the switch is in the off position the pin is floating and picking up mains hum. I put a resistor from RB7 to ground and it solved the problem... great... Thanks a lot.
 
Glad to hear you got it sorted out.

You should still consider using the WPUs (weak pull ups) on portb. They are turned on by clearing bit 7 of the option register (probably RBPU=0;). You can then just have switches to ground without an external resistor.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top