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

Question on waking up from sleep (ULPWU)

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



Joined: 20 Mar 2010
Posts: 9

View user's profile Send private message

Question on waking up from sleep (ULPWU)
PostPosted: Sat Mar 20, 2010 9:51 am     Reply with quote

Hi,
I am using a PIC16F886. I want to use the ULPWU function. I would like the pic to wake up periodically or by an external interrupt. The ULPWU interrupt works but when it wakes up it goes to the ULPWU isr. I would like any interrupt to just wake up processor and perform code after the sleep statement without going to a ISR. Is this possible?
I am using CCS compiler the latest version.
Code:

main()
{
   setup_adc_ports(sAN1|sAN2|sAN3|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_8);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard

 /* these interrupts are enabled after wake up from ulpwu

     // enable_interrupts(INT_EXT);
    // enable_interrupts(INT_EXT|INT_EXT_H2L);
   // enable_interrupts(INT_EXT_H2L);
  //enable_interrupts(INT_TIMER1);
  // enable_interrupts(INT_TIMER0);
  //
 
*/

   enable_interrupts(INT_ULPWU);     // must be enabled, works but always goes to isr I want to goto next statement after sleep / nop
                                                    // if not enabled does not wake up on time out

   enable_interrupts(GLOBAL);          // global interrupt enable
   setup_oscillator(OSC_4mHZ);
   port_b_pullups(0x01);
 


while(1)                                            // main sleep loop will stay in here
{

output_high(pyro_enbl);
output_high(gain_enbl);
output_high(light_enbl);

sleep_ulpwu(400);                      // this puts out 400us pulse to charge cap and put to sleep
//delay_cycles(1);


//                         I would like to wake up and go here regardless of the interrupt cause then return to main sleep loop I will determine cause of interrupt


//                          below is test code only.


do
{

/*
now we have to go and see why we woke up.

check status of radio int if low, then get status and word

next check to see light level and put in buffer

next check pyro and get level to store

if was normal ulpwu then go back to sleep

else
turn off ulpwu  int
turn on light if warranted. ie radio or change or pyro
*/

if (!input(radio_int))
{
/*
go read radio status

*/
}


set_adc_channel (1);

light_in=get_voltage();

if(light_in > 700)
{
shift_left(upper_level,1,1);
}


if(light_in < 300)
{
shift_left(lower_level,1,1);
}


if ((upper_level==7 & Lower_level==1) & (light_in < 200))        //check result of filter
{
// light was on and went off
// turn on light
lite_on=true;
}


if (light_in<200)
{
set_adc_channel (3);         //get pyro reading

pyro_in=get_voltage();

if (pyro_in>last_pyro_in)
{

lite_on=true;               /// have to add some filtering here
}

last_pyro_in=pyro_in;

}

lite_on=true;
if (lite_on)
{


full_power();

while(lite_on & (sec_run< 10))
{
}

two_thirds_power();

while(lite_on & (sec_run< 20))
{
}

one_third_power();

while(lite_on & (sec_run< 30))
{
}


output_low(led_cntl);



}         ///        end of if lite on

}while(1);

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 21, 2010 3:48 pm     Reply with quote

I think there are problems with the CCS sleep_ulpwu() function.
Rather than try and fix it right now, I've posted a work-around routine
and a test program below.

I have a 100 nF (0.1 uF) capacitor connected between pin A0 and ground.
The code program will charge up the capacitor, go to sleep, then let the
cap bleed off it's voltage to ground, and then wake-up. Two LEDs show
the progress of the program. I timed it with a stopwatch, and it takes
about 1.6 seconds for the 2nd LED to turn on. The charge time of 1ms
is overkill. It could probably be reduced to 100us for this cap size.
Code:

#include <16F886.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#byte PCON = 0x8E   // Register address for 16F886
#bit ULPWUE = PCON.5

#define INT_PEIE  0x0B40

#define my_sleep_ulpwu(x)  \
  output_high(PIN_A0);     \
  if(x / 1000)             \ 
     delay_ms(x / 1000);   \ 
  if(x % 1000)                  \   
     delay_us(x % 1000);        \
  clear_interrupt(INT_ULPWU);   \
  ULPWUE = 1;                   \   
  output_float(PIN_A0);         \
  enable_interrupts(INT_PEIE);  \
  enable_interrupts(INT_ULPWU); \
  sleep();                      \
  disable_interrupts(INT_ULPWU)

//=======================================     
void main()
{
output_high(PIN_B0);  // Turn on LED0 to show program start

my_sleep_ulpwu(1000);   // 1000us charge time for 100 nF cap

output_high(PIN_B1);  // Turn on LED1 to show ULP wake-up.

while(1);
}
armondo_522



Joined: 20 Mar 2010
Posts: 9

View user's profile Send private message

thanks
PostPosted: Sun Mar 21, 2010 3:56 pm     Reply with quote

Thank you, I think my biggest problem was that I enabled the global interupt and that brought me to the isr instead of the statement after sleep, but I will try your method to give me a work around in case the ccs version does not work.

Thanks again, your responses are always right on the money.

Regards,
Pulsartomi



Joined: 26 May 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed May 26, 2010 1:17 pm     Reply with quote

Thank You for providing this code, solved my problem with wake up with ulwp pin. CCS not seems to be working with sleep_ulwp();
Pulsartomi



Joined: 26 May 2010
Posts: 17

View user's profile Send private message

PostPosted: Thu May 27, 2010 7:11 am     Reply with quote

VERY BIG ATTENTION:
disable other interrupts if you enabled before (for eg TIMER1), or it will wake up before it would be desired (the ulpwu timing) even if global interrupts is disabled!
If you are not sure what is the wake up timing, use a voltmeter on the capacitor. Although it will discharge the capacitor faster because of the impedance of the voltmeter.
Pulsartomi



Joined: 26 May 2010
Posts: 17

View user's profile Send private message

PostPosted: Sun Jun 06, 2010 1:50 pm     Reply with quote

New problem Exclamation
I would like to use this routine with 18f46j11, but in compiler there is no INT_ULPWU defined for this device (although it has ulpwu).
Before i wanted to use sleep_ulpwu(); but compiler returned an error: undefined identifier (use delay is ok, because delay_ms(); is working)
Does anybody know why is it undefined?With other device it is "defined".
My question would be if i can use somewhat sleep_ulwpu function.
And the other: where can I find int_uplwu?
Thanks
Here are the defined int addresses:
Code:

////////////////////////////////////////////////////////////////// INT
// Interrupt Functions: ENABLE_INTERRUPTS(), DISABLE_INTERRUPTS(),
//                      CLEAR_INTERRUPT(), INTERRUPT_ACTIVE(),
//                      EXT_INT_EDGE()
//
// Constants used in EXT_INT_EDGE() are:
#define L_TO_H              0x40
#define H_TO_L                 0
// Constants used in ENABLE/DISABLE_INTERRUPTS() are:
#define GLOBAL                    0xF2C0
#define INT_RTCC                  0x00F220
#define INT_TIMER0                0x00F220
#define INT_TIMER1                0x009D01
#define INT_TIMER2                0x009D02
#define INT_TIMER3                0x00A002
#define INT_EXT_L2H               0x5000F210
#define INT_EXT_H2L               0x6000F210
#define INT_EXT                   0x00F210
#define INT_EXT1_L2H              0x5001F008
#define INT_EXT1_H2L              0x6001F008
#define INT_EXT1                  0x00F008
#define INT_EXT2_L2H              0x5002F010
#define INT_EXT2_H2L              0x6002F010
#define INT_EXT2                  0x00F010
#define INT_RB                    0x00FFF208
#define INT_AD                    0x009D40
#define INT_RDA                   0x009D20
#define INT_TBE                   0x009D10
#define INT_SSP                   0x009D08
#define INT_CCP1                  0x009D04
#define INT_CCP2                  0x00A001
#define INT_BUSCOL                0x00A008
#define INT_COMP                  0x00A040
#define INT_RDA2                  0x00A320
#define INT_TBE2                  0x00A310
#define INT_TIMER4                0x00A308
#define INT_OSCF                  0x00A080
#define INT_BUSCOL2               0x00A340
#define INT_EXT3_L2H              0x5003F020
#define INT_EXT3_H2L              0x6003F020
#define INT_EXT3                  0x00F020
#define INT_PMP                   0x009D80
#define INT_SSP2                  0x00A380
#define INT_RTC                   0x00A301
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jun 06, 2010 3:16 pm     Reply with quote

Look in the 18F46J11 data sheet. It doesn't mention a ULPWU interrupt.
It says to use an INTx interrupt:
Quote:

3.7 Ultra Low-Power Wake-up

The Ultra Low-Power Wake-up (ULPWU) on RA0 allows
a slow falling voltage to generate an interrupt without
excess current consumption.
Follow these steps to use this feature:
1. Configure a remappable output pin to output the
ULPOUT signal.
2. Map an INTx interrupt-on-change input function
to the same pin as used for the ULPOUT output
function. Alternatively, in step 1, configure
ULPOUT to output onto a PORTB
interrupt-on-change pin.

In CCS, the pin mapping is done with the #pin_select directive.

The 18F46J11 data sheet has sample code here:
Quote:

EXAMPLE 3-1: ULTRA LOW-POWER WAKE-UP INITIALIZATION

That code can be translated to CCS, by using #byte and #bit statements
to allow direct access to register bits. CCS delay_us() or delay_ms()
can be used to do the required delay time. Etc.

For example 3-1, the Pin Select statements for CCS that do the same
thing as the top two lines in the example code, would look like this:
Code:

#include <18F46J11.h>
#fuses HS,NOWDT 
#use delay(clock=20000000)

#pin_select ULPOUT=PIN_D4
#pin_select INT1=PIN_D4

//=====================================
void main()
{

while(1);
}

You should attempt to write the code by yourself and debug it.
Pulsartomi



Joined: 26 May 2010
Posts: 17

View user's profile Send private message

PostPosted: Sun Jun 06, 2010 3:21 pm     Reply with quote

At the same time You replied, I've read that in the datasheet. I've just started to write the code and didn't know this mapping command.
Thank You very much for your help Razz

Best Regards, Tomi
Pulsartomi



Joined: 26 May 2010
Posts: 17

View user's profile Send private message

PostPosted: Sun Jun 06, 2010 5:36 pm     Reply with quote

bit_set(INTCON,6); //don't forget to enable peripherial interrupts before sleep();
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