如何使用FRC Divide-by-N计算dsPIC内部时钟(Fosc)?

时间:2014-12-26 16:35:21

标签: clock microchip

我目前正在编程dspic33ep256mc506,但我对它的配置感到有些困惑。 目前我只是测试内部时钟以进行调试,但我不确定最大频率是多少。我试图做的就是弄清楚如何计算内部快速RC(FRC)除以N(FRCDIVN)的Fosc和Fcy。

据我所知,CPU速度为70 MIPS,据称7.43 Mhz是默认的Fosc。

最初我的印象是FRCDIVN基于\ $ F_ {PLL} \ $,所以像这样将它设置为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;

阅读oscillator module似乎与FRC divid-by-n(FNOSC_FRC)的情况不同。 enter image description here

所以现在我尝试使用带有PLL的FRC除法(FNOSC_FRCPLL),并且想知道现在最终的Fosc是否为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;

现在我想知道所有这些是否正确计算并注意到多路复用后的额外分频块是Fosc 4Mhz还是Fcy 2Mhz?

P.S。假设我使用FRC Divide-by-N,并根据ostune寄存器进行调整,其中0为7.373 Mhz。振荡器模块数据表建议我查看容差,以确定每个位对新时钟的影响程度。我不确定如何找到它。


这里是生成的起始FOSC配置:

// 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)

更新

所以我把一个实验放在一起测试它。我设置了一个for循环,导致切换延迟为3秒

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

在开头我加入了libpic30.h并定义了

 #define FCY 2000000UL
 #define FOSC 4000000UL

虽然它无法编译以在libpic30.h中使用__ms_delay(x)防御,但我将其复制到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)); }

使用此配置我注意到__ms_delay(3000)的延迟实际上是6秒,而不是3秒。

在第二次尝试中,我将FCY重新定义为

#define FCY 1000000UL

然后__ms_delay(3000)结束了3秒,这似乎指出Fcy实际上是1Mhz,而Fosc是2Mhz。

1 个答案:

答案 0 :(得分:0)

刚刚意识到我在计算振荡器频率的分子时犯了一个错误,结果是在这个配置中N2被设置为4,因为它是2*(PLLPOST+1) PLLPOST = 1 与我原先的想法相反,N2是(PLLPOST+1)

所以在这种情况下,Fosc = 7.37 * 13 /(12 * 4)= 2Mhz,这意味着Fcy是其中的一半,1Mhz