stm32 RCC 时钟分析

stm32芯片手册上有张图表示的很清楚,一共有4个时钟源:

1.HSI(内部高速时钟 8MHz)提供可以位系统时钟提供时钟源

2.HSE(外部高速时钟)可以提供系统时钟和RTC时钟时钟源

3.LSE(低速外部时钟32.768kHz)可以为可以为RTC提供时钟源

4.LSI(低速内部时钟)可以为独立看门狗提供时钟源

首先分析一下ST公司给的库函数:我用的是3.5的库

我们看看SystemInit里是什么

void SystemInit (void)

{

RCC->CR |= (uint32_t)0x00000001;
 //打开HSI内部高速时钟

#ifndef STM32F10X_CL

RCC->CFGR &= (uint32_t)0xF8FF0000;//CFCG寄存器的27位没用,所以这个宏没用

#else  //MCO的两位清零,不往外输出时钟,0-15位清零,PLCK 2分频给ADC,HCLK不分频给APB2

RCC->CFGR &= (uint32_t)0xF0FF0000;//HCLK不分频给APB1,sysclk不分频给AHB,HSI用作系统时钟,

#endif /* STM32F10X_CL */

/* Reset HSEON, CSSON and PLLON bits */

RCC->CR &= (uint32_t)0xFEF6FFFF;
 //HSE禁用

/* Reset HSEBYP bit */

RCC->CR &= (uint32_t)0xFFFBFFFF;
//外部高速时钟未被旁路

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

RCC->CFGR &= (uint32_t)0xFF80FFFF;     //PLL 1.5分频,给USBpre,PLLMUL *2,HSE未分频做PLL输入HSI/2做PLL输入

#ifdef STM32F10X_CL

/* Reset PLL2ON and PLL3ON bits */

RCC->CR &= (uint32_t)0xEBFFFFFF;
//

/* Disable all interrupts and clear pending bits  */

RCC->CIR = 0x00FF0000;
//禁止所有中断,清中断标志位

/* Reset CFGR2 register */

RCC->CFGR2 = 0x00000000;

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* Disable all interrupts and clear pending bits  */

RCC->CIR = 0x009F0000;

/* Reset CFGR2 register */

RCC->CFGR2 = 0x00000000;

#else

/* Disable all interrupts and clear pending bits  */

RCC->CIR = 0x009F0000;

#endif /* STM32F10X_CL */

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

#ifdef DATA_IN_ExtSRAM

SystemInit_ExtMemCtl();

#endif /* DATA_IN_ExtSRAM */

#endif

/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

/* Configure the Flash Latency cycles and enable prefetch buffer */

SetSysClock();
//最终调用时钟设置函数,下面分析

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /*中断向量表定位在SRAM_BASE(0X20000000)+VECT_TAB_OFFSET(0X0)处*/

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /*中断向量表定位在FLASH_BASE(0X08000000)+VECT_TAB_OFFSET(0X0)处 */

#endif

}

下面看看SetSysClock()函数

static void SetSysClock(void)

{

#ifdef SYSCLK_FREQ_HSE

SetSysClockToHSE();

#elif defined SYSCLK_FREQ_24MHz

SetSysClockTo24();

#elif defined SYSCLK_FREQ_36MHz

SetSysClockTo36();

#elif defined SYSCLK_FREQ_48MHz

SetSysClockTo48();

#elif defined SYSCLK_FREQ_56MHz

SetSysClockTo56();

#elif defined SYSCLK_FREQ_72MHz

SetSysClockTo72();

#endif

/* 如果上面没有一个宏成立,则HSI用作系统时钟源,一般调用SetSysClockTo72()函数*/

}

static void SetSysClockTo72(void)

{

__IO uint32_t StartUpCounter = 0, HSEStatus = 0;  //__IO uint32_t即vu32

/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/

/* Enable HSE */

RCC->CR |= ((uint32_t)RCC_CR_HSEON); // RCC_CR_HSEON((uint32_t)0x00010000) HSE使能

/* Wait till HSE is ready and if Time out is reached exit */

do

{

HSEStatus = RCC->CR & RCC_CR_HSERDY;//RCC_CR_HSERDY((uint32_t)0x00020000) 测试HSE状态

StartUpCounter++;   //计数等待

} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));   //当计数 > HSEStartUp_TimeOut(0x500)时且HSE可用则跳出

if ((RCC->CR & RCC_CR_HSERDY) != RESET)  //如果HSE可用

{

HSEStatus = (uint32_t)0x01; //HSEStatus置1

}

else

{

HSEStatus = (uint32_t)0x00; //HSEStatus置0

}

if (HSEStatus == (uint32_t)0x01)      //当hse可以用时

{

/* Enable Prefetch Buffer */

FLASH->ACR |= FLASH_ACR_PRFTBE;

/* Flash 2 wait state */

FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);

FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;

/* HCLK = SYSCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;  //HCLK等于系统时钟

/* PCLK2 = HCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//APB高速预分频为HCLK

/* PCLK1 = HCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//APB高低速预分频为HCLK/2

#ifdef STM32F10X_CL

/* Configure PLLs ------------------------------------------------------*/ //没有PLL2

/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */

RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |

RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);

RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |

RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV3);

/* Enable PLL2 */

RCC->CR |= RCC_CR_PLL2ON;

/* Wait till PLL2 is ready */

while((RCC->CR & RCC_CR_PLL2RDY) == 0)

{

}

/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */

RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |

RCC_CFGR_PLLMULL9);

#else

/*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ //PLL9倍频==72MHz

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |

RCC_CFGR_PLLMULL));

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

#endif /* STM32F10X_CL */

/* Enable PLL */

RCC->CR |= RCC_CR_PLLON; //使能PLL

/* Wait till PLL is ready */

while((RCC->CR & RCC_CR_PLLRDY) == 0)  //等待PLL准备好

{

}

/* Select PLL as system clock source */  //设置系统时钟为PLL时钟源

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;

/* Wait till PLL is used as system clock source */ //等待系统时钟准备好

while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)

{

}

}

else

{ /* If HSE fails to start-up, the application will have wrong clock

configuration. User can add here some code to deal with this error */

/* Go to infinite loop */

while (1)   //如果HSE不能用,则跳入死循环

{

}

}

}

时间: 2024-10-01 06:55:22

stm32 RCC 时钟分析的相关文章

[转] STM32各种时钟的区别

[原创]:http://m.oschina.net/blog/129357 我在原创的基础又从另一位博主处引用了一些内容. 时钟系统是处理器的核心,所以在学习STM32所有外设之前,认真学习时钟系统是必要的,有助于深入理解STM32.     下面是从网上找的一个STM32时钟框图,比<STM32中文参考手册>里面的是中途看起来清晰一些:         重要的时钟:   PLLCLK,SYSCLK,HCKL,PCLK1,PCLK2 之间的关系要弄清楚; 1.HSI:高速内部时钟信号 stm3

rcc时钟

1.时钟源 在 STM32 中,一共有 5 个时钟源,分别是 HSI . HSE . LSI . LSE . PLL . ①HSI 是高速内部时钟, RC 振荡器,频率为 8MHz : ②HSE 是高速外部时钟,可接石英 / 陶瓷谐振器,或者接外部时钟源,频率范围是 4MHz – 16MHz : ③LSI 是低速内部时钟, RC 振荡器,频率为 40KHz : ④LSE 是低速外部时钟,接频率为 32.768KHz 的石英晶体: ⑤PLL 为锁相环倍频输出,严格的来说并不算一个独立的时钟源, P

STM32系统时钟

一.时钟树 STM32有4个时钟源: 1)HSE(高速外部时钟源) 外部晶振作为时钟源,范围为4~16MHz,常取为8MHz 2)HSI(高速内部时钟源) 由内部RC振荡器产生,频率为8MHz,但不稳定 3)LSE(低速外部时钟)   以外部晶振作为时钟源,主要供给实时时钟模块,一般用32.768KHz. 4)LSI(低速内部时钟)         由内部RC振荡器产生,也是提供给实时时钟模块,频率约为40KHz. 二.系统启动过程中时钟设置 以使用STM32库函数SystemInit为例进行说

crazyflie2.0 RCC时钟知识

由于目前手里只有16MHZ的2520封装的贴片晶振,8MHZ这种封装做不到这么小,所以就先用16MHZ,这样我们就需要修改程序相关的RCC时钟: 1,stm32f4xx.h #define HSE_VALUE    ((uint32_t)16000000) /*!< Value of the External oscillator in Hz */ 2,system_stm32f4xx.c /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N

STM32之时钟

1.时钟源 三个不同的时钟源可做系统时钟(SYSCLK): HSI 振荡器时钟 :高速内部时钟 HSE 振荡器时钟:高速外部时钟 PLL 时钟 两个二级时钟 LSI(低速内部时钟) :32kHz 低速内部 RC (LSI RC) 独立看门狗时钟源,RTC 可用于自动唤醒停止/待机模式. LSE(低速外部时钟):32.768kHz 低速外部晶振 (LSE crystal) ,可选择作为 RTC(RTCCLK) 时钟源 每一个时钟源不需要时都可以被选择性关闭,用来节省系统电源消耗 预分频器被用来设置

(转)stm32时钟分析

原文传送门 在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. 其实是四个时钟源,如下图所示(灰蓝色),PLL是由锁相环电路倍频得到PLL时钟. ①.HSI是高速内部时钟,RC振荡器,频率为8MHz. ②.HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz. ③.LSI是低速内部时钟,RC振荡器,频率为40kHz. ④.LSE是低速外部时钟,接频率为32.768kHz的石英晶体. ⑤.PLL为锁相环倍频输出,其时钟输入源可选择为HS

stm32时钟分析

文章来源:http://blog.chinaunix.net/uid-21658993-id-3129667.html 在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. 其实是四个时钟源,如下图所示(灰蓝色),PLL是由锁相环电路倍频得到PLL时钟. ①.HSI是高速内部时钟,RC振荡器,频率为8MHz. ②.HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz. ③.LSI是低速内部时钟,RC振荡器,频率为40kHz. ④.LSE

(六)STM32的时钟系统

   在STM32中,一共有5个时钟源,分别是HSI.HSE.LSI.LSE.PLL (1) HSI是高速内部时钟,RC振荡器,频率为8MHz: (2) HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz: (3) LSI是低速内部时钟,RC振荡器,频率为40KHz: (4) LSE是低速外部时钟,接频率为32.768KHz的石英晶体: (5) PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL的输入可以接HSI/2.HSE或者HSE/

STM32 开机流程分析

一.启动模式,决定向量表的位置 当CPU上电后,首先代码区(Flash)应该从地址为0x00000000开始,而数据区(SRAM)应该从0x20000000开始,Cortex - M3 CPU总是通过代码区获得复位向量.STM32F10XXX微处理器中运用了特殊的机制使得STM32不仅可以通过Flash(主闪存和系统闪存)启动,同时还可以从SRAM中启动. STM32 有下面3种启动方式: 关于Main Flash/System Memory/SRAM 可以参见下面内存映射: 从上图可以看出 0