结合函数库的一个WDT的代码来说说看怎么设置系统时钟到选择外设时钟的: /***************************************************************************** ** Main Function main() ******************************************************************************/ int main (void) { SystemInit(); /* Config WDT clock */ WDT_CLK_Setup(WDTCLK_SRC_MAIN_CLK); /*** The main Function is an endless loop ****/ init_timer16( 0, TIME_INTERVAL ); WDTInit(); enable_timer16( 0 ); while( 1 ) { if ( timer16_0_counter > 0 ) { /* Feed the watchdog timer */ feed_counter++; WDTFeed(); timer16_0_counter = 0; } } }
上面作棕色的为我们即将仔细分子的两个子函数:
void WDT_CLK_Setup ( uint32_t clksrc ) { /* Watchdog configuration. */ /* Freq = 0.5Mhz, div_sel is 0, divided by 2. WDT_OSC should be 250khz */----小心烟幕弹,这里是误导人的 LPC_SYSCON->WDTOSCCTRL = (0x1<<5)|0x00; //bit5=1,Freq(Fclkana)=0.5MHZ LPC_SYSCON->WDTCLKSEL = clksrc; /* Select clock source看门狗时钟源为系统主时钟Main clock */ /*接下来我们会带领大家去寻找Main clock=???????????????*/ LPC_SYSCON->WDTCLKUEN = 0x01; /* Update clock 看门狗时钟源更新*/ LPC_SYSCON->WDTCLKUEN = 0x00; /* Toggle update register once看门狗时钟源更新启用要求先向WDTCLKUEN写0,再写1为启用 */ LPC_SYSCON->WDTCLKUEN = 0x01; while ( !(LPC_SYSCON->WDTCLKUEN & 0x01) ); /* Wait until updated */ LPC_SYSCON->WDTCLKDIV = 1; /* Divided by 1 分频器值为1 */ LPC_SYSCON->;PDRUNCFG &= ~(0x1<<6); /* Let WDT clock run 为PDRUNCFG的bit7清零赋值即SYSPLL_PD=0,这个很关键的,决定主时钟Pclk的计算方式 */ return; /* 首先我们必须确认Main clock的具体大小,然后再根据其他的值来计算WDT的具体时钟 */ }
void SystemInit (void) { uint32_t i; #if (CLOCK_SETUP) /* Clock Setup */ LPC_SYSCON->SYSOSCCTRL = 0; /* Reset Clock Settings */ LPC_SYSCON->;PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */ for (i = 0; i < 200; i++); #if (SYSCLK_SETUP) /* System Clock Setup */ #if (SYSOSC_SETUP) /* System Oscillator Setup */ LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val; #if (SYSPLL_SETUP) /* System PLL Setup */ LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input-- 系统PLL时钟源为System oscillator */ /*个人添加注释解释System oscillator下面文字来之LPC1343官方文档 When the system oscillator is not used, connect XTALIN and XTALOUT as follows: XTALIN can be left floating or can be grounded (grounding is preferred to reduce susceptibility to noise). XTALOUT should be left floating. 可以知道这里不做特别说明的话默认System oscillator为外部接入的晶振12M */ LPC_SYSCON->SYSPLLCLKUEN = 0x01; /* Update Clock Source */ LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */ LPC_SYSCON->SYSPLLCLKUEN = 0x01; while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */ LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val; /* 由SYSPLLCTRL = SYSPLLCTRL_Val=0x25有如下值 MSEL=5 //反馈分频器值。分频值M为MSEL+1 PSEL=0x01 //后置分频器速率P。分频率为2×P DIRECT=0 //CCO时钟输出控制 BYPASS=0 //旁路系统振荡器 */ LPC_SYSCON->;PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL SYSPLL_PD=0 */ /* 由此可以判断PLL operating modes为普通模式,按照手册上说的普通模式计算Fclkout为 Fclkout = M x Fclkin = (FCCO)/(2*P) Fclkin为system PLL 输入时钟由前面代码LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val 得出PLL时钟源为System oscillator,不做特别说明的话默认System oscillator为外部接入的晶振12M 即有Fclkout(Frequency of sys_pllclkout)=(5+1)*12M=72M */ while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */ #endif #endif if ((SYSPLLCLKSEL_Val & 3) == 2) { /* If WDT Clock Selected */ LPC_SYSCON->;PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */ } LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */ /* main clock时钟源选择为System PLL clock out,即main clock为PLL输出时钟Fclkout(Frequency of sys_pllclkout)=(5+1)*12M=72M 到此意味着WDT看门狗的时钟源为系统主时钟main clock,而main clock又选择的PLL输出时钟Fclkout(Frequency of sys_pllclkout) 而进过计算有Fclkout(Frequency of sys_pllclkout)=(5+1)*12M=72M,由此推出WDT时钟为72M -----------------------------------确定WDT时钟大小*/ 有这个函数库的代码可以小窥,Cortex-M3的时钟真的是很烦烦躁的@@@!
[ 本帖最后由 pepsi360 于 2010-5-24 11:39 编辑 ] |