标签:
三个不同的时钟源可做系统时钟(SYSCLK):
HSI 振荡器时钟 :高速内部时钟
HSE 振荡器时钟:高速外部时钟
PLL 时钟
两个二级时钟
LSI(低速内部时钟) :32kHz 低速内部 RC (LSI RC) 独立看门狗时钟源,RTC 可用于自动唤醒停止/待机模式。
LSE(低速外部时钟):32.768kHz 低速外部晶振 (LSE crystal) ,可选择作为 RTC(RTCCLK) 时钟源
预分频器被用来设置 AHB, APB (APB2) 和 APB (APB1) 频率。 AHB域最大频率可设置为168 MHz。APB2 域最高频率可达 84 MHz。APB1 域最高频率可达 42 MHz。
AHB:主要用于控制USB,网卡,IO口,DMA等设备 APB:主要用于控制串口,AD,I2C等设备 以上总线时钟分频系数在RCC_CFGR 寄存器的10到15位设置
另:输出时钟的最高频率不得超过100MHz,因为引脚的最高速不超过100MHz
STM32F407ZG允许用TIM5 channel 4 和 TIM11 channel 1捕获时钟源,以此间接的测量所有片上时钟源的频率
TIM5 channel 4
TIM5有一个复用控制器可用来选择输入捕获由I/O触发还是由内部时钟触发。可通过设置 TIM5_OR 的 TI4_RMP [1:0] 位来选择。
测量LSI时钟频率的设置步骤:
- 使能 TIM5 时钟,并配置 channel 4 为输入捕获模式
- 设置 TIM5_OR 寄存器的 TI4_RMP 位为 0x01 来连接 LSI 时钟
- 用TIM5 4个事件或者中断来捕获/比较测量内部时钟
4.用测量到的 LSI 频率来更新 RTC 的预分频对看门狗时钟输出编程
TIM11 channel 1
TIM11有一个复用控制器可用来选择输入捕获由I/O触发还是由内部时钟触发。可通过设置 TIM11_OR 的 TI1_RMP [1:0] 位来选择。
设置步骤与TIM5 channel 4 类似
f(VCO clock) = f(PLL clock input) × (PLLN / PLLM) f(PLL general clock output) = f(VCO clock) / PLLP f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
标号 | 意义 |
---|---|
f(PLL clock input) | 也就是输入到PLL锁相环的时钟,输入源可选择,系统刚刚上电的时候是HSI源,参见下面的:系统复位时钟设置 |
f(VCO clock) | 暂且理解为经倍频之后待输出的频率,之后要进行分频设置,频率大小与芯片硬件相关 |
f(PLL general clock output) | PLL实际输出的时钟频率,参照STM32时钟树图的中间部分SYSCLK 168MHz max处,这个点的时钟频率就是f(PLL general clock output),之后又会经过分频以供不同的设备使用 |
f(USB OTG FS, SDIO, RNG clock output) | 也就是USB SDIO等等的频率,通常48MHz |
对比S3C2440与该STM32也就是Cortex M4的时钟图(S3C2440画的更清晰明了,更详细一点)
STM32的时钟树图:
S3C2440的时钟树图:
寄存器 | 复位值 | 意义 |
---|---|---|
RCC_CR | 0x00000083 | 开启HSI,系统运行刚上电就是以HSI为时钟源运行的 |
RCC_PLLCFGR | 0x24003010 | PLLQ = 4, HSI为PLL源,PLLP = 2,PLLM = 16,PLLN = 192 |
RCC_CFGR | 0x00000000 | 系统时钟不分频,系统时钟源为HSI |
STM32F407ZG寄存器地址映射:
#define BYM_RCC_struct \
((RCC_TypeDef *)(AHB1PERIPH_BASE + 0x3800))
#define BYM_FLASH_struct \
((FLASH_TypeDef *)(AHB1PERIPH_BASE + 0x3C00))
#define F_VCO_CLK_336 ((336 << 6) | (8 << 0))
#define PLL_OUT_CLK_168 (0 << 16)
#define USB_OUT_CLK_48 (7 << 24)
/*
* Initialize system clock
* f(VCO clock) = f(PLL clock input) * (PLLN / PLLM)
* f(PLL general clock output) = f(VCO clock) / PLLP
* f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
*
* PLLP = 2; PLLQ = 7; PLLN / PLLM = 42;
* f(PLL clock input) = 8M; f(VCO clock) = 336M;
* f(PLL general clock output) = 168M; f(USB OTG FS, SDIO, RNG clock output) = 48M
*/
void sys_clk_init(void)
{
/* 开启HSE高速外部时钟 */
BYM_RCC_struct->CR &= ~(1 << 16); //Disable HSE, be required by bit18 if you want to write bit18
BYM_RCC_struct->CR &= ~(1 << 18); //HSE not bypassed
BYM_RCC_struct->CR |= (1 << 16); //Enable HSE
while((BYM_RCC_struct->CR & (1 << 17)) == 0); //Wait for HSE ready
/* 设置倍频系数确定时钟频率(PLL模式) */
BYM_RCC_struct->PLLCFGR &= ~(0xf << 24); //Clear old data
BYM_RCC_struct->PLLCFGR |= USB_OUT_CLK_48; //Flush new data
BYM_RCC_struct->PLLCFGR &= ~(0x3 << 16); //Clear old data
BYM_RCC_struct->PLLCFGR |= PLL_OUT_CLK_168; //Flush new data
BYM_RCC_struct->PLLCFGR &= ~(0x7fff << 0); //Clear old data
BYM_RCC_struct->PLLCFGR |= F_VCO_CLK_336; //Flush new data
/* 选择PLL源为HSE,开启PLL */
BYM_RCC_struct->PLLCFGR |= (1 << 22); //HSE oscillator clock selected as PLL and PLLI2S clock entry
BYM_RCC_struct->CR &= ~(1 << 26); //Close PLLI2S
BYM_RCC_struct->CR |= (1 << 24); //Enable PLL
while((BYM_RCC_struct->CR & (1 << 25)) == 0);
/* 使能指令预取与指令数据Cache(调试过程发现此步是必须的,否则程序没法运行) */
BYM_FLASH_struct->ACR |= (1 << 8); //
BYM_FLASH_struct->ACR |= (1 << 9); //Enable ICache
BYM_FLASH_struct->ACR |= (1 << 10); //Enable DCache
BYM_FLASH_struct->ACR |= (5 << 0); //Wait
/* 配置预分频器来对时钟进行分频 */
BYM_RCC_struct->CFGR &= ~(0x7 << 13);
BYM_RCC_struct->CFGR |= (4 << 13); //APB2 max value = 84M, 2 devided as system clock = 168M
BYM_RCC_struct->CFGR &= ~(0x7 << 10);
BYM_RCC_struct->CFGR |= (5 << 10); //APB1 max value = 42M, 4 devided as system clock = 168M
BYM_RCC_struct->CFGR &= ~(0xf << 4); //system clock not devided
/* 选择系统时钟来源 */
BYM_RCC_struct->CFGR &= ~(0x3 << 0);
BYM_RCC_struct->CFGR |= (2 << 0); //PLL used as system clock
while((BYM_RCC_struct->CFGR & (2 << 2)) == 0);
BYM_RCC_struct->CR &= ~(1 << 0); //Close HSI
while((BYM_RCC_struct->CR & (1 << 1)));
}
由上面的程序可知,某些步骤可以被打乱,但是开启PLL之前必须选择好PLL源以及设置好倍频系数。设置系统时钟来源之前必须先启动ICache与DCache。要关闭HSI的话要在上述步骤设置完之后才能够关闭,因为系统上电之后默认的是HSI为系统时钟源并且使用PLL,所以在HSI还在被使用的时候是不可能被关闭的,只有系统时钟源改变之后才能够被关闭,关闭HSI以节省电量
标签:
原文地址:http://blog.csdn.net/u013904227/article/details/51336353