I got a PIC24EP128MC206 because of its rated speed of 70 MIPS. (For whatever reason, it is rated in MIPS, while most other PIC24s are rated in MHz.)

Since my understanding is that one instruction on the PIC24 takes one Fcy clock cycle, I am trying to configure the clock so Fcy is as close to 70 MHz as possible. However it seems I can only run it at about half the rated speed -- around 31.5 MHz. Anything higher than that, and the PLL stops doing its thing.

I am using the internal FRC clock, since I don't need exact timing anywhere (not using UARTs for example). The nominal FRC frequency is 7.37 MHz, which can be adjusted from 6.52 MHz to 8.20 MHz using the OSCTUN register.

As a reference, I am using the PIC24EPXXXGP/MC20X datasheet. Here is the relevant section on setting up the clock:

enter image description here

and here is my setup code:

// configuration fuses for PIC24EP128MC206


int main(void)

    RCONbits.SWDTEN = 0;            // Disable Watch Dog Timer

    // configure Oscillator
    // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
    // with default 7.37 MHz FRC clk, Fcy = approx 7.37*34/(2*2*2) = 31.3 MHz

    PLLFBD = 32;                   // M=34      (ANYTHING HIGHER DOESN'T WORK)
    CLKDIVbits.PLLPRE = 0;         // N1=2
    CLKDIVbits.PLLPOST = 0;        // N2=2

    __builtin_write_OSCCONH(0x01);  // set up to switch to FRC+PLL
    __builtin_write_OSCCONL(OSCCON | 0x01);  // do the switch

    while(OSCCONbits.COSC != 0x00); // wait for switch to take place    
    while(OSCCONbits.LOCK != 1){ };     // wait for PLL lock

Fsys = 34*7.37/2 = 125.29 which is near but not below the acceptable range of 120 to 340 MHz.

With the values show above the clock works and I get a nice output of around 31.5 MHz as measured using the CLKO pin (which is the same as Fcy, the instruction cycle clock). The 31.5 MHz compares well with my calculated value of 31.3 MHz above, given that the 7.37 MHz FRC clock may be off somewhat.

enter image description here

I would like to use an M value of 76, which would give me an instruction cycle time of 70 MHz.

But if I make the value of M any higher than 34, the PLL becomes unstable and the clock output reverts to around 3.70 MHz, which is half of the FRC frequency (implying the PLL circuit is out of the picture). When it is running, I can sometimes see some flashes of the higher frequency on the scope, as if the PLL is trying to start up and can't stabilize. As one can see from my code sample, I am waiting for the PLL lock before continuing.

UPDATE: This seems somehow related to the final frequency, not the PLL Fsys frequency. I tried the following combination and it also worked:

PLLFBD = 120;                  // M=122     (ANYTHING HIGHER DOESN'T WORK)
CLKDIVbits.PLLPRE = 1;         // N1=3
CLKDIVbits.PLLPOST = 0;        // N2=4

which results in a PLL frequency of 300 MHz a Fcyc of 37.46 MHz (measured, 37.7).

I was a little concerned maybe you couldn't run at 70 MIPS using the internal FRC, but the datasheet for the PIC24E oscillator says "the FRC postscaler output can be used with the internal PLL to boost the system frequency (FOSC) up to 140 MHz for 70 MIPS instruction cycle execution." so I'm not trying to do the impossible.

Another UPDATE: I tried a second board and got the same results -- I can't seem to set Fcy to a frequency higher than 40 MHz without the PLL dropping out. I also tried hooking up a buffered 24 MHz clock into OSC1 and configuring the system to use that as a extral clock (EC) with PLL. Exactly same results.

How can I get a faster clock to work?

FINAL UPDATE: Turns out that the person doing the board layout put a 0.1 uF cap on VCAP without looking at the datasheet and I never caught it either. I swapped that out with a 10 uF 16v low ESR (datasheet called for 4.7 uF or higher) and now I can run at 70 MIPS. See accepted answer re how I found this was the problem.

  • \$\begingroup\$ To remove confusion about the PLLDIV/PLLFBD register, the datasheet refers to the value of the 9 bits in the PLLFBD register as PLLDIV, so there is no inconsistency. \$\endgroup\$
    – justing
    Commented Dec 17, 2012 at 7:32
  • \$\begingroup\$ PLLFBD or feedback divider makes logical sense and it appears that the use of the 9th bit = 1 causes it to fail (>32) (assuming 1~32 as valid divide ratios) Sounds like a M counter speed failure. Does it run hot? Is it sensitive to +/-0.1 Vcc variations? When PLL loses sync it should be in Freq mode and when locked in Phase mode so VCO should be stuck at min or max F depending on what mixer puts out to VCO filter. VCO has almost 3:1 max:min tuning range. \$\endgroup\$ Commented Dec 17, 2012 at 7:55
  • \$\begingroup\$ @justing Thanks, your comment made me look at the PLLFBD register again, and I see that the field within it is named PLLDIV, so there is no inconsistency. I removed that part from my question. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 8:01
  • \$\begingroup\$ @tcrosley Are you performing any other tests to determine if the clock is running (and at what speed) other than monitoring the CLKO pin with the scope? (also, i agree they make no reference in the datasheet as to which clock it should be outputting!) \$\endgroup\$
    – justing
    Commented Dec 17, 2012 at 8:14
  • \$\begingroup\$ @Richman It is failing at 32 or above, which is the 5th bit, not the 9th or highest bit. The ratios run from 2 to 513. The chip is not running hot at all. I have no way of modifying the VCC since it is driven off an internal regulator. I think I can get a hold of another board though, and will check to see if the problem is the same on it. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 8:14

5 Answers 5


You should check out example 7-2 in the pic24E family reference manual (FRM) titled "Code Example for Using PLL with 7.37 MHz Internal FRC":

// Select Internal FRC at POR
// Enable Clock Switching and Configure Primary Oscillator in XT mode

int main()
    // Configure PLL prescaler, PLL postscaler, PLL divisor
    PLLFBD=63;            // M=65
    CLKDIVbits.PLLPOST=0; // N2=2
    CLKDIVbits.PLLPRE=0;  // N1=2

    // Initiate Clock Switch to FRC oscillator with PLL (NOSC=0b001)
    __builtin_write_OSCCONL(OSCCON | 0x01);

    // Wait for Clock switch to occur
    while (OSCCONbits.COSC!= 0b001);

    // Wait for PLL to lock
    while (OSCCONbits.LOCK!= 1);

It looks like the critical step you're missing is __builtin_write_OSCCONL(OSCCON | 0x01);

Also, looking at the math: 7.37*(76/(2*2)) == 140.03MHz which is slightly outside the allowed range, assuming that 140MHz is actually the maximum range (don't ask me why but for some reason it seems like it may be 120MHz).

If this still doesn't work then perhaps there's just an issue with your power supply. The internal FRC oscillator is unstable under temperature and voltage stress, so perhaps you should check to see if you have too much noise. This would make the FRC wonky as well as the VCO used in the PLL, preventing a lock.

If you look at table 30-18 in the pic24EP128MC206 datasheet, it tells you that over the temperature and voltage range you have about a ±1% for some models and ±2% for others. Figure 31-9 shows the variation with a stable voltage over a temperature range. There doesn't appear to be an analysis of voltage variation at a stable temperature.

If you're trying to get a stable run at a high frequency I would just grab a crystal.

EDIT (from comment): So from the sounds of your other posts about your conditions it sounds like you should look elsewhere for a problem. What's the frequency of the ripple? Did you size the internal Vreg capacitor properly? It sounds like since this is a locking issue and not a setting issue you're having some other problems with the board that aren't related to your code.


Glad this turned out to be the right answer! Good luck debugging the rest of the board!

  • \$\begingroup\$ XT mode wont run that fast. \$\endgroup\$ Commented Dec 17, 2012 at 14:24
  • \$\begingroup\$ ...? I mean grab a crystal and run it through the PLL. Sorry if that wasn't clear. \$\endgroup\$
    – Kit Scuzz
    Commented Dec 17, 2012 at 17:39
  • \$\begingroup\$ I changed my code to use __builtin_write_OSCCONL(OSCCON | 0x01) but there was no effect. Also updated my original post. Thanks. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 18:30
  • \$\begingroup\$ It turns out we have a buffered 24 MHz clock being used elsewhere on the board, so I ran a line from that to the OSC1 input and reconfigured things to use that as an external clock (EC) source. Got exactly the same results -- I can't seem to set an Fcy above 40 MHz. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 21:46
  • 1
    \$\begingroup\$ The person doing the board layout put a 0.1 uF cap on VCAP without looking at the datasheet (which calls out for a minimum of 4.7 uF) and I never caught it either. I swapped out the 0.1 uF with a 10 uF 16v low ESR and now I can run at 70 MIPS. \$\endgroup\$
    – tcrosley
    Commented Dec 18, 2012 at 7:03

Have a look at the PIC24E reference manual, Section 07. Oscillator. It has a more in-depth explanation of the oscillator section and the PLL. Especially, on page 7-26, it has an example of exactly what you want: use the FRC and the PLL (even though it is for 60MHz). THis example sets the configuration bits differently that your example code - esp. it doesn't automatically switch to the user-defined clock source.

I also see that you enable the clock monitor - it might be that it triggers for some reason and then switches back to the normal FRC.

Regarding the PLLDIV: I think this is a misconception. The data sheets always talk about the values used (e.g. PLLDIV), which are part of larger registeres (PLLFBD in this case). The same is for PLLPOST and PLLPRE in the image you posted - they are part of the CLKDIV register.

  • \$\begingroup\$ As I mentioned in my comment to justing above, I have disabled the clock monitor but it didn't allow me to run any higher. I understand now that PLLDIV is the field and PLLFBD is the register. Thanks. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 18:24

I'm not familiar with PICs, and obviously you seem to know what you're doing. But are you sure the PLLDIV doesn't exist? Are you sure you have the correct chip or datasheet?


Updated the All Resets values for CLKDIV and PLLFBD in the System Control Register Map (see Table 4-35).

So maybe you have an older chip (if this effects anything, I only skimmed the datasheet.)

There is a minor inconsistency in the documentation; Figure 9-2 and Equation 9-2 refer to a PLLDIV register, which doesn't exist on this microcontroller

If you're sure you have the correct chip and datasheet, that seems like a major discrepancy, enough to almost make me think you may have a counterfeit or defective chip (as long as you do know what you're doing.)

And it looks like you are following this, from the datasheet:

If the PLL of the target device is enabled and configured for the device start-up oscillator, the maximum oscillator source frequency must be limited to 3 MHz < FIN < 5.5 MHz to comply with device PLL start-up conditions. This means that if the external oscillator frequency is outside this range, the application must start-up in the FRC mode first. The default PLL settings after a POR with an oscillator frequency outside this range will violate the device operating speed. Once the device powers up, the application firmware can initialize the PLL SFRs, CLKDIV and PLLDBF to a suitable value, and then perform a clock switch to the Oscillator + PLL clock source. Note that clock switching must be enabled in the device Configuration Word.

  • 1
    \$\begingroup\$ As I mentioned in a comment to justing, I discovered that there is no inconsistency after all, the PLLDIV field is simply the only field within the PLLFBD register so I think you can go ahead and delete your answer. \$\endgroup\$
    – tcrosley
    Commented Dec 17, 2012 at 8:04

I've had success with dsPICs at 50MIPS using the internal RC oscillator and PLL. Give this a try:

  • Set the part to use FRC with divide-by-N and PLL directly (FRCPLL) - I see no reason to start with another clock then switch to it. Also disable any clocks coming outside and any external oscillator sources - set them as GPIO lines if the options exist.
  • As the first lines in main(), set PLLFBD, PLLPOST and PLLPRE, then wait for the PLL lock.

I had the same problem with the PLL which didn't not lock on the high frequency from my external oscillator. My problem was the ESR of capacitor on the VCAP input. It must be less to 1 ohm (see PIC24E datasheet), and in my case the ESR was 4 ohm, and it was not running.

So thanks for the tip!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.