|
|
View previous topic :: View next topic |
Author |
Message |
jpage
Joined: 23 Jun 2004 Posts: 24
|
Timer1() and Sleep() Code Basics |
Posted: Wed Sep 22, 2004 12:36 pm |
|
|
Hi,
I just wanted to get some basics to get me started in the right direction.
This is what I want to do:
I need to be able to place a PIC18F4320 to sleep and only turn on the PIC at a certain interval (this can vary from once every 1sec to once every 24hrs---depending on customer request).
I will be implementing an external clock 32.728Khz for use in sleep mode.
I want to implement the Timer1 interrupt right before the sleep function and, of course, wakeup after the correct time interval and then sleep until the next interval.
Just for testing, I want to blink an LED for the set time interval.
I'm not quite sure how to 'fire' on Timer1() and exactly what code needs to go into TIMER1_isr() .
This is some basic code that I have:
Code: |
#int_TIMER1
TIMER1_isr()
{
code
}
void main(){
int x;
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1 | T1_CLK_OUT); // 1:1 Prescalar Value
TMR1ON = 0; //turn off timer1
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(0);
for (x=0;x<=2;++x){
output_high(POWER_LED); //test OK indicator//
#ifdef NormalCode
delay_ms(500);
#endif
output_low(POWER_LED);
#ifdef NormalCode
delay_ms(500);
#endif
}
TMR1ON = 1;//turn on timer1
sleep();
TMR1ON = 0;///turn off timer1
for (x=0;x<=2;++x)
output_high(LINK_LED); //test up OK indicator//
#ifdef NormalCode
delay_ms(500);
#endif
output_low(LINK_LED);
#ifdef NormalCode
delay_ms(500);
#endif
}
|
Any help will be appreciated. Thanks. |
|
|
ninjanick
Joined: 25 May 2004 Posts: 25
|
|
Posted: Wed Sep 22, 2004 11:52 pm |
|
|
Not really sure if TIMER1 is active during SLEEP. Might want to check the datasheet. But as a suggestion, you could do exactly what you want with the WDT. |
|
|
jpage
Joined: 23 Jun 2004 Posts: 24
|
Timer1() and Sleep() Code Basics |
Posted: Thu Sep 23, 2004 8:46 am |
|
|
Thanks. I'll check out the datasheet.
I just thought that since I was using an external XTAL (32.728Khz) on Timer1, it would continue running (counting) while the main processor clock (4MHZ) turned off.
I would use the WDT, but this is a battery operated device that we are trying to minimize current and it looked like this (Timer1) would be the best method. I think the WDT uses the internal clock and will draw more current than if the uP was completely asleep.
This is basically what I want to do:
Run the Main() program
Sleep()
Enable the Timer1() ISR
After Timer1() timeout --return or resume to Main()
Start whole process over again using forever loop --While(1)
Note: Would like the uP to Sleep anywhere from 1sec to 24hrs
Will the above sequence work??
When Timer1() timeouts and exits ISR, will this automatically wake up the processor??
Thanks for any help. |
|
|
jpage
Joined: 23 Jun 2004 Posts: 24
|
Timer1() and Sleep() Code Basics |
Posted: Thu Sep 23, 2004 12:05 pm |
|
|
Just wanted to get a reality check on the code below.
I want to blink an LED 2 times and then put the uP in sleep mode.
Sleep mode will shut down the internal XTAL and start the External
XTAL (32.728Khz). Timer1() will start counting up to 65,536 (2 seconds) and then rollover to 0 which will trigger an interrupt and wake the uP.
Can anyone give me any feedback on this??
Thanks.
Code: |
#include <18f4320.H>
#fuses HS,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay (clock=4000000)
#define POWER_LED PIN_E0
#define NormalCode
#int_TIMER1
void timer1_isr()
{
set_timer1(0);
}
void main()
{
int x;
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1 | T1_CLK_OUT); // 1:1 Prescalar Value
enable_interrupts(GLOBAL);
while(1){
for (x=0;x<=2;++x)
{
output_high(POWER_LED); //test OK indicator//
#ifdef NormalCode
delay_ms(500);
#endif
output_low(POWER_LED);
#ifdef NormalCode
delay_ms(500);
#endif
}
enable_interrupts(INT_TIMER1);
sleep();
}
return;
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Sep 23, 2004 4:30 pm |
|
|
Basically I think your code should work, but there is some room for optimizations.
1) Your #fuses line
Code: | #fuses HS,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP |
You can save a little more power by disabling the internal RC-oscillator, for this both the watchdog and the Fail-Safe Clock Monitor must be disabled.
- Add NOWDT to disable the watchdog.
- Add NOFCMEN to disable the Fail-Safe Clock Monitor.
2) Sorry, your interrupt routine makes no sense.
The interrupt is called on the rollover to 0, so why set Timer1 to 0 again? You can remove this line and leave your interrupt funtion empty. The only reason for having your interrupt function would then be to clear your interrupt (the compiler takes care of this for you).
A further improvement is to remove the interrupt routine at all. Check Chapter 28.4 of the PIC18C Reference Manual, here is explained that the PIC will awake from sleep when the interrupt enable bit for timer1 is set. But, by not setting the Global Interrupt Enable bit, the PIC will not execute an interrupt and continue directly with the instruction after the sleep().
3) Just a design note: I don't know what your circuit looks like, but be aware that floating inputs can generate a considerable current consumption caused by noise causing high frequent switching from low to high state. This bit me once. After reset most I/O ports are configured as inputs, just make sure all (unused) inputs are connected to Vdd or Vss.
4) Do not return from main().
At the end of your main() function you have a return statement, this doesn't belong there. The main function never has a return statement because nobody ever called it. In some other compilers you would place a call to exit() here to exit your program but in CCS you don't. CCS will automatically add a sleep() to the end of your program.
5) Your LED will blink 3 times, not 2 times.
Change the '<=' to '<'.
All changes added to your code:
Code: | #include <18f4320.H>
#fuses HS,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP, NOWDT, NOFCMEN // Added NOWDT and NOFCMEN
#use delay (clock=4000000)
#define POWER_LED PIN_E0
#define NormalCode
// Removed interrupt function
//#int_TIMER1
//void timer1_isr()
//{
// set_timer1(0);
//}
void main()
{
int x;
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1 | T1_CLK_OUT); // 1:1 Prescalar Value
// enable_interrupts(GLOBAL); // Not required
enable_interrupts(INT_TIMER1); // Moved out of loop
while(1)
{
for (x=0;x<2;++x) // Changed '<=' to '<'
{
output_high(POWER_LED); //test OK indicator//
#ifdef NormalCode
delay_ms(500);
#endif
output_low(POWER_LED);
#ifdef NormalCode
delay_ms(500);
#endif
}
// enable_interrupts(INT_TIMER1); // Moved out of loop
sleep();
clear_interrupt(INT_TIMER1); // added
}
// return; // Removed
} | [/quote] |
|
|
jpage
Joined: 23 Jun 2004 Posts: 24
|
Timer1() and Sleep() Code Basics |
Posted: Thu Sep 23, 2004 8:39 pm |
|
|
Thanks very much for your comments, ideas, and suggestions.
It was very helpful.
I appreciate the heads up on floating pins and tieing them high or low.
With the code right now, the uP will blink the LED and then sleep for 2 seconds, wakeup, and repeat forever.
If I want to lengthen the sleep time to a preset value, do I just increment a counter and keep track of the counter in the main() with a while loop??
Something like this:
Code: |
int counter = 0;
#int_TIMER1
void timer1_isr()
{
counter++
}
void main()
{
.
.
.
while (counter < 2){// loops 3 times to keep in sleep mode for 6 sec.
enable_interrupts(INT_TIMER1); // Moved out of loop
sleep();
clear_interrupt(INT_TIMER1); // added
}
)
|
Thanks again. |
|
|
|
|
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
|