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

waking up from sleep using timer1.

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



Joined: 22 Aug 2006
Posts: 18

View user's profile Send private message

waking up from sleep using timer1.
PostPosted: Tue Sep 04, 2007 4:08 am     Reply with quote

Hello,

I am trying to put the PIC to sleep and wake it up using TIMER1. I've been using the WDT timer in the past but I'd like to have a better accuracy using TIMER1.
I'm using a PIC18LF2620
CCS v4.033 and also V3.249

I can observe 2 things:
1: If the timer value is 0xFB00 or more, I can't see the PIC going to sleep, and the message: "Wakeup on T1\n" from the isr isn't printed on the serial port. On the other hand, the while loop keeps going.

2: if the Timer value is less than 0xFB00, the PIC goes to sleep but never wakes up.

Here is my code:
Main.c
Code:

#include "main.h"


#BYTE   T1CON = 0xFCD
#BIT T1SYNC=T1CON.2

void main()
{

   while ( 1 )
   {
      fprintf( COM2, "Go to Sleep\n" );
      set_timer1(0xF000);
      //setup_timer_1(T1_EXTERNAL_SYNC| T1_DIV_BY_8);
      T1CON= 0xBF; //16bit, div8, osc en, ext clk, TMRON
      enable_interrupts(INT_TIMER1);

      sleep();
      delay_ms( 500 );
   }

}
#INT_TIMER1
void timer1_isr()
{
   disable_interrupts( INT_TIMER1 );
   setup_timer_1( T1_DISABLED );
   delay_ms( 4000 );
   fprintf( COM2, "Wakeup on T1\n" );

}

main.h
Code:

#ifndef _MAIN_H
#define _MAIN_H

#include <18F2620.h>
#device adc=8
#IF  getenv("VERSION")>4.001
   #device ANSI
#ENDIF

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT8192                   //Watch Dog Timer uses 1:8192 Postscale: for about 30s sleeping time
#FUSES HS                       //High speed Osc (> 4mhz)
//#FUSES INTRC
#FUSES NOPROTECT                //Code not protected from reading
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES DEBUG                  //No Debug mode for ICD
#FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=20000000)
//#use rs232(baud=9600, parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//#ifdef __DEBUG__
#use rs232(baud=57600, parity=N,xmit=PIN_B0,/*rcv=PIN_A5,*/bits=8, invert, STREAM=COM2)
//#endif



#endif   //_MAIN_H


Thanks for your help.

Christophe D.
Ttelmah
Guest







PostPosted: Tue Sep 04, 2007 5:17 am     Reply with quote

Comment one.
The interrupt code, will _only_ get executed, if both the interrupt is enabled, and the global interrupt flag is set. Without the global flag, the interrupt will only wake the chip. 3.5.1 in the data sheet.
Second, if the interrupt handler is not called, it becomes _your_ responsibility to clear the interrupt flag. You need to do this before sleeping, or the code will never wake. You should do this anyway, otherwise if the flag is set, the CPU will not go to sleep.
In the 'setup_timer' version, you want:
setup_timer_1(T1_DIV_BY_8 | T1_EXTERNAL | T1_CLK_OUT);
Given external input, output, to form the oscillator, and the division by eight.
Get rid of the IESO fuse. This will imply, that because the T1 oscillator is running, you will almost certainly _not_ see messages printed just after wake up. With this set, the chip will wake up immediately from sleep, without waiting for the main oscillator to start. It'll run the first few dozen instructions, at the speed that T1 is running, not the master clock. This means that any serial print done here, wll just result in garbage. Lok at 23.3.1 in the data sheet. The delay in the interrupt, will probably avoid this, but it is a danger.
Get rid of the delay in the interrupt routine. Since delays are used in both the interrupt code, and also the main, this will result in interrupts automatically being disabled in the main, wherever delays are used. On sleep, the instruction immediately after the sleep, is 'prefetched', and in some cases, may actually be partially performed, before the sleep is entered. This could really screw things up...
[code]
#INT_TIMER1
void timer1_isr(void) {
fprintf( COM2, "Wakeup on T1\n" );
}

void main()
{

//setup timer just once
setup_timer_1(T1_DIV_BY_8 | T1_EXTERNAL | T1_CLK_OUT);
while ( 1 )
{
//ensure any print from the interrupt has completed
delay_ms(30);
fprintf( COM2, "Sending to Sleep\n" );
set_timer1(0xF000);
clear_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
sleep();
//ensure the prefetched instruction is nop
delay_cycles(1);
delay_ms( 500 );
}
}

Best Wishes
ch_dupre



Joined: 22 Aug 2006
Posts: 18

View user's profile Send private message

PostPosted: Tue Sep 04, 2007 8:33 am     Reply with quote

Thanks Tthelmah.
I've modified my code to :
Code:


#INT_TIMER1
void timer1_isr(void)
{
   fprintf( COM2, "T1 ON\n" );
   setup_timer_1(  T1_DISABLED );
}

void main()
{

   delay_ms( 1000 );
   fprintf( COM2, "Program Start\n" );
   
   while ( 1 )
   {
      delay_ms(30);
      fprintf( COM2, "Sendingi to Sleep\n" );
      set_timer1(0xF600); //the PIC will not wake up if this values is < 0xF600
      setup_timer_1(T1_DIV_BY_8 | T1_EXTERNAL | T1_CLK_OUT);
      clear_interrupt(INT_TIMER1);
      enable_interrupts(INT_TIMER1);
      enable_interrupts(GLOBAL);
      sleep();
      //ensure the prefetched instruction is nop
      delay_cycles(1);
      delay_ms( 500 );
   }
}

That works quite well for small duration. Unfortunately, it doesn't work if the timer value is less than oxF600.
That looks like a hardware bug to me. I've checked the errata but I can't see anything obvious there.

Thanks,

Christophe D.
kevcon



Joined: 21 Feb 2007
Posts: 142
Location: Michigan, USA

View user's profile Send private message

PostPosted: Tue Sep 04, 2007 8:56 am     Reply with quote

What crystal frequency are you using?

You are making it more complicated than it needs to be, look at the code on this page

http://www.ccsinfo.com/forum/viewtopic.php?t=31822&postdays=0&postorder=asc&start=15

The LED will be on for 2 seconds and off for 2 seconds.
ch_dupre



Joined: 22 Aug 2006
Posts: 18

View user's profile Send private message

PostPosted: Tue Sep 04, 2007 10:56 am     Reply with quote

I'm using a 20MHz crystal, and a 32,768KHz oscillator connected on RC0.

Christophe D.
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