pic16f88 sleep mode and wake on interrupt

Thread Starter

gatoulisss

Joined Jan 23, 2015
55
hello everyone!

I need your help, im using mikro c and trying to use sleep mode on a pic16f88 mcu and wake from a interrupt on RB0 pin (I use internal osc)
what I want to do is a simple project so I can understand how to use sleep mode, for example:

I have a sensor on RB0 pin, when this is '1' then a led will blink, when it goes '0' for more than 3secs then the mcu goes to sleep till RB0 goes '1' again and then repeat the process.


can anyone help me with the code? thank you!
 

nsaspook

Joined Aug 27, 2009
6,473
It's pretty simple.

Example code frag for a PIC18 but a mikro c version for pic16f88 should be much the same.
C:
/*
* shutdown the controller if nothing is happening
*/
if (V.sleep_ticks > SLEEP_COUNT) {
LED1 = 0;
LED2 = 0;
RPMLED = 0;
OSCCON = 0x00; // sleep, no clocks
Sleep();
OSCCON = 0x72;
}
A timer interrupt ISR counter increments V.sleep_times and the external interrupt ISR resets V.sleep_times back to zero. If the external interrupt stops V.sleep_times increases until past SLEEP_COUNT after SLEEP_COUNT+1 triggers. A this point we Sleep().

https://raw.githubusercontent.com/nsaspook/mass_slit/fixes/pat.c
 

Thread Starter

gatoulisss

Joined Jan 23, 2015
55
It's pretty simple.

Example code frag for a PIC18 but a mikro c version for pic16f88 should be much the same.
C:
/*
* shutdown the controller if nothing is happening
*/
if (V.sleep_ticks > SLEEP_COUNT) {
LED1 = 0;
LED2 = 0;
RPMLED = 0;
OSCCON = 0x00; // sleep, no clocks
Sleep();
OSCCON = 0x72;
}
A timer interrupt ISR counter increments V.sleep_times and the external interrupt ISR resets V.sleep_times back to zero. If the external interrupt stops V.sleep_times increases until past SLEEP_COUNT after SLEEP_COUNT+1 triggers. A this point we Sleep().

https://raw.githubusercontent.com/nsaspook/mass_slit/fixes/pat.c

I was thinking something like the code below but it seem mcu never goes to sleep
Code:
int k;

void main() {
osccon=0x70;                 // set osc
ansel=0;                     //  set analog
intcon.inte=1;               // enable RB0/INT

trisb.f0=1;                 //set RB0 as input
trisb.f3=0;                 //set RB3 as output

for (;;) {
start:
while (portb.f0==1){         //  led blink till RB0=0
portb.f3=0;
delay_ms(400);
portb.f3=1;
delay_ms(400);}
if (portb.f0==0){
k=1;
delay_ms (3000);
if (portb.f0==0 && k==1){    //check RB0=0 for more than 3secs and then sleep
intcon.gie=0;             //clear GIE before sleep
portb.f3=0;
asm sleep;}
else{
k=0;
goto start;}
}
}
}
any help?
 

Ian Rogers

Joined Dec 12, 2012
666
Try not to use "goto" in C... In your example it does "goto start" anyway...

I would have thought the opposite... You unset interrupts before you sleep... It shouldn't wake up!!

Has this device a soft ware watchdog setting???
 

Thread Starter

gatoulisss

Joined Jan 23, 2015
55
Try not to use "goto" in C... In your example it does "goto start" anyway...

I would have thought the opposite... You unset interrupts before you sleep... It shouldn't wake up!!

Has this device a soft ware watchdog setting???
yes it has, I have disable watchdog timer
it wakes up beacause it doesn't sleep I think , when I measure the current when it should sleep the led is off like it had to but the current is 2-2,40mA so its not at sleep mode
 

nsaspook

Joined Aug 27, 2009
6,473
From the 'net'.
INTCON.GIE (the global interrupt enable) does *NOT* have to be set (enabled) to wake up from sleep. The individual interrupt enable for the chosen wakeup interrupt source *MUST* be set, as well as INTCON.PEIE for any source that doesn't have its flags in INTCON. See fig 15-7 and section 15.13. The advantage of not enabling GIE is that after wakeup, execution continues immediately after the SLEEP instruction, instead of calling the ISR, simplifying your code. Rem,ember all possible enabled wakeup interrupt sources *MUST* have their interrupt flags cleared to enter sleep successfully. The system clock stops in sleep so either monitor the crystal, or if using the internal oscillator, enable Fosc/4 output on the Osc2 pin and monitor that to confirm it has successfully entered sleep mode.

To enter sleep mode using MikroC, use:
asm{SLEEP}; // enables sleep mode
Try clearing the interrupt flag (INT0IF I think) before 'sleeping'.
C:
void main()
{
    osccon = 0x70; // set osc
    ansel = 0; //  set analog
    intcon.inte = 1; // enable RB0/INT

    trisb.f0 = 1; //set RB0 as input
    trisb.f3 = 0; //set RB3 as output

    for (;;) {
start:
        while (portb.f0 == 1) { //  led blink till RB0=0
            portb.f3 = 0;
            delay_ms(400);
            portb.f3 = 1;
            delay_ms(400);
        }
        if (portb.f0 == 0) {
            k = 1;
            delay_ms(3000);
            if (portb.f0 == 0 && k == 1) { //check RB0=0 for more than 3secs and then sleep
                intcon.gie = 0; //clear GIE before sleep
                portb.f3 = 0;
                asm sleep;
            } else {
                k = 0;
                goto start;
            }
        }
    }
}
http://ww1.microchip.com/downloads/en/DeviceDoc/01146B_chapter 2.pdf
 
Last edited:
Top