ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

STM32F4 时钟树概述

2021-07-29 20:31:34  阅读:414  来源: 互联网

标签:分频 Clock 概述 STM32F4 PLL 取值 时钟


STM32F4 相对于 STM32F1 来说,时钟部分复杂了很多, STM32F4 的时钟配置,我们提供两个函数: Sys_Clock_Set 和 Stm32_Clock_Init。其中 Sys_Clock_Set 是核心的系统时钟配置函
数,由 Stm32_Clock_Init 调用,实现对系统时钟的配置。外部程序,一般调用 Stm32_Clock_Init函数来配置时钟。 sys文件夹中

STM32F4 的时钟树图(非常重要)

 

 

上图从左往右看,就是整个 STM32F4 的时钟走向。这里,我们挑选出 9 个重要的地方进行介绍(图 5.2.2.1 中标出的①~⑨)。
① 这是进入 PLL 之前的一个时钟分频系数(M),取值范围是: 2~63,一般取 8。注意,这个分频系数,对主 PLL 和 PLLI2S 都有效。
② 这是 STM32F4 的主 PLL,该部分控制 STM32F4 的主频率(PLLCLK)和 USB/SDIO/随机数发生器等外设的频率(PLL48CK)。其中, N 是主 PLL vco 的倍频系数,其取值
范围是: 64~432; P 是系统时钟的主 PLL 分频系数,其取值范围是: 2、 4、 6 和 8(仅 限这四个值); Q 是 USB/SDIO/随机数产生器等的主 PLL 分频系数,其取值范围是:
2~15; R 没用到。
③ 这是 STM32F4 I2S 部分的 PLL,该部分主要用于设置 STM32F4 I2S 内部输入时钟频率。其中, N 是用于 PLLI2S vco 的倍频系数,其取值范围是: 192~432; R 是 I2S 时钟的分
频系数,其取值范围是: 2~7; P 和 Q 没用到。
④ 这是 PLL 之后的系统主时钟(PLLCLK), STM32F4 的主频最高是 168Mhz,所以我们一般设置 PLLCLK 为 168Mhz(M=8,N=336,P=2),通过 SW 选择 SYSCLK=PLLCLK
即可得到 168Mhz 的系统运行频率。
⑤ 这是 PLL 之后的 USB/SDIO/随机数发生器时钟频率,由于 USB 必须是 48Mhz 才可以正常工作,所以这个频率一般设置为 48Mhz(M=8,N=336,Q=7)。
⑥ 是 I2S 的时钟,通过 I2SSRC 选择内部 PLLI2SCLK 还是外部 I2SCKIN 作为时钟。 探索者 STM32F4 开发板使用的是内部 PLLI2SCLK。
⑦ 这是 Cortex 系统定时器,也就是 SYSTICK 的时钟。上图清楚的表明 SYSTICK 的来源是 AHB 分频后再 8 分频(这个 8 分频是可以设置的,即 8 分频,或者不分频,一般使
用 8 分频), 我们一般设置 AHB 不分频,则 SYSTICK 的频率为: 168M/8=21Mhz。前面介绍的延时函数,就是基于 SYSTICK 来实现的。
⑧ 这里是 STM32F4 很多外设的时钟来源,即两个总线桥: APB1 和 APB2,其中 APB1是低速总线(最高 42Mhz), APB2 是高速总线(最高 84Mhz)。另外定时器部分,如
果所在总线(APB1/APB2)的分频系数为 1,那么就不倍频,如果不为 1(比如 2/4/8/16),那么就会 2 倍频(Fabpx*2)后,作为定时器时钟输入。
⑨ 这是 STM32F4 内部以太网 MAC 时钟的来源。对于 MII 接口来说,必须向外部 PHY芯片提供 25Mhz 的时钟,这个时钟,可以由 PHY 芯片外接晶振,或者使用 STM32F4
的 MCO 输出来提供。然后, PHY 芯片再给 STM32F4 提供 ETH_MII_TX_CLK 和ETH_MII_RX_CLK 时钟。对于 RMII 接口来说,外部必须提供 50Mhz 的时钟驱动 PHY
和 STM32F4 的 ETH_RMII_REF_CLK,这个 50Mhz 时钟可以来自 PHY、有源晶振或者 STM32F4 的 MCO。 我们的开发板使用的是 RMII 接口,使用 PHY 芯片提供 50Mhz
时钟驱动 STM32F4 的 ETH_RMII_REF_CLK。
关于时钟的详细介绍,在《STM32F4xx 中文参考手册》第 6.2 节(106~113 页)有详细介绍。有不明白的地方,可以对照手册仔细研究。 最后,提醒下大家, STM32F4 默认的情况下
(比如串口 IAP 时或未初始化时钟时),使用的是内部 16M 的 HSI 作为时钟的,所以不需要外部晶振也可以下载和运行代码的。
从上图可以看出 STM32F4 的时钟设计的比较复杂,各个时钟基本都是可控的,任何外设都有对应的时钟控制开关,这样的设计,对降低功耗是非常有用的,不用的外设不开启时钟,
就可以大大降低其功耗。
下面开始 Sys_Clock_Set 函数的介绍, 该函数用于配置 STM32F4 的时钟,包括系统主时钟、USB/SDIO/随机数发生器时钟、 APB1 和 APB2 时钟等。 该函数代码如下:

//时钟设置函数
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
//Fvco:VCO 频率
//Fsys:系统时钟频率
//Fusb:USB,SDIO,RNG 等的时钟频率
//Fs:PLL 输入时钟频率,可以是 HSI,HSE 等.
//plln:主 PLL 倍频系数(PLL 倍频),取值范围:64~432.
//pllm:主 PLL 和音频 PLL 分频系数(PLL 之前的分频),取值范围:2~63.
//pllp:系统时钟的主 PLL 分频系数(PLL 之后的分频),取值范围:2,4,6,8.(仅限这 4 个值!)
//pllq:USB/SDIO/随机数产生器等的主 PLL 分频系数(PLL 之后的分频),取值范围:2~15.
//外部晶振为 8M 的时候,推荐值:plln=336,pllm=8,pllp=2,pllq=7.
//得到:Fvco=8*(336/8)=336Mhz
// Fsys=336/2=168Mhz
// Fusb=336/7=48Mhz
//返回值:0,成功;1,失败。
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
u16 retry=0;
u8 status=0;
RCC->CR|=1<<16; //HSE 开启
while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待 HSE RDY
if(retry==0X1FFF)status=1; //HSE 无法就绪
else
{
RCC->APB1ENR|=1<<28; //电源接口时钟使能
PWR->CR|=3<<14; //高性能模式,时钟可到 168Mhz
RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4 分频;APB2 2 分频.
RCC->CR&=~(1<<24); //关闭主 PLL
RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);
//配置主 PLL,PLL 时钟源来自 HSE
RCC->CR|=1<<24; //打开主 PLL
while((RCC->CR&(1<<25))==0);//等待 PLL 准备好
FLASH->ACR|=1<<8; //指令预取使能.
FLASH->ACR|=1<<9; //指令 cache 使能.
FLASH->ACR|=1<<10; //数据 cache 使能.
FLASH->ACR|=5<<0; //5 个 CPU 等待周期.
RCC->CFGR&=~(3<<0); //清零
RCC->CFGR|=2<<0; //选择主 PLL 作为系统时钟
while((RCC->CFGR&(3<<2))!=(2<<2));//等待主 PLL 作为系统时钟成功.
}
return status;
}

在 Sys_Clock_Set 函数中,我们设置了 APB1 为 4 分频, APB2 为 2 分频, HCLK 不分频,同时选择 PLLCLK 作为系统时钟。该函数有 4 个参数,具体意义和计算方法,见函数前面的说
明。 一般我们推荐设置为: Sys_Clock_Set(336,8,2,7),即可设置 STM32F4 运行在 168Mhz 的频率下, APB1 为 42Mhz, APB2 为 84Mhz, USB/SDIO/随机数发生器时钟为 48Mhz。

 

 以上代码中, RCC 和 FLASH 都是 MDK 定义的一个结构体,包含 RCC/FLASH 相关的寄存器组。其寄存器名与《STM32F4xx 中文参考手册》 里面定义的寄存器名字是一摸一样的,所
以在你不明白某个寄存器干什么用的时候,可以到《STM32F4xx 中文参考手册》里面查找一下,你就可以迅速查到这个寄存器的作用以及每个位所代表的意思。 特别注意,由于 FLASH 速度
远远跟不上 CPU 的运行频率,所以这里我们设置了 FLASH 的等待周期为 5, 很明显, FLASH会大大拖慢程序的运行,不过 STM32F4 有自适实时存储器加速器(ART),通过这个加速器,可
以让 STM32F4 获得相当于 0 FLASH 等待周期的运行效果。关于 STM32F4 的 FLASH 以及 ART等的介绍,请大家参考《STM32F4xx 中文参考手册》第 3.3 节(59 页开始)。
接下来,我们再看下 Stm32_Clock_Init 函数,该函数代码如下:

//系统时钟初始化函数
//plln:主 PLL 倍频系数(PLL 倍频),取值范围:64~432.
//pllm:主 PLL 和音频 PLL 分频系数(PLL 之前的分频),取值范围:2~63.
//pllp:系统时钟的主 PLL 分频系数(PLL 之后的分频),取值范围:2,4,6,8.(仅限这 4 个值!)
//pllq:USB/SDIO/随机数产生器等的主 PLL 分频系数(PLL 之后的分频),取值范围:2~15.
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
RCC->CR|=0x00000001; //设置 HISON,开启内部高速 RC 振荡
RCC->CFGR=0x00000000; //CFGR 清零
RCC->CR&=0xFEF6FFFF; //HSEON,CSSON,PLLON 清零
RCC->PLLCFGR=0x24003010; //PLLCFGR 恢复复位值
RCC->CR&=~(1<<18); //HSEBYP 清零,外部晶振不旁路
RCC->CIR=0x00000000; //禁止 RCC 时钟中断
Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟
//配置向量表
#ifdef VECT_TAB_RAM
MY_NVIC_SetVectorTable(1<<29,0x0);
#else
MY_NVIC_SetVectorTable(0,0x0);
#endif
}

该函数主要进行了时钟配置前的一些设置工作,然后通过调用 Sys_Clock_Set 函数,实现对 STM32F4 的时钟配置。最后,根据代码运行的位置( FLASH or SRAM), 调用函数
MY_NVIC_SetVectorTable 进行中断向量表偏移设置。MY_NVIC_SetVectorTable 函数的代码如下:

//设置向量表偏移地址
//NVIC_VectTab:基址
//Offset:偏移量
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab,u32 Offset)
{
SCB->VTOR=NVIC_VectTab|(Offset&(u32)0xFFFFFE00);
//设置 NVIC 的向量表偏移寄存器,VTOR 低 9 位保留,即[8:0]保留。
}

该函数是用来配置中断向量表基址和偏移量,决定是在那个区域。当在 RAM 中调试代码 的时候,需要把中断向量表放到 RAM 里面, 这就需要通过这个函数来配置。关于向量表的详
细介绍请参考《Cortex M3 与 M4 权威指南》第 4.5.3 节(117 页)或者《Cortex M3 权威指南》第七章,第 113 页的向量表一章。 关于 SCB->VTOR 寄存器,请参考《STM32F3 与 F4 系列 Cortex
M4 内核编程手册》第 4.4.4 节(212 页),有详细描述。

 

 

 

标签:分频,Clock,概述,STM32F4,PLL,取值,时钟
来源: https://www.cnblogs.com/caiya/p/15076923.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有