STM32F2系列系统时钟默认配置

发布者:chuyifei最新更新时间:2018-08-13 来源: eefocus关键字:STM32F2系列  系统时钟  默认配置 手机看文章 扫描二维码
随时随地手机看文章

新到一家公司后,有个项目要用到STM32F207Vx单片机,找到网上的例子照猫画虎的写了几个例子,比如ADC,可是到了ADC多通道转换的时候就有点傻眼了,这里面的时钟跑的到底是多少M呢?单片机外挂的时钟是25M,由于该单片机时钟系统较为复杂,有内部高/低、外部高/低 、PLL锁相环时钟,又有AHB总线时钟、APB1/2时钟,而例子中很少讲到系统时钟的默认配置是怎么配置呢?那么就发点时间研究下这个单片机内部的复杂时钟系统吧。

下图是STM32F2系列的时钟树结构图:

1、内部高速时钟HSI、外部高速时钟HSE和PLL时钟PLLCLK时钟都接到了SW开关处,通过SW选择哪一路作为SYSCLK,SYSCLK经过AHB分频器进行分频得到HCLK,APB1和APB2是挂在总线AHB上的,通过APB1和APB2分频得出fpclk1和fpclk2。

2、PLL输入时钟源主要是靠外部高速时钟和内部高速时钟作为时钟源,通过PLLCFGR寄存器的bit22来选择具体哪一路作为时钟源。选择好了时钟源进入/M分频器,也就是PLLM进行分频,送入VCO,在通过xN,进行倍频,也就是PLLN:(1)通过/P进行分频(PLLP)得到PLLCLK;(2)通过/Q分频(PLLQ),得到PLL48CK。

然后边看代码边对照结构图进行分析,看软件如何给单片机配置系统时钟的。

然后找到启动代码“startup_stmf32xx.s”,该代码是用汇编写的,可以看到,在调用main函数之前,是先调用了SystemInit函数的,该函数是在“system_stm32f2xx.c”中

; Reset handler

Reset_Handler    PROC

                 EXPORT  Reset_Handler             [WEAK]

        IMPORT  SystemInit

        IMPORT  __main

                 LDR     R0, =SystemInit

                 BLX     R0

                 LDR     R0, =__main

                 BX      R0

                 ENDP


代码如下,变量直接赋个16进制的数,都不知道是啥意思,目的是干什么的,不知道,所以看下面代码时最好对照STM32F2x用户手册。当然这个只是一个初始化,待会主要看SetSysClock();这个函数,在调用该函数之前,我们知道单片机是先启用了内部高速时钟等一些配置。



void SystemInit(void)

{

  /* Reset the RCC clock configuration to the default reset state ------------*/

  /* Set HSION bit */

  RCC->CR |= (uint32_t)0x00000001; //RCC_CR复位值0x0000_xx83,内部高速时钟使能,也就是说上电开始就使用内部高速时钟,16MHZ


  /* Reset CFGR register */

  RCC->CFGR = 0x00000000;    //通过开关SW选择内部高速时钟作为系统时钟16MHZ

                                                        //AHB prescaler 不分频

                                                      //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ

                                                        //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ

                              //MCO1和MCO2时钟输出等配置可参考用户手册Page95


  /* Reset HSEON, CSSON and PLLON bits */

  RCC->CR &= (uint32_t)0xFEF6FFFF;


  /* Reset PLLCFGR register */

  RCC->PLLCFGR = 0x24003010; //RCC_CFGR复位值是0x2400_3010


  /* Reset HSEBYP bit */

  RCC->CR &= (uint32_t)0xFFFBFFFF;  //对bit18 HSEBYP 设置为0,外部高速时钟被禁止


  /* Disable all interrupts */

  RCC->CIR = 0x00000000;  //所有时钟中断都被禁止


#ifdef DATA_IN_ExtSRAM

  SystemInit_ExtMemCtl(); 

#endif /* DATA_IN_ExtSRAM */

         

  /* Configure the System clock source, PLL Multiplier and Divider factors, 

     AHB/APBx prescalers and Flash settings ----------------------------------*/

  SetSysClock();


  /* Configure the Vector Table location add offset address ------------------*/

#ifdef VECT_TAB_SRAM

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */

#else

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

#endif

}


在SystemInit(void)函数中在配置完一些参数后,还调用了SetSysClock()函数,该函数代码如下



static void SetSysClock(void)

{

/******************************************************************************/

/*            PLL (clocked by HSE) used as System clock source                */

/******************************************************************************/

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  

  /* Enable HSE */

  RCC->CR |= ((uint32_t)RCC_CR_HSEON);  //外部高速时钟使能,25MHZ

 

  /* Wait till HSE is ready and if Time out is reached exit */  //外部时钟使能后,得需要一点时间到达各个端口

  do

  {

    HSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好

    StartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时

  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));


  if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的

  {

    HSEStatus = (uint32_t)0x01;   //说明时钟已准备好了,才结束do whlie循环

  }

  else

  {

    HSEStatus = (uint32_t)0x00;  //说明是因为超时了而退出do while循环

  }


  if (HSEStatus == (uint32_t)0x01)

  {

    /* HCLK = SYSCLK / 1*/

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M

      

    /* PCLK2 = HCLK / 2*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M

    

    /* PCLK1 = HCLK / 4*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M


    /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

//配置完后RCC->PLLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能

//通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M

//通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN

//bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M

//bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M

//bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M

        

    /* Enable the main PLL */

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


    /* Wait till the main PLL is ready */

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

    {

    }

        //到这里RCC->CR已配置完,最终值0x03036783

        //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启

        

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;


    /* Select the main PLL as system clock source */

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

    RCC->CFGR |= RCC_CFGR_SW_PLL;

        

        //到这里RCC->CFGR已配置完,最终值是0x0000_940A

        //通过查看用户手册,知道,PLL时钟作为系统时钟即120M

        //AHB不分频,即HCLK = 120M

        //APB1 4分频,即fpclk1 = 120/4=30M

        //APB2 2分频,即fpclk2 = 120/2=60M


    /* Wait till the main PLL is used as system clock source */

    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);

    {

    }

  }

  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 */

  }


}


OK,分析完这段代码后,调用系统固件函数后,现在知道了时钟树结构图中右边出来的时钟是多少MHz了吧。


总结:


1、使用的是外部时钟25MHZ,通过PLL进行分频倍频分频得到PLLCLK 120M,PLLCLK作为系统时钟SYSCLK。


2、APB1出来是30M,也就是FPCLK1。


3、APB2出来是60M,也就是FPCLK2。


关键字:STM32F2系列  系统时钟  默认配置 引用地址:STM32F2系列系统时钟默认配置

上一篇:STM32系统时钟修改
下一篇:STM32的时钟系统RCC详细整理

推荐阅读最新更新时间:2024-03-16 16:10

【STM32F103攻城笔记】外部晶振HSE倍频设置系统时钟
上一篇的内部晶振的系统时钟设置已经对系统时钟进行了配置,而外部晶振的倍频只需要改变上一篇的初始化函数就可以,其他均一样! 第一步:建立一个HSE倍频的初始化函数void SystemClock_Config(void) ; 所以我们由上一篇文章变为: int main (void) { RCC_ClocksTypeDef RCC_Clocks; //初始化 SystemClock_Config(); //调用刚才改过的函数 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Usart_Init(115200); //串口为了看数据而已 RCC_GetClocksF
[单片机]
STM32时钟系统学习
时钟系统是处理器的核心,所以在学习STM32所有外设之前,认真学习时钟系统是必要的,有助于深入理解STM32。 下面是从网上找的一个STM32时钟框图,比《STM32中文参考手册》里面的是中途看起来清晰一些: 重要的时钟: PLLCLK,SYSCLK,HCKL,PCLK1,PCLK2 之间的关系要弄清楚; 1、HSI:高速内部时钟信号 stm32单片机内带的时钟 (8M频率) 精度较差 2、HSE:高速外部时钟信号 精度高 来源(1)HSE外部晶体/陶瓷谐振器(晶振) (2)HSE用户外部时钟 3、LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时
[单片机]
STM32<font color='red'>时钟</font><font color='red'>系统</font>学习
STM32查看系统时钟
调用库函数RCC_GetClocksFreq,该函数可以返回片上的各种时钟的频率 函数原形 void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) RCC_ClocksTypeDef定义于文件 stm32f10x_rcc.h : typedef struct { uint32_t SYSCLK_Frequency; /*! SYSCLK clock frequency expressed in Hz */ uint32_t HCLK_Frequency; /*! HCLK clock frequency expressed in Hz */ uint32_t PC
[单片机]
STM32系统中的五个时钟源介绍
时钟信号好比是单片机的脉搏,了解STM32时钟系统很有必要。下图是STM32F1xx用户手册中的时钟系统结构图。 在STM32F1xx中,有五个时钟源,分别为HSI、HSE、LSI、LSE、PLL。 HSI是高速内部时钟,RC振荡器,频率为8MHz HSE是高速外部时钟,可接石英/陶瓷谐振器或者接外部时钟源,频率范围为4MHz~16MHz LSI是低速内部时钟,RC振荡器,频率为40kHz LSE是低速外部时钟,接频率为32.768kHz的石英晶振 PLL为锁相环倍频输出,其输出频率最大不得超过72MHz SYSCLK系统时钟SYSCLK最大频率为72MHz,它是供STM32中绝大部分部件工作的时钟源。系统时钟可由PLL、
[单片机]
STM32<font color='red'>系统</font>中的五个<font color='red'>时钟</font>源介绍
STM32F4 (7) Systemlinit时钟系统初始化函数剖析
开始我们今天的内容,今天主要讲解systeminit , 参考《STM32中文参考手册》、STM32库函数开发 回顾一下上一讲有五个的时钟来源 1.LSI 低速的内部时钟 2.LSE 低速的外部时钟 3HSI 高速的内部时钟 4PLLCLK 通过锁相环 5 HSE高速的外部时钟 SYSCLK 系统时钟,他的主要来源有1HSI 2HSE 3PLLCLK,大部分情况都是用PLLCLK,应为F4芯片可以跑到168Mhz,PLLCLK主要来自主PLLCLK的锁相环,时钟 法人计算方法 之前已经说过,主PLLCLK的锁相环可以选择HSI、HSE作为时钟输入,在我们系统初始化的时候(正点原子)使用的是H
[单片机]
STM32F4 (7) Systemlinit<font color='red'>时钟</font><font color='red'>系统</font>初始化函数剖析
ATmega168 时钟系统及其分布
时钟系统及其分布 Figure12为ATmega168 的主要时钟系统及其分布。这些时钟并不需要同时工作。为了降低功耗,可以通过使用不同的睡眠模式来禁止无需工作的模块的时钟,详见 P32” 电源管理及休眠模式 ” 。下面为时钟系统的详细描述。 CPU 时钟- clkCPU CPU时钟与操作AVR内核的子系统相连,如通用寄存器文件、状态寄存器及保存堆栈指针的数据存储器。终止CPU 时钟将使内核停止工作和计算。 I/O 时钟- clkI/O I/O时钟用于主要的I/O 模块,如定时器/ 计数器、SPI 和USART。I/O 时钟还用于外部中断模块。要注意的是有些外部中断由异步逻辑检测,因此即使I/O 时钟停止了这些中断仍然可以得到
[单片机]
ATmega168 <font color='red'>时钟</font><font color='red'>系统</font>及其分布
详解STM32的时钟系统
STM32的时钟树 时钟信号推动单片机内各个部分执行相应的指令,时钟就像人的心跳一样。 STM32本身十分复杂,外设非常多,任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,如果都用高速时钟势必造成浪费。同一个电路,时钟越快功耗越大、抗电磁干扰能力越弱。复杂的MCU采用多时钟源的方法来解决这些问题。如下图,是STM32的时钟系统框图。 如上图左边的部分,看到STM32有4个独立时钟源,HSI、HSE、LSI、LSE。 HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。 HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 LSI是低速内部时钟,RC
[单片机]
一种基于锁相环的时钟系统设计
图1:锁相环在时钟产生中应用。 锁相环广泛应用于时钟系统设计中,其中包括相位同步以及时钟倍频等应用。通常,当芯片工作频率高于一定频率时,就需要消除由于芯片内时钟驱动所引起的片内时钟与片外时钟间的相位差,嵌入在芯片内部的PLL可以消除这种时钟延时。此外,很多芯片控制链逻辑需要占空比为50%的时钟,因此需要一个2倍于此的时钟源,集成在芯片内部的PLL可以将外部时钟合成为此时钟源。 系统集成PLL可以从内部触发,比从外部触发更快且更准确,能有效地避免一些与信号完整性相关的问题。系统集成PLL的另一个显著特点是通过调节位于锁相环反馈回路中的时钟树缓冲区中的参数,锁相环能够产生相对于参考输入时钟频率不同倍率的内核时钟,这种调节能
[单片机]
一种基于锁相环的<font color='red'>时钟</font><font color='red'>系统</font>设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved