![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Rich
Joined: 27 Apr 2011 Posts: 3
|
PIC18LF26K22 Crystal to Internal Oscillator switching |
Posted: Wed Apr 27, 2011 8:30 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19382
|
|
Posted: Thu Apr 28, 2011 2:04 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Rich
Joined: 27 Apr 2011 Posts: 3
|
|
Posted: Thu Apr 28, 2011 6:51 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
parthiv2eng
Joined: 17 Jul 2013 Posts: 6
|
|
Posted: Tue Aug 27, 2013 9:59 am |
|
|
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);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19382
|
|
Posted: Wed Aug 28, 2013 4:55 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
steav
Joined: 22 Nov 2011 Posts: 10
|
|
Posted: Wed Feb 26, 2014 11:18 am |
|
|
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](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|