06. Oscillator and Timing
It is widely known that microcontrollers usually need some sort of external oscillator such that it may function. This is mainly because the hardware in the controller is more likely than not, based on sequential logic. Without a consistent external stimulus, the controller would cannot consistently execute instructions, and as a result, the outputs may become unpredictable in terms of timing and value. This is why it is very important to understand the fundamental nature of oscillators and timing settings, and how they affect the microcontrollers connected to them.

Terminology
Every Microchip product’s datasheet has a section with the oscillator diagram. This is a very good starting point, but first some terminology.
An electronic oscillator refers to a device that displays a repetitive variation, with respect to time. Typically the electronic response has amplitude and frequency, as well as a quantitative measurement of the frequency error. These values determine whether the signal produced by an oscillator is suitable for the application in which the device will be used.
The amplitude simply refers to the difference of electric potential between the peaks and troughs. Typically, if the inputs of the microcontroller can only take 3.3V, an oscillator with a 5V output will not do. The maximum DC characteristics for every microcontroller are listed in the respective datasheet and should be carefully looked at.
The AC characteristics however are defined by the frequency rating of the oscillator. Typically these are in the range of MHz, to hundreds of MHz in value. The PIC24 family usually can take upwards of 10-20 Mhz, but they have an internal phase lock loop (PLL) that can give the controller an effective million instruction per second (MIPS) value upwards of 120 (that’s like having a 120 MHz clock!).
Lastly if the application needs to be very accurate, naturally anything that has to do with precise measurement of time or speed, the frequency error value for that oscillator needs to be minimized. This value is usually expressed as parts-per-million or PPM. For example, 8 MHz oscillator with a 50 PPM value might actually be an oscillator with a frequency value anywhere from 7 999 600 to 8 000 400 Hz.
The PIC24’s are very versatile in terms of their oscillator input. There are three main categories of timing devices compatible with most PIC24’s. Direct piezoelectric crystals can be applied (with corresponding capacitors circuits), as well as IC external clocks. In addition, for applications where timing isn’t that important, Microchip even provided an internal fast RC oscillator (FRC), so you can run the controller without an external input.
Primary and Secondary
There are two sets of IOs on the PIC24’s that can be used for clocking purposes. The primary IOs, usually labeled OSCI/OSCIO are just like what they sound like, primary oscillators. This is your main input/output, and the oscillator connected to OSCI will run the main processor on the PIC. Next there is a secondary clock, aptly labeled SOSCI/SOSCO. Usually, for time keeping applications such as an alarm clocks and time sensitive measurements applications, a secondary timing oscillator (such as 32.768 kHz crystals) can be applied here.
Selection
There are seven main modes of oscillator selection compatible with most PIC24s. These are controlled by the configuration bits FOSC and POSCMD. The selection process is fairly trivial, as Microchip provides a useful table with the values required. See the configurations section to learn how to set the configuration bits.

Once selected, the user will also need to put in the corresponding selection to the OSCCON register. Once this is done, test your OSCO pin to see if you are getting an oscillating clock signal. If you see a signal, it means that your connections work. However, the desired frequency might not be correct.
Generally the dividing the clock is done with the CLKDIV register. This register has several bits that dictate the manner in which the clock will be interpreted. The CLKDIV.DOZE<2:0> is the division taken before the clock is sent to the core processor. The minimum value is 2. As an example, if I connect and select an 8MHz clock to the PIC24, without PLL, and I set the DOZE<2:0> value to divide by 2, then the processor will be clocked at 4MHz.
General Usage
Generally if I’m writing a program for an application that does not require any precise timing or interrupts, I avoid using external oscillators. It saves me the time of soldering and the cost of the oscillator IC. In these situations, I will generally use the FRC mode.
Like I mentioned before, the FRC is not a very accurate clock. However, it is relatively flexible and can be scaled using the CLKDIV register. The FRCDIV<2:0> allows the user to adjust the postscaler to divide the clock before being sent to the DOZE<2:0> divider.
In addition to the division, you can tune your FRC to a certain degree (about +/-3% of the listed frequency) with the register OSCTUN. Of course, you will need to hook the OSCO pin to the oscilloscope to actually know what kind of effect the OSCTUN register is having on the FRC clock.
PLL Makes Things Go Fast, Very Fast
If you require some extreme amount of processing power, or you need to run an application at some high frequency, the PIC24’s have a built in PLL to enhance the external clock inputs. To turn on the PLL, the correct selection on FOSC and POSCMD must first be made. Then set the register OSCCON to any of the corresponding settings with PLL. The PLL will allow you to multiply your clock input, and get a faster oscillator input to clock the processor. The PLL scaling factor is controlled by the bits CLKDIV.PLLPOST(N2), CLKDIV.PLLPRE(N2) and PLLFBD.PLLDIV(M). These bits affects the how the input clock is perceived. The underlying equation becomes K = M/(N2*N1), where K is the multiplier to the input clock frequency. As you can see, this architecture allows the user to get many different values to clock the core processor, while featuring flexibility in the types of inputs required.
I generally stay away from PLL usage. It is a way for me to avoid dealing with the multiplying and dividing. However, I have needed the PLL modules in the past where pure processing speed was a requirement.
Examples
I have included several examples. “Fin” is the clock frequency coming in from the clock source, and “Fcy” is the clock frequency going into the processor.
External Clock, Primary without PLL, No Divide
Fcy = Fin/2 (always get divided by 2, no matter the selection)
//Configs, EC clock, No protect, Watchdog Off
_FBS (BWRP_WRPROTECT_OFF & BSS_NO_FLASH);
_FGS (GSS_OFF & GCP_OFF & GWRP_OFF);
_FOSCSEL(FNOSC_PRI & IESO_OFF);
_FOSC (FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_EC);
_FWDT (FWDTEN_OFF);
_FPOR (FPWRT_PWR1 & ALTI2C_ON);
int main(void)
{
OSCCON = 0x2200; //Use primary, no divide FCY = 10Mhz/2 = 5Mhz
CLKDIV = 0x0000; //do not divide
.. Rest of main function
FRC with PLL, Tuned, No Divide, DOZE = 2, N2 = 2, N1 = 2, M = 8
Fcy = Fin*K/2 where K = M/(N2*N1)
//Configs, FRC with PLL, No protect, Watchdog Off
_FBS (BWRP_WRPROTECT_OFF & BSS_NO_FLASH);
_FGS (GSS_OFF & GCP_OFF & GWRP_OFF);
_FOSCSEL(FNOSC_FRCPLL & IESO_OFF);
_FOSC (FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_EC);
_FWDT (FWDTEN_OFF);
_FPOR (FPWRT_PWR1 & ALTI2C_ON);
int main(void)
{
OSCCON = 0x1100; OSCTUN = 0x0012; //SET FRC at 8 Mhz
PLLFBD = 0x0006; //PLL = 8, bring FOSC to 16 MHz
CLKDIV = 0x0000; //do not divide
.. Rest of main function
Credit to Xo Wang, Jose V for corrections.
Table of Contents
Previous – Inputs and Outputs
Next – Interrupts

Entries (RSS)
“For example, 8 MHz oscillator with a 50 PPM value might actually be an oscillator with a frequency value anywhere from 7 999 950 to 8 000 050 Hz.”
Shouldn’t that be 8 000 000 Hz +/- 400 Hz, since it’s 50 parts per million, and not 50 parts per 8 million?
“PLLFBD = 0×0008; //PLL = 8, bring FOSC to 16 MHz
CLKDIV = 0×0000; //do not divide”
The datasheet actually has the PLL multiplication as 2 more than the value of PLLFBD, so 0×8 would give a 6-fold multiplication. Also, clearing CLKDIV will make the pre-/post-scalers of the PLL both be 1⁄2 division, so the resulting Fosc would be
8 MHz × 6 × 1⁄2 × 1⁄2 = 12 MHz
which is what I found by experimenting.
I’m getting full speed (40 MIPS) on my PIC24HJ128GP502 by setting PLLFBD to 0×0026, which is 2 less than the 40× multiplier I want.
I love this tutorial, by the way.
You are correct! Just checked the datasheet. Was writing it off the top of my head, so my bad. The sections are corrected. Keep the corrections coming, I would like this resource to be available for all who want it.
-J
Great job!
I think i am in love with you!
Uh.. okay…
I’m in love with the tutorial
Not sure I follow the correction by Xo Wang.
If the PLL multiplication is 2 more than the value of PLLFBD, wouldn’t PLLFBD = 0×8 give a (M=8+2) 10-fold multiplication, leading to a Fosc of
8 MHz × 10 × 1⁄2 × 1⁄2 = 20 MHz?
BTW, Great tutorial!
Carl
Hi Carl,
You forgot that Fcy is always calculated with a 1/2 factor with respect to Fin. Each instruction cycle requires two oscillator cycles. So the correct value would be 8 x 10 / (2 * 2 * 2) = 10 Mhz (assuming DOZE = FYC/1), with PLLFBD = 0×08. There was a mistake in the code that I did not catch. I got the “+2″ as a “-2″. PLLFBD should be 0×06, with M = 8, as has been corrected right now.
Thanks,
-J
Hi I’m using a PIC24FJ128GA006 for a student project, basically I am using the Interrupt on change function and cannot get RC13 / RC14 ( CN0 / CN1 ) to work which happen to be SOSC0/SOSCI, I have managed to use interrupt on change pins on PORTG. Have set TRIS reg and am using internal fast RC, if required i can post code but ive been through datasheet many times and cannot find much about this.
Have tried just using as a general IO controlling an LED too but no go.
thanks
Danny
Make sure you have the secondary oscillator disabled, this is usually found in the configuration bits. Also, scan through the datasheet for the SOSC0 pin, there might be more clues as to why you are getting problems. My guess is that the secondary oscillator module is enabled, and it is actually waiting for a secondary clock on the pins.
Good luck, tell me how it goes.
-J
After Testing my code on a development board I made and found CN0 CN1 working I realised that I was being stupid and hadn’t made a contact on them 2 pins whilst soldering,,, should have been the first thing I checked!
About the SPI errata stuff I had a quick look,, there is a lot of stuff about the SPI but could not see the problem I encountered, but my work around is working fine so ill just stick with that for now.
Thanks
Danny