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 support@ccsinfo.com

PIC18LF26K22 Crystal to Internal Oscillator switching

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



Joined: 27 Apr 2011
Posts: 3

View user's profile Send private message

PIC18LF26K22 Crystal to Internal Oscillator switching
PostPosted: Wed Apr 27, 2011 8:30 pm     Reply with quote

I am working with the PIC 18LF26K22 processor. I have a 16Mhz external crystal and have the clock set to use the PLL to give a speed of 64Mhz.

#use delay(oscillator=16Mhz, clock=64Mhz, RESTART_WDT ) //16MHZ Crystal 4XPLL Enabled

I would like to be able to switch to the internal oscillator and drop down to 2Mhz to reduce power but still allow for RS232 communications at 38.4KBaud.

#fuses INTRC
setup_oscillator(OSC_2MHZ | OSC_INTRC | OSC_PLL_OFF);
#use delay(clock=2MHZ, RESTART_WDT) //4.47ma

The CCS function 'setup_oscillator' seems to be only for the internal oscillator. The manual states that I can use multiple #use delay statements to adjust timing inside the program.

In small test programs this seems to work. But, in larger programs, the #use delay statement triggers an error during compile: ERROR 101 - Library Not Found "1000".

Has anyone run into this before?

I am wondering if CCS has a function to allow switching from the primary external, secondary external and internal clocks on these newer chips?

I am going down the path of altering the OSCCON,OSCCON2,OSCTUNE registers.

It would be nice if CCS could expand the existing functions to work with these new chips.
Ttelmah



Joined: 11 Mar 2010
Posts: 19382

View user's profile Send private message

PostPosted: Thu Apr 28, 2011 2:04 am     Reply with quote

The setup_oscillator, combined with #use delay, can already do what you want.
A 'fuse', is a permanently programmed setting, and cannot be changed inline.
I have not seen any problem with inserting a #use delay 'in a large project', probably something to do with the specific location/syntax nearby.

Sequence is:
Code:

setup_oscillator(OSC_INTRC|OSC_2MHz);
#use delay(CLOCK=2MHz) //To select internal 2MHz operation

setup_oscillator(OSC_NORMAL|OSC_PLL_ON);
#use delay(CLOCK=64MHz) //to return to the main _fuse set_ oscillator


_However_ you need to critically understand what is, and isn't changed.
Code like delays, are _fixed_ counters. They only change for the code section compiled _with_ the above delay options. There is no 'dynamic' switching of the delays inline. You need to design your code with a 'low speed' section, and a 'high speed' section, and change your settings that need changing in each. Similarly, if you have timers programmed, you need to change these, and also, after changing the clock, you need to call 'setup_uart' with your required baud rate, so that the uart dividers are reprogrammed. Only parts you reprogram are changed.

Best Wishes
Rich



Joined: 27 Apr 2011
Posts: 3

View user's profile Send private message

PostPosted: Thu Apr 28, 2011 6:51 am     Reply with quote

Hi Ttelmah,

You are correct. I was assuming that the "#use delay" would have a global effect and change all of the delay_ms(), delay_us() routines in the program. During runtime it can't because this code is created when the program is compiled and hard coded. So changing clock speeds from 64Mhz to 2Mhz will probably alter all the delays by a factor of x32. A 10ms delay will become a 320ms delay and so on.

Your idea about building separate sections of code, "High Speed" and "Low Speed" is probably the right way to approach this.

Thanks
parthiv2eng



Joined: 17 Jul 2013
Posts: 6

View user's profile Send private message

PostPosted: Tue Aug 27, 2013 9:59 am     Reply with quote

Quote:
Similarly, if you have timers programmed, you need to change these, and also, after changing the clock, you need to call 'setup_uart' with your required baud rate, so that the uart dividers are reprogrammed. Only parts you reprogram are changed.


I had similar issue..Even though I am resetting uart after clock switch over, The UART won't reset according to delay.

Here's my code:
Code:

#FUSES H4                     //Enable PLL with EC

#use delay(clock=14745600)
#use RS232(baud=115200,UART1,ERRORS)   //!Initialize UART

//!Clock Switch over function
void clock_switchover(int1 clock_select){   
   if(!clock_select){
      setup_oscillator(OSC_NORMAL|OSC_PLL_ON);
      #use delay(clock=14745600)
   } else {
      setup_oscillator(OSC_INTRC|OSC_16MHz);
      #use delay(clock=16MHz) //To select internal 16MHz operation
   }
   set_uart_speed(115200);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19382

View user's profile Send private message

PostPosted: Wed Aug 28, 2013 4:55 am     Reply with quote

Do a search here on #use rs232.
This was covered many times ages ago, when people were trying to switch baud rates with this statement.

The key is to understand, that the #use delay, is early in the processor pass, rather than at runtime. You actually need completely separate code. One 'program' effectively written with one speed selected, and another separate section with the other. In yours, both #use delays are inside one routine, so the latter will be used (the compiler always uses the last one 'met' at compile time - It knows nothing about a value test performed at run time).

Best Wishes
steav



Joined: 22 Nov 2011
Posts: 10

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 11:18 am     Reply with quote

Ttelmah wrote:
Do a search here on #use rs232.
This was covered many times ages ago, when people were trying to switch baud rates with this statement.

The key is to understand, that the #use delay, is early in the processor pass, rather than at runtime. You actually need completely separate code. One 'program' effectively written with one speed selected, and another separate section with the other. In yours, both #use delays are inside one routine, so the latter will be used (the compiler always uses the last one 'met' at compile time - It knows nothing about a value test performed at run time).

Best Wishes


This worked for me (PIC18F47J53, CCS v5.018) - switching from 48MHz to 8MHz during runtime:

1. Manually set fuses for external 16MHz crystal with 4xPLL, no CPUDIV.

2. #use delay only once, right after my fuses
Code:
#use delay(clock=48MHz, RESTART_WDT)


3. Within my timers I have code like this:
Code:
if(LowPowerMode)
        set_timer1(0xFFFF - TIMER1_RELOAD_OFFSET/LOWPOWER_FREQUENCY_DIV);
else
        set_timer1(0xFFFF - TIMER1_RELOAD_OFFSET);

Where LOWPOWER_FREQUENCY_DIV for me is 48/8 = 6

4. Using delay_us / delay_ms wrapper:
Code:
void delayMS(uint16_t ms){
    if(LowPowerMode)
        ms = ms / LOWPOWER_FREQUENCY_DIV;

    delay_ms(ms);
}


5. Switch from 48MHz => 8MHz:
Code:
setup_oscillator(OSC_INTRC | OSC_8MHZ);
LowPowerMode = 1;
setup_uart(BAUD_UART2*LOWPOWER_FREQUENCY_DIV, COM_UART2);


6. Switch from 8MHz => 48MHz:
Code:
setup_oscillator(OSC_NORMAL | OSC_8MHZ);
LowPowerMode = 0;
setup_uart(BAUD_UART2, COM_UART2);


7. Enjoy Smile
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