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

Sleep_ulpwu()

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



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

Sleep_ulpwu()
PostPosted: Wed Jan 02, 2008 10:48 am     Reply with quote

Can someone provide me with some insight as to what the Sleep_ulpwu() does differently than sleep()?

I ask this because my complier version is 3.249 and doesn't have the function. I spent several days over the holiday trying to get my PIC12F635 to sleep and wake using the ULPWU module, but nothing seemed to work. I have no code to post because I was on a different computer and had no internet access (Yikes!). I was trying to follow all recommendations in the datasheet, but of course their example is in assembly and assumed proper mapping of the registers.

Since ULPWU was not addressed in my compiler version I found myself directly writing to registers that were not defined in the include file. I also do not understand how to interpret the address of the INTCON register. The datasheet tells me that INTCON address is 0Bh/8Bh. Is this a high byte / low byte deal?

Perhaps someone has a working example of using the ULPWU module in an earlier complier version that did not use sleep_ulpwu()?

Thanks,

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 02, 2008 12:10 pm     Reply with quote

The easiest way to answer this is to show you the .LST file output
for vs. 4.064 and then you can use that as a guide to write your
own function for your version of the compiler. When you write
your code, compile it, and compare the .LST file to the one below.
Make sure that it's effectively doing the same thing.
Code:

#include <12F635.h>
#fuses XT, NOWDT, NOMCLR, PUT, BROWNOUT
#use delay(clock=4000000)

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

sleep_ulpwu(10);

while(1);
}

Here's the .LST file code for that program.

Code:
.................... void main() 
.................... { 
0004:  CLRF   04
0005:  MOVLW  1F
0006:  ANDWF  03,F
0007:  CLRF   1A
0008:  MOVLW  07
0009:  MOVWF  19
.................... 
.................... sleep_ulpwu(10);
000A:  MOVF   19,W
000B:  MOVWF  40
000C:  MOVLW  07
000D:  MOVWF  19
000E:  BSF    03.5
000F:  BCF    1F.0
0010:  BCF    05.0
0011:  BCF    03.5
0012:  BSF    05.0
0013:  BSF    03.5
0014:  BSF    05.0
0015:  BCF    03.5
0016:  BCF    0D.2
0017:  MOVLW  03
0018:  MOVWF  40
0019:  DECFSZ 40,F
001A:  GOTO   019
001B:  BSF    03.5
001C:  BSF    0E.5
001D:  BCF    0D.2
001E:  BSF    16.0
001F:  BCF    03.5
0020:  MOVF   0B,W
0021:  MOVWF  41
0022:  MOVLW  08
0023:  MOVWF  0B
0024:  SLEEP
0025:  MOVF   41,W
0026:  MOVWF  0B
0027:  MOVF   40,W
0028:  MOVWF  19
.................... 
.................... while(1);
0029:  GOTO   029
.................... }


Same thing, but in Symbolic format:
Code:
.................... void main() 
.................... { 
0004:  CLRF   FSR
0005:  MOVLW  1F
0006:  ANDWF  STATUS,F
0007:  CLRF   CMCON1
0008:  MOVLW  07
0009:  MOVWF  CMCON0
.................... 
.................... sleep_ulpwu(10);
000A:  MOVF   CMCON0,W
000B:  MOVWF  @40
000C:  MOVLW  07
000D:  MOVWF  CMCON0
000E:  BSF    STATUS.RP0
000F:  BCF    09F.0
0010:  BCF    TRISO.TRISIO0
0011:  BCF    STATUS.RP0
0012:  BSF    GPIO.GP0
0013:  BSF    STATUS.RP0
0014:  BSF    TRISO.TRISIO0
0015:  BCF    STATUS.RP0
0016:  BCF    00D.2
0017:  MOVLW  03
0018:  MOVWF  @40
0019:  DECFSZ @40,F
001A:  GOTO   019
001B:  BSF    STATUS.RP0
001C:  BSF    PCON.ULPWUE
001D:  BCF    08D.2
001E:  BSF    IOCA.IOCA0
001F:  BCF    STATUS.RP0
0020:  MOVF   INTCON,W
0021:  MOVWF  @41
0022:  MOVLW  08
0023:  MOVWF  INTCON
0024:  SLEEP
0025:  MOVF   @41,W
0026:  MOVWF  INTCON
0027:  MOVF   @40,W
0028:  MOVWF  CMCON0
.................... 
.................... while(1);
0029:  GOTO   029
.................... }
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jan 02, 2008 12:15 pm     Reply with quote

Quote:
Can someone provide me with some insight as to what the Sleep_ulpwu() does differently than sleep()?
Which part did you not understand from reading the manual? Even when you have v3.249, the latest manual is free for download from the CCS website.

Quote:
I also do not understand how to interpret the address of the INTCON register. The datasheet tells me that INTCON address is 0Bh/8Bh. Is this a high byte / low byte deal?
The PIC12 and PIC16 processors have the RAM addresses divided into banks of 0x80 bytes. Switching from one bank to the other takes a few instructions and because the INTCON register is used so often Microchip has decided to duplicate (mirror) the same register in both memory banks. So using either of the two mentioned addresses you are accessing exactly the same physical register.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Jan 02, 2008 12:16 pm     Reply with quote

Quote:

Can someone provide me with some insight as to what the Sleep_ulpwu() does differently than sleep()?

From:
http://www.ccsinfo.com/content.php?page=v4compiler

sleep_ulpwu(us) - Sets the ultra-low power wakeup pin high for the set micro-seconds (which will charge the user's capacitor), then put's the PIC® MCU to sleep. When the capacitor has discharged, the PIC® MCU will awaken (this time is determined by the user's RC time constant). Requires a PIC® MCU with the ultra-low power wakeup feature (see the GP0 on the PIC12F683).

Humberto
hansknec



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

PostPosted: Wed Jan 02, 2008 12:24 pm     Reply with quote

Thanks all.

I didn't know I could access the latest manual, and that .LST file will be great for double checking my register assignments.

I'll give it another shot with this new info.
hansknec



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

PostPosted: Wed Jan 02, 2008 12:39 pm     Reply with quote

So now I can see that:

sleep_ulpwu(10);

is exactly the same as:

output_high(PIN_A1);
delay_us(10); // charge cap for 10us
code to make A1 an input, enable the ULPWU bit, and enable the interrupt.
sleep();
hansknec



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

sleep_ulpwu problems.
PostPosted: Wed Apr 30, 2008 8:02 pm     Reply with quote

I have a problem with the new sleep_ulpwu command.
Compiler version=PCWHD 4.071

I wrote the following code before getting an upgraded compiler that had the sleep_ulpwu command:

Code:
#include <12F635.h>

#FUSES NOMCLR,NOWDT,NOBROWNOUT,INTRC_IO
#use delay(clock=8000000)

#BIT ULPWU = 0x8E.5   // PCON bit 5 enables the ULPWU
#BYTE INTCON = 0x8b   // entire INTCON register
#BYTE PIR1 = 0x0c     // Peripheral interrupt flags  (0 to clear)
#BIT WOC1 =  0x8b.1   // Wake up on change interrupt flag  (0 to clear)
#BIT IOC0 =  0x96.0   // interrupt on change for pin A0 (1 to set)


#INT_DEFAULT   // interrupt service routine for ULPWU sleep module
   void isr_DEFAULT()  {
      PIR1 = 0;       //clear the peripheral interrupt flags
      WOC1 = 0;       //clear the wake on change interrupt flag
      }
     
void main() {
  setup_comparator(NC_NC);
  setup_vref(FALSE);
  setup_oscillator(OSC_8MHZ);
 
  while (1){
  output_high(PIN_A4);  // pulse high to show wakeup
  delay_ms(4);          // wait 4ms
  output_low(PIN_A4);   // back low
 
 // begin setup of ULPWU module using a manual configuration
   output_high(PIN_A0);      // high on A1 to charge the cap
   delay_us(10);             // let it charge
   set_tris_A(1);            // Set all port A to inputs (high Z)
   ULPWU = 1;                // remember ULPWU = 0x8E.5 (PCON bit 5)
   IOC0 = 1;                 // enable interrupt on change for pin A0
   INTCON = 0b00001000;      // enable the PortA change interrupt
   sleep();
}
}


I'm not quite sure if I handled the interrupt properly, but at least it worked. With .1uf cap and 100 ohms on A0 it would sleep for a couple seconds then wake up and pulse pin A4 to show the wakeup. I'm using the ULPWU for minimum current consumption in a project. So far so good.

Now, I got the new compiler that has the sleep_ulpwu function and here is my test code:
Code:
#include <12F635.h>

#FUSES NOMCLR,NOWDT,NOBROWNOUT,INTRC_IO
#use delay(clock=8000000)

void main() {
  setup_comparator(NC_NC);
  setup_vref(FALSE);
  setup_oscillator(OSC_8MHZ);
 
  while (1){
  output_high(PIN_A4);  // pulse high to show wakeup
  delay_ms(4);          // wait 4ms
  output_low(PIN_A4);   // back low
  sleep_ulpwu(10);  // Use the fancy new ulpwu command
}
}


Note that everything is the same but I am using the new fancy sleep command. It should give me the same timing since in both cases I have commanded a 10us cap charge time, but when I run this code it only sleeps for 120 ms. Adding capacitance does nothing, when it should increase the sleep time. It is as if something else has overtaken the timing and wakes it every 120ms, because if increase my resistance, I can make it wake at a faster rate.

Any ideas?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 01, 2008 1:08 pm     Reply with quote

The sleep_ulpwu() code is buggy for the 12F635 with vs. 4.071.
You should report this to CCS support. See the comments in
the code below.
Code:

....................   sleep_ulpwu(10); 
 
003E:  MOVF   19,W   // Save CMCON0 register
003F:  MOVWF  40     
0040:  MOVLW  07     // Then disable the comparator
0041:  MOVWF  19     

// This is a bug because there is no register at 0x9F
// on the 12F635.  It's a bug but it's harmless here.
0042:  BSF    03.5   // Bank 1
0043:  BCF    1F.0   // Clear 0x9F.0  *** BUG ***


0044:  BCF    05.0   // TRISIO.0 (pin A0) = output

0045:  BCF    03.5   // Bank 0
0046:  BSF    05.0   // Set Pin A0 = 1 to charge the cap


// This is a bug because pin A0 should not
// be set back to an input pin until after
// the 10 us delay, when the capacitor has
// been charged up.  This code should really
// be placed below the 10 us delay routine
// that you can see a few lines below this point.
0047:  BSF    03.5   // Bank 1
0048:  BSF    05.0   // Set pin A0 = input  *** BUG ***



// This is a bug because there is no register at 0x0D.
// on the 12F635.  This code is applicable to the
// 16F887.  It clears the ULPWUIF bit on those PICs.
// It's a bug to have this code in here for the 12F635,
// but it's harmless.
0049:  BCF    03.5   // Bank 0
004A:  BCF    0D.2   // Clear 0x0D.2  *** BUG ***


// 10 us delay
004B:  MOVLW  06
004C:  MOVWF  40
004D:  DECFSZ 40,F
004E:  GOTO   04D
004F:  NOP

0050:  BSF    03.5  // Bank 1
0051:  BSF    0E.5  // PCON.ULPWUE bit = 1 to enable wakeup


// This is a bug because there is no register at 0x8D.
// on the 12F635.  This code is applicable to the
// 16F887.  It clears the ULPWUIE bit on those PICs.
// Actually, according to the 16F887 data sheet, it
// should set that bit, not clear it. 
// It's a bug to have this code in here, but it's
// harmless for the 12F635.
0052:  BCF    0D.2  // Clear 0x8D.2  *** BUG ***


0053:  BSF    16.0  // ICOA.0 = 1, enable interrupt on A0
0054:  BCF    03.5  // Bank 0

0055:  MOVF   0B,W  // Save INTCON register
0056:  MOVWF  41

0057:  MOVLW  08    // Enable PortA interrupts
0058:  MOVWF  0B

0059:  SLEEP

005A:  MOVF   41,W  // Restore INTCON
005B:  MOVWF  0B

005C:  MOVF   40,W  // Restore CMCON0
005D:  MOVWF  19
....................  } 
005E:  BSF    03.5
005F:  GOTO   034
hansknec



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

PostPosted: Thu May 01, 2008 1:25 pm     Reply with quote

Wow! That's quite a few bugs! Thanks! We will report it to CCS. I guess I'll stick to my manual coding for now. I was hoping the new compiler would work for me because I was running into difficulty when trying to use the ULPWU and the int_ext. I need the PIC to wake on ULPWU and also if I see a change on my external interrupt pin. I know I'm not handling my interrupt service routines properly, but I haven't worked my way through it.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 01, 2008 1:32 pm     Reply with quote

CCS will probably fix it in the next release. If your maintenance has
run out before then, I think they will let you download the fixed version.
Make sure you give them your user reference number when you report
the bug.
starbuck



Joined: 21 Jan 2009
Posts: 6

View user's profile Send private message

ULPWU_sleep on 16F886
PostPosted: Wed Jan 21, 2009 1:48 am     Reply with quote

I have been trying to get the ULPWU_sleep command to work on a 16F886 device. I have a 0.1uf cap in parallel with a 15K resistor and in series with a 200 ohm resistor attached to RA0. I have not been able to get the circuit to reliably trigger. I can see the cap being charged for a few cycles after startup using a scope, but then MPLAB and Real Ice report an error and stop execution after a few what appear to be randomly timed cycles.

The following is the code that I am trying to get to work. Eventually, I would like to have the ULPWU timer trigger an interrupt where I can check the state of a input and then either stop the ULPWU and go on with the rest of the code or reset the ULPWU_ sleep and go back to sleep for a few milliseconds until I am ready to check the input again.
Code:
#use delay ( clock = 20 000 000 )

//#use fast_io(a)
#use fast_io(b)
#use fast_io(c)

//#fuses HS,NOWDT,NOPROTECT,BROWNOUT,NOPUT,NOLVP,NOCPD,NOWRT
#fuses HS


#zero_ram

void main() {
   set_tris_c(0x14);   // C2 and C4 are Inputs, other pins are outputs

   setup_vref(FALSE);
   setup_adc_ports(NO_ANALOGS);
    // all pins digital
 
   setup_comparator(sAN0);
    //a0 IS analog comparator input
 
 
 //true when comparator output is high
 
 

 
while (1){
      output_high(PIN_C1);  // pulse high to show wakeup
      delay_ms(4);          // wait 4ms
      output_low(PIN_C1);   // back low
      sleep_ulpwu(10);  // Use the ulpwu command
   }
}
hansknec



Joined: 30 Sep 2004
Posts: 25
Location: Virginia, USA

View user's profile Send private message Visit poster's website

PostPosted: Wed Jan 21, 2009 8:39 am     Reply with quote

I wish I could help, but I never did get the new "sleep_ulpwu()" function to work on my chip. I used the manual coding that I showed earlier in this thread and it works fine. Perhaps CCS has released an upgrade that fixes the function, because there were known bugs when I was playing with it.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 21, 2009 2:47 pm     Reply with quote

The ASM code generated for sleep_ulpwu() for the 16F886 is buggy.
I checked it for vs. 4.084. It has many of the same bugs as I reported
above. I don't know if this ever got reported to CCS. I'll write up the
bugs and send them into CCS support.
starbuck



Joined: 21 Jan 2009
Posts: 6

View user's profile Send private message

PostPosted: Mon Jan 26, 2009 7:43 pm     Reply with quote

Here is my cut at the ULPWU for the 16F886, it is not optimized but it does work and my provide someone else with a starting point.

Code:
#include <16F886.h>
#device ICD = TRUE
#device *=16 ADC=8
#fuses HS,WDT,NOPROTECT,BROWNOUT,PUT,NOLVP,NOCPD,NOWRT
#use delay( clock=20 000 000, restart_wdt )

#bit   ULPWUIF = 0x0D.2   // PIR2 bit 2 ULPWUIF: Ultra Low-Power Wake-up Interrupt Flag bit
                     //       1 = Wake-up condition has occurred (must be cleared in software)
                     //       0 = No Wake-up condition has occurred
#bit   ULPWUE = 0x8E.5      // PCON bit 5 bit 5 ULPWUE: Ultra Low-Power Wake-up Enable bit
                     //      1 = Ultra Low-Power Wake-up enabled
                     //      0 = Ultra Low-Power Wake-up disabled
#BIT   ULPWUIE = 0x8D.2   // PIE2 bit 2 ULPWUIE: Ultra Low-Power Wake-up Interrupt Enable bit
                     //      1 = Enables Ultra Low-Power Wake-up interrupt
                     //      0 = Disables Ultra Low-Power Wake-up interrupt
#BYTE   INTCON = 0x8B   // entire INTCON register
#BYTE   PIR1 = 0x0c      // Peripheral interrupt flags  (0 to clear)
#BIT   WOC1 =  0x8b.1   // Wake up on change interrupt flag  (0 to clear)
#BIT   IOC0 =  0x96.0   // interrupt on change for pin A0 (1 to set)


#INT_ULPWU   // Ultra-low power wake up interrupt
// interrupt service routine for ULPWU sleep module
void isr_ULPWU()  {
   disable_interrupts(INT_ULPWU);

//   ULPWUE = 0;      // Disable Ultra Low-Power Wake-up interrupt
   ULPWUIF = 0;   //clear the peripheral interrupt flags
//   ULPWUIE = 0;   //clear the wake on change interrupt flag
//   enable_interrupts(INT_ULPWU);
}
     
void main() {
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
 
   disable_interrupts(INT_ULPWU);
   enable_interrupts(GLOBAL);


 
   while (1){
      output_high(PIN_B5);  // pulse high to show wakeup
      delay_ms(4);          // wait 4ms
      output_low(PIN_B5);   // back low



       // begin setup of ULPWU module using a manual configuration
      set_tris_A(0b00000000);   // Set all port A0 to output

      output_high(PIN_A0);   // high on A0 to charge the cap
      delay_us(50);         // let it charge

      set_tris_A(0b00000001);   // Set all port A0 to input (high Z)

      ULPWUIF = 0;         // Clear the Ultra Low-Power Wake-up Interrupt Flag bit

        ULPWUE = 1;            // Enable Ultra Low-Power Wake-up interrupt on change for pin A0
       
      ULPWUIE = 1;         // Enable Ultra Low-Power Wake-up Interrupt Enable bit
      enable_interrupts(INT_ULPWU);

      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