LPC11U68的系统时钟整体来说还是比较简单了,通过时钟树,就可以清晰明白的了解到LPC11U68的时钟结构。
其中,有两个时钟参数是比较重要的,这里就主要分析这两个时钟:main clock和system clock. main clock: 由图可知,主时钟可以有多种来源,包括内部内部振荡器IRC,看门狗振荡器,PLL等。锁相环可以输出一个稳定且频率较高的时钟。我们需要一个频率高于12MHz主时钟,所以使用PLL锁相环来产生main clock。 system clock:系统时钟由主时钟分频而来,这个系统时钟主要是给CPU,AHB上面的各种外设提供时钟来源,系统时钟可以等于等于主时钟,但是系统时钟不能超过50MHz(主时钟不能超过100MHz,user manual描述如此)。 时钟选择具体操作如下: 首先我们知道,在IAR工程里面,相关的时钟初始化操作是在mian函数之前完成的。参考启动代码可知,在单片机启动过程中,会调用SystemInit()这个函数,这个函数里面就是时钟配置的相关代码。我们找到这个函数,将其修改为调用E3V_sysclock_init()函数,然后我们就可以开始编写自己的时钟初始化函数了。用为PLL的输入来源可以使单片机内部的12MHz IRC,也可以是来自外部的12MHz晶振,所以我们通过E3V_PLL_USE_IRC和E3V_PLL_USE_XTAL_12M这两个宏进行条件编译,用户可以自行选择采用哪个源来作为PLL的输入。 xxx_pll_init()函数设置主时钟(main clock)的大小,之后再设置system clock的分频系数,得到系统时钟。 - /****************************************************************
- * 功能:初始化PLL得到main_clock,并将其分频得到system_clock
- * 参数:无
- * 修改:2018-11-28
- *****************************************************************/
- void E3V_sysclock_init(void)
- {
- #if defined(E3V_PLL_USE_IRC)
- E3V_irc_pll_init(E3V_MAIN_CLOCK_MHZ);
-
- #elif defined(E3V_PLL_USE_XTAL_12M)
- E3V_xtal_pll_init(E3V_MAIN_CLOCK_MHZ);
- #else
- E3V_irc_pll_init(E3V_MAIN_CLOCK_MHZ);
-
- #endif
- E3V_set_systemclock(E3V_SYSClK_DIV);
- }
- /****************************************************************
- * 功能:启动代码会调用这个函数,进行时钟初始化
- * 参数:无
- * 修改:2018-11-28
- *****************************************************************/
- void SystemInit(void)
- {
-
- E3V_sysclock_init();
-
- }
复制代码PLL倍频设置里面,有几个重要的参数,分别是:M, P, FCLKOUT, FCLKIN, FCCO。相关的寄存器主要是SYSPLLCTRL(里面的msel和psel) 他们的关系可以用以下的等式来表示: /* M = msel + 1
* P = 2^psel = 1,2,4,8 (pesl = 0,1,2,3)
* FCLKOUT = FCLKIN * M = 12MHz * M
* FCCO = FCLKOUT * 2 * P (FCCO range in 156 to 320 MHz)
*/
在在这里,里面有些参数已经是确定值了,而有些是有选择范围的: FCLKIN = 12 已确定; 1<M<32,M为正整数; P = 1,2,4,8, 取值四选一; 156<FCCO<320。 通过这写约束条件,就可以得出FCLKOUT的几种输出的组合方式,在这里main clock = FCLKOUT, 所以可以通过用户设定的参数,设定main clock的大小,利用swich case语句进行不同的参数配置: - switch (mainclock)
- {
- case MAIN_CLOCK_24M:
- Chip_Clock_SetupSystemPLL(1, 2); //M = 2, P = 4
- break;
- case MAIN_CLOCK_36M:
- Chip_Clock_SetupSystemPLL(2, 2); //M = 3, P = 4
- break;
- case MAIN_CLOCK_48M:
- Chip_Clock_SetupSystemPLL(3, 1); //M = 4, P = 2
- break;
- case MAIN_CLOCK_60M:
- Chip_Clock_SetupSystemPLL(4, 2); //M = 5, P = 4
- break;
- case MAIN_CLOCK_72M:
- Chip_Clock_SetupSystemPLL(5, 1); //M = 6, P = 2
- break;
- case MAIN_CLOCK_84M:
- Chip_Clock_SetupSystemPLL(6, 0); //M = 7, P = 1
- break;
- default:
- break;
- }
复制代码main clock设置完成,对其分频即可得到system clock: - void E3V_set_systemclock(uint8_t Div)
- {
- /* 系数为1~255, system_clock = main_clock/Div */
- Chip_Clock_SetSysClockDiv(Div);
- /* 选择PLL作为main clock源 */
- Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT);
- }
复制代码如此,LPC11U68的时钟初始化就完成了,然后我们通过相关的宏,即可完成不同的时钟配置选择: - /****************************************************************
- * 定义: E3V_PLL_USE_IRC
- * 功能: 锁相环PLL的时钟源选择,共两个选项:内部振荡器IRC,外部12M晶振
- * 选项: E3V_PLL_USE_IRC, E3V_PLL_USE_XTAL_12M
- * 定义: E3V_MAIN_CLOCK_MHZ
- * 功能: 设置main_clock的大小,单位MHz
- * 选项: MAIN_CLOCK_72M,36M,48M,60M,72M,84M
- * 定义: E3V_SYSClK_DIV
- * 功能: 设置分频系数,main_clock分频得到system_clock
- * 选项: 1~255
- * 补充: 需要注意的是的 system_clock不能超过50MHz
- * 即: E3V_MAIN_CLOCK_MHZ/E3V_SYSClK_DIV <50
- *****************************************************************/
- #define E3V_PLL_USE_IRC
- #define E3V_MAIN_CLOCK_MHZ MAIN_CLOCK_72M
- #define E3V_SYSClK_DIV 2
复制代码简单测试一下,主时钟配置为72M, 然后两分频得到36M的系统时钟,通过串口打印出来:
1.PLL实验.zip
(313.57 KB, 下载次数: 5)
|