NXP LPC17xx之时钟模块
来源:互联网 发布:怎么注册开淘宝店 编辑:程序博客网 时间:2024/06/06 03:12
1 模块介绍
图1.系统框图
时钟模块的晶振源一共有3个:主晶振、内部RC晶振、RTC晶振。
1.1 主时钟
一般为12M的晶振,外部输入,LPC1765的引脚名是XTAL1/XTAL2。它是CPU主频的主要时钟源,主晶振的频率范围为1M Hz ~ 25MHz。
1.2 内部RC振荡器
顾名思义,内置的RC振荡器,当然不会很准了,所以该时钟源不能用于USB模块。内部RC振荡器是芯片复位后默认的系统时钟源,频率为:4M Hz。
1.3 RTC时钟
RTC晶振(1 Hz ~ 32768 Hz)主要用于RTC模块实现时钟功能,还有就是看门狗模块,当然,如果你发神经病的话,你可以拿它作为PLL0或CPU的时钟源。RTC晶振一般都是使用32768 Hz的频率,这个频率用来跑秒是最好不过的了。外部输入,引脚名为RTCX1/RTCX2。
1.4 Main PLL(PLL0)
通过寄存器CLKSRCSEL[1:0]可以选择介入Main PLL的时钟源,PLL的功能就是实现稳定的高频率时钟输出,大概框图如下:
图2.PLL系统框图
这里要注意,pllclkin的时钟范围是32768Hz~50MHz,。pllclkin会先被N分频(NSEL[7:0]),得到refclk,refclk和M-DIVIDER(MSEL[14:0])输出的频率差通过鉴频鉴相器、滤波器,最后通过流控晶体振荡器产生的频率Fcco,Fcco最后又通过2*M分频后与Frefclk进行比较,如此循环反馈和调节的过程,最终使得两个频率相同,该过程就是锁相。
若pllclk为目标频率,则有:
(Fpllclk*M)/2 = Frefclk,
即:
Fpllclkin/N = Fpllclk/(2*M)
最后,结合图1,有
Fpllclk = (Fpllclkin*2*M)/N
1.5 usbclk、cclk、pclk
pllclk是个很重要的时钟,它直接为usb模块、系统主频、外设提供时钟源,后端就很好理解了,结合图1很清楚能够明白,稍微配置下寄存器就OK了。其中,cclk就是CPU的主频了。
2 LPC1700CMSIS SystemInit()函数分析
LPC1700CMSIS标准库是专门为LPC17xx系列芯片所设计的底层驱动标准代码,它提供所有外设的控制接口,能大量缩短项目的开发周期。其实之前我对使用库文件这种行为是很不齿的,呵呵,其实也没啥,就是希望当时能够多做一些多学一些,因为写底层驱动还是一个很重要的工作。随着后面慢慢工作重心转向产品功能实现以后,我也慢慢理解了库文件所带来的便利了,呵呵!不过也是建立在已经有了较多底层驱动设计经验的基础上的情况下,言归正传,贴代码:
以下是一些宏定义:
/** @addtogroup LPC17xx_System_Defines LPC17xx System Defines @{ */#define CLOCK_SETUP 1#define SCS_Val 0x00000020#define CLKSRCSEL_Val 0x00000001#define PLL0_SETUP 1#define PLL0CFG_Val 0x00050063#define PLL1_SETUP 1#define PLL1CFG_Val 0x00000023#define CCLKCFG_Val 0x00000003#define USBCLKCFG_Val 0x00000000#define PCLKSEL0_Val 0x00000000#define PCLKSEL1_Val 0x00000000#define PCONP_Val 0x042887DE#define CLKOUTCFG_Val 0x00000000</span>
SystemInit()函数源码:
00499 void SystemInit (void)00500 {00501 #if (CLOCK_SETUP) /* Clock Setup */00502 LPC_SC->SCS = <span style="color:#ff6666;">SCS_Val</span>;00503 if (LPC_SC->SCS & (1 << 5)) { /* If Main Oscillator is enabled */00504 while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready */00505 }00506 00507 LPC_SC->CCLKCFG = CCLKCFG_Val; /* Setup Clock Divider */00508 /* Periphral clock must be selected before PLL0 enabling and connecting00509 * - according errata.lpc1768-16.March.2010 -00510 */00511 LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */00512 LPC_SC->PCLKSEL1 = PCLKSEL1_Val;00513 00514 #if (PLL0_SETUP)00515 LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */00516 00517 LPC_SC->PLL0CFG = PLL0CFG_Val; /* configure PLL0 */00518 LPC_SC->PLL0FEED = 0xAA;00519 LPC_SC->PLL0FEED = 0x55;00520 00521 LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */00522 LPC_SC->PLL0FEED = 0xAA;00523 LPC_SC->PLL0FEED = 0x55;00524 while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */00525 00526 LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */00527 LPC_SC->PLL0FEED = 0xAA;00528 LPC_SC->PLL0FEED = 0x55;00529 while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */00530 #endif00531 00532 #if (PLL1_SETUP)00533 LPC_SC->PLL1CFG = PLL1CFG_Val;00534 LPC_SC->PLL1FEED = 0xAA;00535 LPC_SC->PLL1FEED = 0x55;00536 00537 LPC_SC->PLL1CON = 0x01; /* PLL1 Enable */00538 LPC_SC->PLL1FEED = 0xAA;00539 LPC_SC->PLL1FEED = 0x55;00540 while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1 */00541 00542 LPC_SC->PLL1CON = 0x03; /* PLL1 Enable & Connect */00543 LPC_SC->PLL1FEED = 0xAA;00544 LPC_SC->PLL1FEED = 0x55;00545 while (!(LPC_SC->PLL1STAT & ((1<< 9) | (1<< 8))));/* Wait for PLLC1_STAT & PLLE1_STAT */00546 #else00547 LPC_SC->USBCLKCFG = USBCLKCFG_Val; /* Setup USB Clock Divider */00548 #endif00549 LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */00550 00551 LPC_SC->CLKOUTCFG = CLKOUTCFG_Val; /* Clock Output Configuration */00552 #endif00553 00554 #if (FLASH_SETUP == 1) /* Flash Accelerator Setup */00555 LPC_SC->FLASHCFG = FLASHCFG_Val;00556 #endif00557 00558 // Set Vector table offset value00559 #if (__RAM_MODE__==1)00560 SCB->VTOR = 0x10000000 & 0x3FFFFF80;00561 #else00562 SCB->VTOR = 0x00000000 & 0x3FFFFF80;00563 #endif00564 }
2.1 阶段1-时钟源和分频选择
LPC_SC->SCS = SCS_Val; (1) if (LPC_SC->SCS & (1 << 5)) { /* If Main Oscillator is enabled */ (2) while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready */ } LPC_SC->CCLKCFG = CCLKCFG_Val; /* Setup Clock Divider */ (3) /* Periphral clock must be selected before PLL0 enabling and connecting * - according errata.lpc1768-16.March.2010 - */ LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */ (4) LPC_SC->PCLKSEL1 = PCLKSEL1_Val; (5)
(1)中SCS_Val = 0x00000020,主要是配置Main OSC作为PLL0的时钟源,之后(2)则不停轮询,直到Main OSC准备好为止,这里我觉得是等待晶振稳定。(3)中CCLKCFG_Val =0x00000003,实现对PLL0输出时钟的4分频——Fpll0/4。(5)中PCLKSEL0_Val 和PCLKSEL1_Val都是0,表示所有外设的时钟源都为CCLK/4,即CPU主频的1/4。
2.2 阶段2-PLL0初始化
<span style="font-size:14px;"> LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */ (1) LPC_SC->PLL0CFG = PLL0CFG_Val; /* configure PLL0 */ (2) LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */ (3) LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */ (4) LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */ (5) LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24)))); /* Wait for PLLC0_STAT & PLLE0_STAT */</span>
这里主要就是实现对锁相环0的配置了,就是前面提到的N值、M值等的配置。(1)中CLKSRCSEL_Val = 0x00000001,选择PLL0时钟源,这里选择Main OSC,(3)就是对M值和N值进行设定了,
<span style="font-family:FangSong_GB2312;">PLL0CFG_Val = 0x00050063,即M=100,注意,M的实际值为寄存器的值+1,即99+1,同理N=6,(5)就是使能PLL0了。每次对PLL0的寄存器进行配置时需要依次向PLL0FEED写入0xAA、0x55以使配置生效。OK,最后我们来计算验证下PLL0的输出频率是多少?根据公式:<span style="font-family: FangSong_GB2312; font-size: 18px;">Fpllclk = (Fpllclkin*2*M)/N,若Main OSC为12M,则Fpllclk = 12*2*100/6=400M。最后Fcclk = Fpllclk / 4 = 100M,就是系统时钟频率,那么外设时钟源频率为25M。</span></span>
<span style="font-family:FangSong_GB2312;"><span style="font-family: FangSong_GB2312; font-size: 18px;"></span></span>
2.3 阶段3-初始化PLL1
这里略过了,很简单,暂时还没用到USB模块,先不管了,其实理解了PLL0,这个也基本就理解了,无外乎它专用于USB时钟生成,肯定会有一些区别而已。
2.4 阶段4-初始化FLASH加速模块
#if (FLASH_SETUP == 1) /* Flash Accelerator Setup */ LPC_SC->FLASHCFG = FLASHCFG_Val;#endifFLASHCFG_VAL = 0x0000303A,为默认值。FLASH加速模块在后面再介绍了。
2.5 阶段5-设置VTOR
#if (__RAM_MODE__==1) SCB->VTOR = 0x10000000 & 0x3FFFFF80;#else SCB->VTOR = 0x00000000 & 0x3FFFFF80;#endif
0 0
- NXP LPC17xx之时钟模块
- LPC17XX 学习之系统时钟与功率控制
- LPC17XX 学习之 systick
- msp430单片机之时钟模块
- LPC17xx使用内部晶体(Internal RC Oscillator)作为时钟源
- LPC17xx管脚复用之Uart部分
- LPC17XX 学习之 uCOS-II 移植实例
- Linux 内核时钟架构之时钟源模块对外接口
- nxp
- nxp
- 数字电路设计之同步时钟采样模块
- FPGA开发之时钟管理模块
- NXP TWR-KV11Z75M 塔式系统模块简介
- NXP/Freescale i.MX 计算机模块
- LPC17xx芯片中对ucosii操作系统节拍时钟初始化的时机选择
- LPC17xx之PWM输出脉宽和频率(周期)设置
- Cortex-M3 (NXP LPC1788)之GPIO
- Cortex-M3 (NXP LPC1788)之PWM
- UVa做题阶段性总结(2014-10-22)
- NodeJS服务总是崩溃的解决办法
- 模拟退火算法
- 设计模式学习(1) --- 3类工厂模式
- 运算符
- NXP LPC17xx之时钟模块
- C# 请求Web Api 接口,返回的json数据直接反序列化为实体类
- 谢尔宾斯基三角形,“混沌游戏”实现
- spring中lazy-init详解
- 。。。。。。。。。。。。。。。。。。。。
- 小黑小波比.sql语句过长换行解决方法
- 详细解说 STL 排序(Sort)
- HWND句柄与CWnd窗体类的区别与转换
- 开源Web框架PHP与Ruby on Rail对决