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

UART rx during sleep mode problem

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



Joined: 17 Dec 2005
Posts: 58

View user's profile Send private message

UART rx during sleep mode problem
PostPosted: Wed Jul 04, 2007 11:46 am     Reply with quote

I am attempting to capture a single character from a serial device while the PIC18LF8722 is in sleep mode. Everything works fine if I sit in 'idle' mode, but that consumes too much power. I am using a 10Mhz crystal as my main running clock, although I shut that down while in sleep using setup_oscillator(OSC_31250); The circuit draws 60uA in sleep mode, which I am happy with.

I have wired the receive pin to both UART1 and EXT1. my idea is that the high-to-low transition will trigger EXT1 and wake up the PIC, the first instruction will be a getc() ... or a timed getc routine.

So far my logic is correct, but the character is not being read properly, I keep getting 255 back. The character I'm expecting is 165. Again, the problem only occurs in sleep mode, not idle mode.

My assumption is that upon EXT1 being triggered, the PIC switches from 31khz to the 10mhz external crystal. The delay period of the PIC waking up and the 10mhz crystal stabilizing is too long for the character to be properly read.

Without pasting the entire code , which is not really necessary, here are the relevant portions...

Code:

#FUSES HS 
#use delay(clock=10000000) // 10Mhz

char rx_char;

#int_EXT1
void EXT1_isr(void) {
   disable_interrupts(INT_EXT1);
   enable_interrupts(GLOBAL);
      
   rx_char=timed_getc();
}
       

/* code extracted from CCS example file */
char timed_getc() {
   long timeout;
   char retval;

   timeout=0;
   while(!kbhit() && (++timeout< (KEYHIT_DELAY*100)))
      delay_us(10);
   if(kbhit())
      retval = getc();
   else
      retval = 0;
   return(retval);
}

void main(void) {
   setup_oscillator(OSC_31250);
   sleep();
   
   fprintf(SerialPortOne,"Received: %U\n\r",rx_char);
}


any ideas?
ckielstra



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

View user's profile Send private message

PostPosted: Wed Jul 04, 2007 12:10 pm     Reply with quote

Quote:

My assumption is that upon EXT1 being triggered, the PIC switches from 31khz to the 10mhz external crystal.
Don't assume. Most likely this is your problem.

Code:
#int_EXT1
void EXT1_isr(void) {
  disable_interrupts(INT_EXT1);
  enable_interrupts(GLOBAL);

  rx_char=timed_getc();
}
NEVER activate the global interrupt enable flag inside an interrupt handler. This can cause nested interrupts, a feature not supported by the hardware with program crashes as a result. Most likely you intended to disable the global interrupt flag but this is not going to work as the hardware will restore the flag on exiting the interrupt handler.
ktallevi



Joined: 17 Dec 2005
Posts: 58

View user's profile Send private message

UART rx during sleep mode problem
PostPosted: Wed Jul 04, 2007 12:36 pm     Reply with quote

So any ideas as to capturing the character upon waking up? The character is being received at 9600bps, so I would need to power up before the start of the first data bit (100usec or so). Is there a way to keep that single hardware UART active while the device is in sleep mode, without using idle mode of course.

I'm open to any other ideas of course.

thanks
Ttelmah
Guest







PostPosted: Thu Jul 05, 2007 3:23 am     Reply with quote

The problem is that the UART, is clocked by the processor clock, and cannot work without a clock.
What you can do, is have the command to switch the clock to a slow rate (but still running), and then a new #use delay statement, and #use RS232 statement, for this clock rate. Then the UART is running and clocked at the slower rate, to receive the first character.
Unfortunately though, the 32K clock, is not fast enough to operate the UART for 9600bps reception. The UART will trigger a 'wake' on the first edge of the start bit, but cannot then clock the data in, till the main oscillator has woken.
The normal way to deal with this, is to send a dummy 'wake up' character, in front of the actua data, with enough delay, for the oscillator to have started, before the main data is sent.
Unfortunately, this is hardware limitation.

Best Wishes
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Thu Jul 05, 2007 7:32 am     Reply with quote

Why are you sleeping at 32kHz? If it is just something readily available and slow enough to save power without being stopped, but accuracy is not too important, you might try a faster sleep clock, like a 200kHz resonator. It might be slow enough to save power, but fast enough to run your UART.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Thu Jul 05, 2007 10:13 pm     Reply with quote

I think it's worth mentioning that a crystal speed of 38400 will allow you to run in low power mode and still receive at 9600 baud with no error using only the low speed crystal. It will use about the same power that a clock crystal would use but operating a real time clock becomes more complicated. Also, you may be able to go much lower than 60uA in low power mode.
ktallevi



Joined: 17 Dec 2005
Posts: 58

View user's profile Send private message

PostPosted: Thu Nov 29, 2007 10:35 am     Reply with quote

so the best course of action should be enable sleep mode, but use a faster crystal. I'll have to calculate the lowest possible crystal value that allows for 9600 reception, but still provides good power saving.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Thu Nov 29, 2007 12:08 pm     Reply with quote

ktallevi wrote:
so the best course of action should be enable sleep mode, but use a faster crystal. I'll have to calculate the lowest possible crystal value that allows for 9600 reception, but still provides good power saving.


lowest crystal speed for a given baud rate is 4 * baud rate.

While in sleep mode the crystal does not oscillate, there is no clock and no instructions are executed.

Switching from a 10Mhz crystal to a 38.4Khz crystal will cause power use to drop from about 10mA to about 40uA. Instructions will continue to execute.

So to reduce power use, configure USART for slower crystal then switch crystals to the lower crystal speed. You don't need to enter sleep mode.
ktallevi



Joined: 17 Dec 2005
Posts: 58

View user's profile Send private message

PostPosted: Thu Nov 29, 2007 1:44 pm     Reply with quote

I still need the 10Mhz crystal for other purposes, so could I put the 38.4khz crystal on RC0/RC1 and use setup_oscillator(OSC_TIMER1)?

This way the PIC could run off the 38.4khz until it gets the data from the 9600 bps device (instead of sleeping), read the data, then switch back to the 10Mhz crystal again for full operation.

thanks
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