My seat-of-the-pants understanding for load capacitors (corrections invited) goes like this:
When a crystal is cut for a certain load capacitance, it is measured with that capacitance across it during final factory trimming. There is nothing magical about the value. It is simply a way of saying, that if you design your circuit to present that same capacitance, then your crystal will be within the stated (.005% or whatever) tolerance.
So, you add up all the capacitance in your circuit, and then add in what's needed to bring it up to the spec. We'll use your numbers. The stray capacitance due to the traces on the board obviously will vary with the board, so let's guess 1.3 pf. A number I made up, to go with the capacitance of the microprocessor's oscillator, stated to be 1.7 pf. So, we've got 3 pf in parallel with the crystal. The crystal wants 18pf, so we have to make up the 15 pf difference with discrete parts.
Since the two load capacitors are in series (Gnd->cap->xtal->cap->Gnd), we double the cap value to 30pf. Two 30 pf caps in series give us the 15 pf we're looking for.
Note 1. I tried searching for typical PCB stray capacitance. It was all over the map. Suffice it to say, that as the hardware gets smaller, the capacitance will keep getting smaller. A lot of typical values claimed less than 1 pf.
Note 2. If there is more capacitance than spec, the crystal will oscillate at a lower frequency than specified. If there's less, then it's higher. You can see, that if you want to trim the oscillator to spec, it's easier to shoot for a lower capacitance and add some later, than to try the opposite.
Note 3. For fun, look up "gimmick capacitor".
Note 4. My "seat of the pants" explanation is sufficient as an introduction, and this technique works in many cases, but not everywhere. For a more in-depth look at the EE principles behind those capacitors, see this answer.
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
_FOSCSEL(FNOSC_FRC & IESO_OFF);
// Enable Clock Switching and Configure Primary Oscillator in XT mode
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);
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_OSCCONH(0x01);
__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.
EDIT:
Glad this turned out to be the right answer! Good luck debugging the rest of the board!
Best Answer
A microcontroller isn't aware of a thing like time; it only knows clock ticks. So the controller's logic can't tell the difference between running at 16 MHz and 192 MHz: a clock tick is a clock tick, and it will do exactly the same in 10 clock ticks for both frequencies.
That means that when actual time is relevant it's up to you to make sure the number of clock ticks gets properly translated to time. Suppose you have a 1 ms timer for the 16 MHz controller. It will give you an interrupt every 16 000 clock ticks, that's once every ms. Run that same code on a 192 MHz controller and you'll still get the interrupt every 16 000 clock ticks, but now that will be 83 µs. So change the timer's value to 192 000. Do this for everything to which real time is relevant. If you don't the 9600 bps UART will run 12 times too fast, so set the prescaler to a 12 times higher value.
The ADC is a bit different. That one does know about time: the measurement capacitor will droop at the same rate whether you run at 16 MHz or at 192 MHz. Or at 1 Hz. While the controller will run (or rather: "stroll") happily at 1 Hz, for the ADC that's too slow. The datasheet will tell you the minimum frequency it needs.