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 CCS Technical Support

PIC18F4320 and sleep intrrupt

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



Joined: 22 Apr 2005
Posts: 15

View user's profile Send private message

PIC18F4320 and sleep intrrupt
PostPosted: Mon Apr 25, 2005 10:01 am     Reply with quote

Hello all,
My current project requires this chip to sleep and then wake up on its own. My problem is this, I need it to wake up anywhere from 10 seconds to 10 days. I want to use the external 32KHz osc. and Timer1. Is it possible to set Timer1 for anything past 8secs? I'm using a 4MHz Primary Xtal. I though about defining a byte called counter and when it hits a set value the isr will wake up the chip and run the program. As I am somewhat new to CCS and Microchip im not sure how the chip runs after it goes to sleep. Where in the code should it be running? In the While loop or in the isr? Any help with sample code would be great...

Regaurds,

Mike
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Mon Apr 25, 2005 1:59 pm     Reply with quote

Instructions do not execute in sleep. You could quickly wake up out of sleep every 8sec (I think 16sec is possible - with 16LF876) to check an incremented variable for longer times and the go back to sleep. You would probably have to have at least a 16-bit variable.

(1/32768)*65536(counter size)*8(prescaler) = 16sec
(60sec*60min*24hr*10days)/16sec = 54,000 (fits in a 16-bit variable)
_________________
-Matt
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

Re: PIC18F4320 and sleep intrrupt
PostPosted: Mon Apr 25, 2005 2:21 pm     Reply with quote

mharris27 wrote:
Hello all,
As I am somewhat new to CCS and Microchip im not sure how the chip runs after it goes to sleep. Where in the code should it be running? In the While loop or in the isr? Any help with sample code would be great...

mike,
as noted above, the PIC does not execute instructions during sleep. it sleeps very much the same way you do, and is woken up in very much the same manner:
1) by external stimuli (e.g. your alarm clock / PORTB change)
2) after the watchdog expires (e.g. you auto-wakeup after 8 hours or so).

so, to wake up, you can provide an external signal or you can let the PIC wake itself up by setting up the WDT appropriately. what you do after you wake up, again as noted above, can be dependent on how long you have been asleep. if not long enough, just go back to sleep. if long enough, it's time to get up and go to work.

note that after coming out of sleep, execution of your program continues with the next statement after sleep(). coming out of sleep does not reset your program to the beginning unless you code it that way. you don't forget everything you've ever learned after you come out of sleep, and neither does the PIC.

jds-pic
mharris27



Joined: 22 Apr 2005
Posts: 15

View user's profile Send private message

Please evaluate this.
PostPosted: Wed Apr 27, 2005 8:25 am     Reply with quote

I have written this code to sleep for 30 secs and then wake up when the counter hits the correct value. I want to use the 32.768KHz xtal when it is sleeping. Problem is that this code does not keep the right time. It seems that the rollover happens every 1.?? seconds. Would someone please look this over and help me what im doing wrong?

Thanks
regaurds
mike
Code:


#include <18f4320.H>
#fuses XT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOWDT,NOFCMEN,NOCPD,NOSTVREN
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_D1)    //Use for radio


long counter;         //isr counter



/////////////////////////////////////////////Blink LEDs/////////////////////////////////////////////////
void BlinkLeds()      //blink leds on reset and power up
{

output_high(pin_E0);   //Turn on Power LED
delay_ms(500);

output_high(pin_E2);   //Turn on Link LED
delay_ms(500);

output_high(pin_B4);   //Turn on Cal LED
delay_ms(500);
         ///////turn off all LED's/////////
output_low(pin_E2);      //Link LED
output_low(pin_B4);      //Cal LED
output_low(pin_E0);      //Power LED
}
////////////////Wake up interrupt//////////////////////////////////////////
#INT_TIMER1
void timer1_isr()
{
counter++;
if (counter <= 29)                // Enter one less than the amonut of delay in seconds

clear_interrupt(INT_TIMER1);
set_timer1(32768);             // setup timer1 for 1 sec rollover
sleep();
}
//////////////////////////////////////Main/////////////////////////////////
void main(){

setup_timer_1 (T1_EXTERNAL | T1_CLK_OUT | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);     //
enable_interrupts(GLOBAL);        //Required for tmr1 interrupt
set_timer1 (0);
counter = 0;

BlinkLeds();                  //blink leds


while(1)
{
setup_timer_1 (T1_EXTERNAL | T1_CLK_OUT | T1_DIV_BY_1);

if (counter >= 30)               //Inter the amount of delay in seconds.
clear_interrupt(INT_TIMER1);     
set_timer1(32768);
counter = 0;

output_high(pin_E2);            //Turn on Link LED
delay_ms(500);
output_low(pin_E2);               //Turn off Link LED
sleep();
#asm
NOP
NOP
#endasm
}
}                            //End of main
Ttelmah
Guest







PostPosted: Wed Apr 27, 2005 9:33 am     Reply with quote

Do a search in the forum on RTC's, or real time clocks.
General comments:
You do not need to clear the interrupt in the handler, unless you use the 'noclear' option. The handler does this for you automatically.
Generally, setting a timer 'to' a value, is dangerous for accuracy, because depending on the times involved, the timer may well already have advanced from zero. There have been a lot of threads about this in the past, and Neutone in particular has posted some code that handles generating a real 'time' value, with a clock that is not an even multiple of the frequency required. Though this does not apply in your case, some of the examples do show how to handle 'non 1 second' counting.
Though at 4Mhz, versus 32KHz, you would think there would be plenty of time to get to this point without the clock having advanced, this is definately _not_ true when using sleep. The wake-up from sleep, takes a long time when using a crystal oscillator, and so your clock will permanently lose time. Either use a 2 second counter, or use the CTC, to reset the counter for you.

Best Wishes
mharris27



Joined: 22 Apr 2005
Posts: 15

View user's profile Send private message

PostPosted: Wed Apr 27, 2005 10:01 am     Reply with quote

Thanks
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Wed Apr 27, 2005 10:32 am     Reply with quote

i think that you should use the WDT to wake up out of sleep, check a variable, and then do work when required. this would be simpler and easier to debug than all of the clock rate switching that is going on. moreover, it frees up a counter and power consumption will be lower as well.

jds-pic
Ttelmah
Guest







PostPosted: Thu Apr 28, 2005 3:03 am     Reply with quote

There is no 'clock rate switching'. he is using the ability of timer1, to run with an external clock. The 'problem' about the watchdog, is the extreme variability of the timings involved. I have seen over 4:1 variation in the timeout period between chip versions, and temperature changes.
If there is an external RTC, using the watchdog, is fine, but this will probably draw as much extra power, as running timer1.

Best Wishes
Guest








Re: Please evaluate this.
PostPosted: Mon May 02, 2005 3:03 pm     Reply with quote

Code:

////////////////Wake up interrupt//////////////////////////////////////////
#INT_TIMER1
void timer1_isr()
{
counter++;
if (counter <= 29)                // Enter one less than the amonut of delay in seconds

clear_interrupt(INT_TIMER1);
set_timer1(32768);             // setup timer1 for 1 sec rollover
sleep();
}


Not really sure about this. When it comes out of sleep, wont it exit the interrupt and and clear the interrupt flag. Wouldn't you miss the interrupt? I would set a flag in interrupt and then after the sleep(); in your main (the place you interrupt should return to), insert an if statment "if(sleep_flag == 1) sleep();" or a "while(sleep_flag);"
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Mon May 02, 2005 6:55 pm     Reply with quote

IMHO, going to sleep in an interrupt is bad programming practice.

jds-pic
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