Search code examples
clockmicrochip

How to calculate dsPIC internal clock (Fosc) using FRC Divide-by-N?


I'm currently programming a dspic33ep256mc506 but I'm a little confused by the configuration of it. At the moment I'm just testing the internal clock for debugging purposes, but am unsure what the maximum frequency is. All I'm trying to do is figure out how to calculate the Fosc and Fcy for Internal Fast RC (FRC) Divide-By-N (FRCDIVN).

As far as I'm aware, the CPU speed is 70 MIPS, and supposedly 7.43 Mhz is the default Fosc.

Originally I was under the impression that FRCDIVN is based on the \$F_{PLL}\$, so something like this would set it to 4 MHz

/* Configure Oscillator to operate the device at 4Mhz */
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// M is PLLDIV + 2
PLLFBDbits.PLLDIV = 11; //M is 13
// N1 is PLLPRE + 2
CLKDIVbits.PLLPRE = 10;  //N1 is 12
// N2 is 2*(PLLPOST + 1)
CLKDIVbits.PLLPOST = 1; // N2 is 2
// Fosc = Fin * 43/(80) = Fin * 128; 7.37 * 43/ 80 = 4Mhz
// Fcy = Fosc / frcdiv (if 0 then 1)
CLKDIVbits.FRCDIV = 0;

Reading the oscillator module it seems like that's not the case with FRC divid-by-n (FNOSC_FRC). enter image description here

So now I'm trying to use FRC divide-by-n with PLL (FNOSC_FRCPLL), and was wondering whether now the final Fosc is 4Mhz.

_FOSCSEL(FNOSC_FRCPLL);
CLKDIVBITS.FRCDIV = 0;      //FRC Divid-by-1
OSCTUNbits = 0;     //7.373Mhz

/* Configure Oscillator to operate the device at 4Mhz */
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// M is PLLDIV + 2
PLLFBDbits.PLLDIV = 11; //M is 13
// N1 is PLLPRE + 2
CLKDIVbits.PLLPRE = 10;  //N1 is 12
// N2 is 2*(PLLPOST + 1)
CLKDIVbits.PLLPOST = 1; // N2 is 2
// Fosc = Fin * 43/(80) = Fin * 128; 7.37 * 43/ 80 = 4Mhz
// Fcy = Fosc / (DOZE+1) 
CLKDIVbits.FRCDIV = 0;
CLKDIVbits.DOZE = 0;

Now i'm wondering if all of this calculated correctly and noticing that extra divide block after the mux, is Fosc 4Mhz and the Fcy 2Mhz?

p.s. suppose I were to use FRC Divide-by-N, and adjust it based on ostune register, where 0 is 7.373 Mhz. The oscillator module data sheet suggests I look at the tolerance to determine how much each bit affects the new clock. I'm not exactly sure how to find this out.


Here's the starting FOSC configuration generated:

// FOSC
#pragma config POSCMD = NONE            // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = OFF           // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = ON             // Peripheral pin select configuration (Allow only one reconfiguration)
#pragma config FCKSM = CSDCMD           // Clock Switching Mode bits (Both Clock switching and Fail-safe Clock Monitor are disabled)


// FOSCSEL
#pragma config FNOSC = FRCDIVN          // Oscillator Source Selection (Internal Fast RC (FRC) Oscillator with postscaler)
#pragma config PWMLOCK = ON             // PWM Lock Enable bit (Certain PWM registers may only be written after key sequence)
#pragma config IESO = ON                // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)

Update

So i put together an experiment to test it. I set a for loop, with led toggling delay of 3 seconds

for(;;){
     //__delay32(1000000);
     __delay_ms(3000);
     LED15=!LED15;
}

and in the beginning I included libpic30.h and defined

 #define FCY 2000000UL
 #define FOSC 4000000UL

although it couldn't compile to use the __ms_delay(x) defend in the libpic30.h, i copied it over to the main.c

#define __delay_ms(d) \
  { __delay32( (unsigned long) (((unsigned long long) d)*(FCY)/1000ULL)); }
#define __delay_us(d) \
  { __delay32( (unsigned long) (((unsigned long long) d)*(FCY)/1000000ULL)); }

using this configuration I noticed the delay with __ms_delay(3000) is actually 6 seconds, not 3 seconds.

On the second try I redefined FCY as

#define FCY 1000000UL

then the __ms_delay(3000) ended up being 3 seconds, which seems to point out that Fcy is actually 1Mhz, and the Fosc is 2Mhz.


Solution

  • Just realized I made a mistake when calculating the numerator of the oscillator frequency, turns out that N2 is set to 4 in this configuration because it's 2*(PLLPOST+1) where PLLPOST = 1 as oppose to what I originally thought, N2 being (PLLPOST+1)

    So in this case Fosc = 7.37*13/(12*4) = 2Mhz, which means Fcy is half of that, 1Mhz