(STM32笔记)九、RCC时钟树与时钟 第二部分
我用的是正点的
STM32F103
来进行学习,板子和教程是野火的指南者
。
之后的这个系列笔记开头未标明的话,用的也是这个板子和教程。
九、RCC时钟树与时钟
- 九、RCC时钟树与时钟
- 2、时钟配置函数
- 时钟初始化思路(72M)
- 复位时钟至默认状态
- 使能HSE,并等待HSE就绪
- 设置flash,设置时钟树,使能PLL
- 更新时钟频率思路
- 获取时钟源
- 选择系统时间源
- 保存在SystemCoreClock
九、RCC时钟树与时钟
2、时钟配置函数
在程序启动文件startup_stm32f10x_hd.s
里找到SystemInit
函数跳转入口
在system_stm32f10x.c
中找到SystemInit
函数
时钟初始化思路(72M)
复位时钟至默认状态
RCC->CR |= (u32)0x00000001; // 开启内部时钟RCC->CFGR &= (u32)0xF8FF0000; // 复位 SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bitsRCC->CFGR &= (u32)0xFF80FFFF; // 复位 PLL和分频的配置RCC->CIR = 0x009F0000; // 关闭中断,清理中断位
使能HSE,并等待HSE就绪
// 配置时钟 HCLK, PCLK, PCLK1, PCLK2, FLASH __IO u32 StartUpCounter = 0, HSEStatus = 0; RCC->CR |= ((u32)RCC_CR_HSEON); // 使能 HSE do{ // 等待HSE就绪HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); // 0x0500
设置flash,设置时钟树,使能PLL
if ((RCC->CR & RCC_CR_HSERDY) != RESET) { FLASH->ACR |= FLASH_ACR_PRFTBE; // 启动预取缓冲区 FLASH->ACR &= (u32)((u32)~FLASH_ACR_LATENCY); // 设置时延FLASH->ACR |= (u32)FLASH_ACR_LATENCY_2; RCC->CFGR |= (u32)RCC_CFGR_HPRE_DIV1; // [7:4] AHB 预分频, HCLK = SYSCLK/1 不分频 RCC->CFGR |= (u32)RCC_CFGR_PPRE2_DIV1; // [13:11] APB2 预分频, APB2 = HCLK/1, 不分频RCC->CFGR |= (u32)RCC_CFGR_PPRE1_DIV2; // [10: 8] APB1 预分频, APB1 = HCLK/2, 2分频RCC->CFGR &= (u32)(~( 1<<16 | 0x01<<17 | 0xF<<18)); // 清零RCC->CFGR |= (u32)(0x01<<16 | 0x07<<18); // PLL 时钟源,低频因子,倍频系数, 使PLLCK= HSE * 9= 72MHz RCC->CR |= (u32)(0x01<<24); // 使能PLL while((RCC->CR & RCC_CR_PLLRDY) == 0) { } // 等待PLL就绪RCC->CFGR &= (u32)((u32)~(0x3<<0)); // 清0RCC->CFGR |= (u32)(0x1 << 1); // 切换系统时钟源为:PLLCLOCK while ((RCC->CFGR & (u32)RCC_CFGR_SWS) != (u32)0x08) { } // 等待系统时钟切换完成}else{ // 重要!!!// 时钟初始化失败 // 处理位置}
更新时钟频率思路
获取时钟源
u32 tmp = 0, pllmull = 0, pllsource = 0; tmp = RCC->CFGR & RCC_CFGR_SWS; // 获取时钟源
选择系统时间源
switch (tmp) {case 0x00: // HSI 内部高速晶振 被选为系统时钟源SystemCoreClock = HSI_VALUE;break;case 0x04: // HSE 外部高速晶振 被选为系统时钟源SystemCoreClock = HSE_VALUE;break;case 0x08: // PLL 被先为系统时钟源 pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; // PLL 时钟源及倍频系数pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; pllmull = ( pllmull >> 18) + 2; if (pllsource == 0x00){ SystemCoreClock = (HSI_VALUE >> 1) * pllmull; // HSI振荡器时钟2分频作为PLL时钟输入}else{ // HSE作为PLL时钟输入 if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (u32)RESET){SystemCoreClock = (HSE_VALUE >> 1) * pllmull; // HSE 2分频}else{SystemCoreClock = HSE_VALUE * pllmull;}}break;default:SystemCoreClock = HSI_VALUE;break;}
保存在SystemCoreClock
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; SystemCoreClock >>= tmp;