|
|
View previous topic :: View next topic |
Author |
Message |
JMnemonic Guest
|
sleep and wakeup |
Posted: Wed May 18, 2005 11:29 am |
|
|
How to put 16C924 to sleep and how to wake him up ?
I know i must use sleep() but how to make him wake up? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 18, 2005 11:53 am |
|
|
Look at the CCS example file: EX_WAKUP.C
The file is in this folder: c:\Program Files\Picc\Examples |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Wed Jun 22, 2005 12:09 pm |
|
|
I have looked at the EX_WAKUP.C, the Feb 2005 manual, and the FAQs.
According to MicroChip's datasheet on the 18F8720:
"...can wake-up the processor from Sleep if bit INTxIE was set prior to going into Sleep."
So how do I set the INTxIE bit with CCS? The manual, header file, and example make no mention of wake up from sleep. Is the INTxIE bit always set? If so, they should mention that in their docs. If not, what am I missing?
-Kyle |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Wed Jun 22, 2005 12:59 pm |
|
|
The manual says "The user can wake from
Sleep through external Reset, Watchdog Timer Reset
or through an interrupt." Thus, I think you want to look into some sample code that triggers off of a external interrupt. The bit they talk about is set with enable_interrupts(INT_EXT); Or maybe IE is interrupt Enable set with the enable_interrupts(GLOBAL); Here is some code for 18F452
Code: | #INCLUDE <18F452.H>
#CASE
#USE DELAY(CLOCK=16000000)
#FUSES HS,NOWDT,NOPROTECT,NOLVP
#DEFINE VER_MAJOR 1
#DEFINE VER_MINOR 00
#USE RS232(BAUD=19200,XMIT=PIN_E0,INVERT,STREAM=DEBUG)
#ZERO_RAM
int8 debounce_count;
int8 keypad_debounce;
int8 lastkey;
#include "C:\ccs\Projects\ME_Lab\new_kpd.c"
#use fast_io (c)
int1 KEYPRESS;
//======================= MAIN ============================//
void main(void)
{
int8 key;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
fprintf(DEBUG,"\n\r");
fprintf(DEBUG,"STARTING New Keypad Test.\n\r");
fprintf(DEBUG,"FIRMWARE VERSION %u.%02u\n\r",VER_MAJOR,VER_MINOR);
KEYPRESS=FALSE;
kpd_init();
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
do
{
if(KEYPRESS)
{
key=kpd_getc();
KEYPRESS=FALSE;
fprintf(DEBUG,"%C ",key);
}
} while (TRUE);
}
//=======================RXisr============================//
#INT_EXT
void EXT_ISR(void)
{
KEYPRESS=TRUE;
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 22, 2005 1:29 pm |
|
|
Quote: | I have looked at the EX_WAKUP.C, the Feb 2005 manual, and the FAQs.
According to MicroChip's datasheet on the 18F8720:
"...can wake-up the processor from Sleep if bit INTxIE was set prior to going into Sleep." |
I feel like you left out quite a bit from the sentence in the data sheet,
or maybe you have an old version. In the data sheet I have, it says
this in Section 9.6:
Quote: |
All external interrupts (INT0, INT1, INT2 and INT3)
can wake-up the processor from Sleep if bit INTxIE
was set prior to going into Sleep. |
Then if you look in the 18F8720.H file, it lists the CCS parameters
that can be used to enable those interrupts with the enable_interrupts()
function:
Code: |
#define INT_EXT 0xF210
#define INT_EXT1 0xF008
#define INT_EXT2 0xF010
#define INT_EXT3 0xF020 |
You will also need to make an interrupt service routine (function). |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Wed Jun 22, 2005 2:01 pm |
|
|
Thanks for the quick reply, but I feel like you missed the whole point of my post. Perhaps I was not clear.
I have made many ISRs with CCS.
When I posted my question, I was trying to find out if CCS sets INTxIE so the processor wakes up from sleep on external interrupts. CCS neither specifies which way they set the bit, nor do they offer a way to change it from whichever way they have chosen in the header file.
I have spent a few man hours experimenting and researching and at this point I see they set it (wake from sleep) on all external interrupts. I wish they had either:
1) Specified this in the documentation for simplicity
2) Allowed me to choose if I wanted to wake from sleep using a bit OR operation like they do with everything else (timers, ccp, rtc, spi, etc.) for consistency.
-Kyle |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 22, 2005 2:34 pm |
|
|
I think that you've got the idea that the CCS sleep() function
does something with interrupts. It doesn't. It just puts in
a single SLEEP instruction in ASM code. Anything that's done
with interrupts, such as enabling them, is done by you, with code.
Example:
Code: |
enable_interrupts(INT_EXT1);
sleep();
#asm
nop
#endasm
|
|
|
|
Newbee Guest
|
|
Posted: Thu Jun 23, 2005 12:45 am |
|
|
I have similar question regarding wdt and wakeup on button switch ( which is not on INT pin ) and no one want's to answer....
If it's so easy to do then show us ( to us who dont know as much as you )...
http://www.ccsinfo.com/forum/viewtopic.php?t=23324 |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Thu Jun 23, 2005 1:05 am |
|
|
Newbee wrote: | I have similar question regarding wdt and wakeup on button switch ( which is not on INT pin ) and no one want's to answer....
If it's so easy to do then show us ( to us who dont know as much as you )... |
Okay.
Here's an example program I gave to a class. It uses an external interrupt, not the RB interrupt (sorry), but I'm not changing it to use the RB interrupt just for you (I guess I'm not sorry.)
This was written for use with the Micro Engineering Labs Lab-X1 board. You can find it (and a schematic) at www.melabs.com
Have fun with it.
Code: | #include <18F452.h>
#device adc=8
#fuses WDT,WDT128, XT, NOPROTECT, NOOSCSEN, BROWNOUT, BORV20, PUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=4000000,RESTART_WDT)
#use fast_io(B) // set up port b
#include "i:\ELEN\LCD Task\lcd_driver.c"
int8 number_of_sleeps, wakeup_cause;
int16 total_time_asleep;
// the watchdog has been set up to timeout every 2.3 sec or so
// I want to put the pic to sleep for about 23 seconds, then wake up and do something
// a button press (external interrupt) will reset the total_time_asleep
// any of the buttons in the top row will trigger this interrupt
#int_EXT
EXT_isr() {
total_time_asleep = 0;
restart_wdt();
lcd_putc("\fTotal time reset!");
}
void main() {
wakeup_cause = restart_cause(); // see what woke us up right away, as the data may be corrupted if we wait
// also beware the "#zero_ram" directive
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_ON);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
enable_interrupts(INT_EXT); // external interrupt on pin B0
ext_int_edge(0,H_TO_L); // falling edge causes interrupt
set_tris_b(0x01); // all output except pin b0
output_b(0x00); // all pins except b0 are low
port_b_pullups(TRUE); // make pin b0 high
// note that enabling the pullups will cause your current drain to be higher than you'd like
enable_interrupts(GLOBAL);
set_tris_e(0x00); // need this for the lcd
switch (wakeup_cause) { // what woke us up?
case NORMAL_POWER_UP: { // a plug-in from dead
// the first time it powers up, set number_of_sleeps to 10
number_of_sleeps = 10;
total_time_asleep = 0;
lcd_init();
lcd_putc("\fReady for bed!"); // stupid powerup message for us to determine if it's working correctly or not
break;
}
case WDT_TIMEOUT: { // watchdog woke us up
// if the watchdog woke it up, go ahead and decrement number_of_sleeps
if (--number_of_sleeps == 0) {
number_of_sleeps = 10; // reset the count
total_time_asleep = total_time_asleep + 23;
// print the total time it's been asleep
printf(lcd_putc,"\fBeen asleep for \n%lu:%02lu", total_time_asleep/60, total_time_asleep % 60);
}
break;
}
}
sleep();
delay_cycles(1); // the next instruction is prefetched - it may be a good idea
// to insert a nop after the sleep
while (TRUE){ // a way of ensuring that the pic doesn't get to the hidden sleep() at the end of main
}
} |
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Thu Jun 23, 2005 1:32 am |
|
|
Newbee wrote: | I have similar question regarding wdt and wakeup on button switch ( which is not on INT pin ) and no one want's to answer....
If it's so easy to do then show us ( to us who dont know as much as you )...
http://www.ccsinfo.com/forum/viewtopic.php?t=23324 |
"Newbee" does not appear as the author of any thread section in the thread you pointed to therefore it is difficult to respond to this point. However, after having reread the entire thread all outstanding points were answered with the exception of the one from guest, guest who wanted to delay 10 hours then "hit" the wdt. If you are refering to this particular requirement then two things, you do not understand what a watchdog timer does, and the second you are asking for a specific implementation that has to be written for you.
The WDT is a free running timer that once runing will eventually reset the processor unless the WDT is cleared under program control. Clearing the WDT simply resets the count. The WDT timer will keep running and will eventually reset the CPU is not continually reset. Therefore you do not "hit" the wdt after 10 hours to cause a reset, instead you must "hit" it continuously to stop it reseting the CPU and, in your case, stop "hitting" it after 10 hours which will result in the WDT timing out and reseting the CPU. But why stuff around doing this on a 16F processor when you can achieve virtually the same effect by resetting the code and data pages to 0 and doing a goto 0? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Last edited by asmallri on Thu Jun 23, 2005 7:18 am; edited 1 time in total |
|
|
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
|
Posted: Thu Jun 23, 2005 7:11 am |
|
|
PCM programmer wrote: | I think that you've got the idea that the CCS sleep() function
does something with interrupts. It doesn't. It just puts in
a single SLEEP instruction in ASM code. Anything that's done
with interrupts, such as enabling them, is done by you, with code.
|
I am a senior programmer with long PIC experience (including ISRs) going back to the early 90s. This is the first project where I have had the experience of sleeping a processor that has ISRs on external pins. I was confused about it. MicroChips docs fueled the confusion, and CCS's docs don't do anything to clear the confusion. Looking at the numerous threads on the forum I believe I am not the only one to be confused about mixing sleep and interrupts.
MicroChip should probably change their wording a bit to indicate the interrups WILL wake the device from sleep instead of that they CAN wake them from sleep if this bit is set. I, like most others, infer that this is a "wake from sleep on interrupt" bit that CCS has not given the programmer control of. It was not until I got to the bit level of what #define INT_EXT1 was setting that I figured it out. CCS does not explain the settings, they simply give them to you, expect you to know the processor, know the language, and make a leap of faith on how the header files are created. I can live with the first two, but the leap of faith on the defines often proves problematic. If one needs to understand which bits are being set to what values (as in this case), there is no documentation that I am aware of to show how they map things like:
#define INT_EXT1 0xF008
into the actual registers of the processor.
I doubt they will help us out by making and publishing a map. But since this is particular case is clearly a point of confusion, CCS could help their programmers out by mentioning (or being more clear) in either the ENABLE_INTERRUPTS() or SLEEP() section, that devices who support external interrupts will be woken from sleep automatically when an external interrupt occurs, if that interrupt is left enabled when the sleep function is called. It would be just that simple if they would be willing to make the effort.
Many thanks for helping me wade through this issue, Mr. or Mrs. "PCM Programmer".
-Kyle |
|
|
Guest Guest
|
|
Posted: Thu Jun 23, 2005 8:51 am |
|
|
I don't know if its better to write newbee or guest cuz am both of this:-)
This is the question:
Quote: |
I have the same problem... I want to restart the whole program on button press. That should be exactly like connecting to MCLR. (restart_wdt and make reset). My reset switch is not connected to MCLR...
|
|
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Thu Jun 23, 2005 9:03 am |
|
|
If it s a PIC18 use reset_cpu()
if not then use reset_cpu() and know that the registers also need to be reset.
see documentation on reset_cpu()
OR
tie an output pin to mclr and lower that pin on the button press. |
|
|
|
|
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
|