LPC111X/LPC11Cxx 的时钟产生模块CGU(Clock Generation Unit)如下图所示:
从CGU图中可以看出,处理器的main clock可以来自于IRC、Watchdog和systemclock三个时钟源。
IRC:内部RC振荡电路,可以为处理器提供误差1%精度的时钟源。外部可以接1Mhz ~ 25Mhz的晶振振荡器。看门狗的振荡源范围在7.8Khz ~ 1.8Mhz。
在主程序中,调用void SystemInit (void)函数对处理器的时钟模块进行初始化。
void SystemInit (void)函数如下
在此函数中,我们只先关心有关时钟配置的内容
void SystemInit (void)
{
uint32_t i;
#ifdef __DEBUG_RAM
LPC_SYSCON->SYSMEMREMAP = 0x1; /* remap to internal RAM */
#else
//#ifdef __DEBUG_FLASH
LPC_SYSCON->SYSMEMREMAP = 0x2; /* remap to internal flash */
//#endif
#endif
#if (CLOCK_SETUP) /* Clock Setup */
/* bit 0 default is crystal bypass,
bit1 0=0~20Mhz crystal input, 1=15~50Mhz crystal input. */
LPC_SYSCON->SYSOSCCTRL = 0x00;
/* main system OSC run is cleared, bit 5 in PDRUNCFG register */
LPC_SYSCON->PDRUNCFG &= ~(0x1<<5);
/* Wait 200us for OSC to be stablized, no status
indication, dummy wait. */
for ( i = 0; i < 0x100; i++ );
#if (MAIN_PLL_SETUP)
Main_PLL_Setup();
#endif
#endif /* endif CLOCK_SETUP */
/* System clock to the IOCON needs to be enabled or
most of the I/O related peripherals won't work. */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
return;
}
根据一下定义
#define CLOCK_SETUP 1
#define MAIN_PLL_SETUP 1
#define MAIN_CLKSRCSEL_Val 0x00000001
#define MAIN_PLL_M_Val 0x00000003
#define MAIN_PLL_P_Val 0x00000000
#define SYS_AHB_DIV_Val 1 /* 1 through 255, typical is 1 or 2 or 4 */
可以很容易的分析出对时初始化配置的内容。
LPC_SYSCON->SYSOSCCTRL = 0x00;选择1-20Mhz范围的晶振
LPC_SYSCON->PDRUNCFG &= ~(0x1<<5);配置在PowerDown模式下system振荡的工作模式
配置完后调用
void Main_PLL_Setup ( void )
void Main_PLL_Setup ( void )
{
uint32_t regVal;
ClockSource = OSC_CLK;
LPC_SYSCON->SYSPLLCLKSEL = MAIN_CLKSRCSEL_Val; /* Select system OSC */
LPC_SYSCON->SYSPLLCLKUEN = 0x01; /* Update clock source */
LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* toggle Update register once */
LPC_SYSCON->SYSPLLCLKUEN = 0x01;
&nbsnbsp; while ( !(LPC_SYSCON->SYSPLLCLKUEN & 0x01) ); /* Wait until updated */
regVal = LPC_SYSCON->SYSPLLCTRL;
regVal &= ~0x1FF;
LPC_SYSCON->SYSPLLCTRL = (regVal | (MAIN_PLL_P_Val<<5) | MAIN_PLL_M_Val);
/* Enable main system PLL, main system PLL bit 7 in PDRUNCFG. */
LPC_SYSCON->PDRUNCFG &= ~(0x1<<7);
while ( !(LPC_SYSCON->SYSPLLSTAT & 0x01) ); /* Wait until it's locked */
LPC_SYSCON->MAINCLKSEL = 0x03; /* Select PLL clock output */
LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK clock source */
LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle update register once */
LPC_SYSCON->MAINCLKUEN = 0x01;
while ( !(LPC_SYSCON->MAINCLKUEN & 0x01) ); /* Wait until updated */
LPC_SYSCON->SYSAHBCLKDIV = SYS_AHB_DIV_Val; /* SYS AHB clock, typical is 1 or 2 or 4 */
#if MAIN_PLL_SETUP
SystemFrequency = ClockSource * (MAIN_PLL_M_Val+1);
#else
SystemFrequency = ClockSource;
#endif
&nbsnbsp; SystemAHBFrequency = (uint32_t)(SystemFrequency/SYS_AHB_DIV_Val);
return;
}
在Main_PLL_Setup()函数中完成了时钟的选择、倍频、分频的设置
ClockSource = OSC_CLK; /* 选择时钟源来自OSC_CLK(即在处理器外部接的晶振源)
我们在外部接的晶振时钟源为12Mhz。*/
LPC_SYSCON->SYSPLLCLKSEL = MAIN_CLKSRCSEL_Val; //选择System oscillator
设置PLL:
regVal = LPC_SYSCON->SYSPLLCTRL;
regVal &= ~0x1FF;
LPC_SYSCON->SYSPLLCTRL = (regVal | (MAIN_PLL_P_Val<<5) | MAIN_PLL_M_Val);
LPC_SYSCON->MAINCLKSEL = 0x03; /* Select PLL clock output */