例程就是参考这个步骤来写的,有一点不是太明白的是,最后倍频结束后,分频的时候,当分频为1时,要先进行2分频,然后再进行不分频????
官方例程如下:
void InitPll(Uint16 val, Uint16 divsel)
{
//
// Make sure the PLL is not running in limp mode
//
if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
//检测到时钟信号不好,直接退出
{
//
// Missing external clock has been detected
// Replace this line with a call to an appropriate
// SystemShutdown(); func
tion.
//
asm(" ESTOP0");
}
//
// DIVSEL MUST be 0 before PLLCR can be changed from
// 0x0000. It is set to 0 by an external reset XRSn
// This puts us in 1/4
//
if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
//分频部分先设定为4分频,在PLLCR改变之前,DIVSEL 必须为0
{
EALLOW;
SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
EDIS;
}
//
// Change the PLLCR
//
if (SysCtrlRegs.PLLCR.bit.DIV != val)
{
EALLOW;
//
// Before setting PLLCR turn off missing clock detect logic
//
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
//改变PLL倍频系数时,要把丢失时钟检测关闭
SysCtrlRegs.PLLCR.bit.DIV = val;
EDIS;
//
// Optional: Wait for PLL to lock.
//在对时钟分频时,要保证PLL已经入锁
// During this time the CPU will switch to OSCCLK/2 until
//pLL稳定之前,内核时钟为OSCCLK/2 =15M
// the PLL is stable. Once the PLL is stable the CPU will
// switch to the new PLL value.
//PLL一旦稳定下来,内核时钟转变为新的值
//
// This time-to-lock is monitored by a PLL lock counter.
//
// Code is not required to sit and wait for the PLL to lock.
//代码不需要等待PLL入锁,但是,如何代码在做一些关键的事情时,需要正确的时钟
// However, if the code does anything that is timing critical,
//入锁,最好等待时钟转换完成
// and requires the correct clock be locked, then it is best to
// wait until this switching has completed.
//
//
// Wait for the PLL lock bit to be set.
//
//
// The watchdog should be disabled before this loop, or fed within
//在循环之前,要保证开门狗关闭,或者喂狗
// the loop via ServiceDog().
//
//
// Uncomment to disable the watchdog
//打开看门狗
//
DisableDog();
while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
//等待PLL入锁
{
//
// Uncomment to service the watchdog
//
//ServiceDog();
}
EALLOW;
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
//振荡器时钟丢失检测使能
EDIS;
}
//
// If switching to 1/2
//
if((divsel == 1)||(divsel == 2))
{
EALLOW;
SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
EDIS;
}
//
// NOTE: ONLY USE THIS SETTING IF PLL IS BYPASSED (I.E. PLLCR = 0) OR OFF
// If switching to 1/1
// * First go to 1/2 and let the power settle
// The time required will depend on the system, this is only an example
// * Then switch to 1/1
//
if(divsel == 3)
//??????????????????????不明白为什么要这样来,不是直接赋成3就行了,,求解,我看网上有说是为了防止两个
{
//分频器同时分频出现错误,可是这样先分成2分频,再分成1分频就行了??????不是太懂,还望大神指点
EALLOW;
SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
DELAY_US(50L);
SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
EDIS;
}
}
红色部分是我的一些理解。
通过以上的配置,就可以得到一个稳定可靠的系统时钟了。为了保证这个时钟时时刻刻稳定可靠,就要对他进行时时刻刻地监控
正常情况下,OSCCLOCK counter(7位)对OSCCLOCK进行计数,VCOCLOCK counter(13位)对VCOCLOCK进行计数,当OSCCLOCK counter计数器溢出时,自动对VCOCLOCK counter清零,正常时,OSCCLOCK counter计数器不会溢出
非正常时(OSCCLOCK时钟丢失时)PLL会进入limp - mode模式并会有一个低频时钟产生,VCOCLOCK counter计数器对该低频时钟进行计数,溢出时将产生一个复位信号对CPU、外设等复位,并将PLLSTS[MCLKCLR]位置1,当检测到PLLSTS[MCLKCLR]位为1时,表明系统时钟工作在limp mode模式下。需要检查硬件是否有问题,通过向PLLSTS[MCLKCLR]写1,对该位清零,并时钟
电路复位,再次上电观察PLLSTS[MCLKCLR]位,重复该过程,直到正常。
考虑到一些外设有可能会需要时钟,DSP专门引出了一个时钟XCLCKOUT为其所用
默认情况下,是将XCLKOUT设置为系统时钟的四分频37.5M,也可以自己设置,最大不超过系统时钟SYSCLKOUT。
这之上的配置过后就可以得到保证系统时时刻刻稳定的时钟了!TI公司又将这个系统时钟分为低速时钟和高速时钟,分别分给不同的外设,之前学习过TI得msp430,这和430里面的架构感觉完全一致,这样可以降低功耗。
为不同的外设提供相应的时钟,低速的外设给你高速的时钟也只能是浪费,并且还有可能速度太快,你跟不上;高速外设提供低速时钟,只能拖后腿,故合适才是最重要的。中庸之道
当有些外设不用的时候,可以将其关闭,以降低功耗,InitSysCtrl()函数中,InitPeripheralClocks()该函数对外设时钟进行初始化,即将一些不必要的外设时钟关闭,以降低功耗。