datasheet

STM32时钟系统以及配置及源码分析

2019-07-12来源: eefocus关键字:STM32  时钟系统  配置

1.STM32F429时钟概述

时钟系统是 CPU 的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。 STM32有多个时钟来源的选择,采用一个系统时钟不是很简单吗?为什么 STM32 要有多个时钟源呢? 因为首先 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 k 的时钟即可。同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。


下面是stm32f4的时钟系统图:



STM32 有5个时钟源:HSI、HSE、LSI、LSE、PLL。


 ①、HSI是高速内部时钟,RC振荡器,频率为16MHz,精度不高。可以直接作为系统时钟或者用作PLL时钟输入。  


 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。(此处以25M为例)


 ③、LSI是低速内部时钟,RC振荡器,频率为32kHz,提供低功耗时钟。主要供独立看门狗和自动唤醒单元使用。  


 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。RTC  


 ⑤、PLL为锁相环倍频输出。


附录:


 PLL 为锁相环倍频输出。 STM32F4 有三个 PLL:

1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。第一个输出 PLLP 用于生成高速的系统时钟(最高 180MHz)第二个输出 PLLQ 为 48M 时钟, 用于 USB OTG FS 时钟,随机数发生器的时钟和 SDIO时钟。


2) 第一个专用 PLL(PLLI2S)用于生成精确时钟, 在 I2S 和 SAI1 上实现高品质音频性能。 其中, N 是用于 PLLI2S vco 的倍频系数,其取值范围是: 192~432; R 是 I2S 时钟的分频系数,其取值范围是: 2~7; Q 是 SAI 时钟分频系数,其取值范围是: 2~15; P 没用到。


3) 第二个专用 PLL(PLLSAI)同样用于生成精确时钟,用于 SAI1 输入时钟,同时还为 LCD_TFT接口提供精确时钟。 其中, N 是用于 PLLSAI vco 的倍频系数,其取值范围是: 192~432;Q 是 SAI 时钟分频系数,其取值范围是: 2~15; R 是 LTDC 时钟的分频系数,其取值范围是: 2~7; P 没用到。



例子:主 PLL 时钟第一个高速时钟输出 PLLP 的计算方法:配置180MHz为例:


分析:主 PLL 时钟的时钟源要先经过一个分频系数为 M 的分频器,然后经过倍频系数为 N 的倍频器出来之后还需要经过一个分频系数为 P(第一个输出 PLLP)或者 Q(第二个输出 PLLQ)的分频器分频之后,最后才生成最终的主 PLL 时钟。例如我们的外部晶振选择 25MHz。同时我们设置相应的分频器 M=25,倍频器倍频系数 N=360,分频器分频系数 P=2,那么主 PLL 生成的第一个输出高速时钟 PLLP 为:


PLL=25MHz * N/ (M*P)=25MHz* 360 /(25*2) = 180MHz


配置过程如下图所示: 



2.系统时钟的初始化寄存器源码分析

在系统进入主函数之前,首先会执行SystemInit这个函数对系统进行初始化



看一看这个程序的内容:


源代码如下:


void SystemInit(void)

{

/* FPU 设置------------------------------------------------------------*/

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */

#endif

/* 复位 RCC 时钟配置为默认配置-----------*/

RCC->CR |= (uint32_t)0x00000001;//打开 HSION 位

RCC->CFGR = 0x00000000;//复位 CFGR 寄存器

RCC->CR &= (uint32_t)0xFEF6FFFF;//复位 HSEON, CSSON and PLLON 位

RCC->PLLCFGR = 0x24003010; //复位寄存器 PLLCFGR

RCC->CR &= (uint32_t)0xFFFBFFFF;//复位 HSEBYP 位

RCC->CIR = 0x00000000;//关闭所有中断

#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)

SystemInit_ExtMemCtl();

#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

/* 配置中断向量表地址=基地址+偏移地址 ------------------*/

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

#endif

}

可以看出这段代码的作用是:

1) FPU 设置

2) 复位 RCC 时钟配置为默认复位值(默认开始了 HIS)

3) 外部存储器配置

4) 中断向量表地址配置


做了这些工作,但是在F4的HAL库汇总SystemInit函数,并没有设置系统的主频和外设时钟的频率,所以所以需要自己去写这个函数。


首先先分析一下使用寄存器版本来写的SystemInit函数吧:


//系统时钟初始化函数

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

}   

这个函数需要的参数是4个,分别与系统原理图对应的是,如下图所示:



接下来,查看时钟控制CR寄存器的描述:


1.开启HISON,开启内部高速RC震荡



2.时钟配置寄存器CFRG清零



3.配置时钟控制CR寄存器, 使位HSEON,CSSON,PLLON清零(第16、19、24位) 



4.RCC PLL 配置寄存器 (RCC_PLLCFGR),恢复默认值:RCC->PLLCFGR=0x24003010;    //PLLCFGR恢复复位值


5.设置CR寄存器,外部晶振不旁路



6.RCC 时钟中断寄存器 (RCC_CIR),RCC->CR=0X00000000;  //禁止RCC时钟中断



7.设置时钟,使用函数Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟,函数原型如下:


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; //高性能模式,时钟可到180Mhz

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;

}  

8.RCC->CR|=1<<16;                //设置CR寄存器的第16位为1,HSE 开启



9.等待HSE时钟就绪,判断CR寄存器的第17位是否为1,返回1准备就绪,如果超时,返回标志位status=1.



10.如果准备就绪,使能电源接口时钟,RCC->APB1ENR|=1<<28;    //设置APB1ENR寄存器28位为1电源接口时钟使能



11.开始电源的高性能模式,PWR->CR|=3<<14;         //高性能模式,时钟可到180Mhz



11.配置RCC的CFGR寄存器,//HCLK 不分频;APB1 4分频;APB2 2分频



12.RCC->CR&=~(1<<24);    //关闭主PLL,配置主PLL的一些参数,配置完再重新打开


13.//配置主PLL,PLL时钟源来自HSE,RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);


pllm,设置PLLM


(plln<<6),设置PLLN


(((pllp>>1)-1)<<16),设置系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)

为何是:(((pllp>>1)-1)<<16)呢?如下解释,当我们取值pllp为2时,可以得到(((pllp>>1)-1)<<16)=0


当pllp取值为4时,(((pllp>>1)-1)<<16)=1,同理,pllp取值为6时,(((pllp>>1)-1)<<16)=3.其实就是在调用函数的时候方便设置。可以看都这个寄存器的位,当第17:16为0时,就是这只pllp为2分频。



(pllq<<24),pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.


 


(1<<22),选择主PLL的时钟源是HSE外部震荡时钟、


所以第13步骤,完成的工作就是如下如所示的设置:



14.设置完主PLL之后,重新打开主PLL:  RCC->CR|=1<<24;            //打开主PLL



15.每次打开PLL之前,都要等待就绪:while((RCC->CR&(1<<25))==0);//等待PLL准备好 



16.设置FLASH寄存器参数:


FLASH->ACR|=1<<8;        //指令预取使能.

FLASH->ACR|=1<<9;        //指令cache使能.

FLASH->ACR|=1<<10;        //数据cache使能.

FLASH->ACR|=5<<0;        //5个CPU等待周期.


17.设置CFRG(RCC时钟配置寄存器)选择PLL作为系统时钟,RCC->CFGR&=~(3<<0);

[1] [2] [3] [4] [5]

关键字:STM32  时钟系统  配置

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic467544.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:单片机入门学习八 STM32单片机学习五 时钟系统
下一篇:STM32学习---位带操作总结

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32解决:st-link连接下载程序的问题

STM32解决:Error: Flash Download failed - "Cortex-M3"本人由于使用普中科技的stm32 的开发板的 USB的下载的地方坏了,所以不得不使用arm仿真器 st-link 进行下载。鼓捣了半天下面总结一下几个问题:1、st-link的驱动下载首先你插上st-link的时候,电脑的设备管理器这个地方是有感叹号的,说明还没有装好驱动,所以我就在网上找啊找。终于根据:win8【笔者没这个系统,无法测试,请大家测试后报告】:http://pan.baidu.com/s/1sjJQxZn(转载来自:https://blog.csdn.net/imxiangzi/article
发表于 2019-07-19
STM32解决:st-link连接下载程序的问题

解决stm32f103通过stlink不能烧录程序问题

问题:   stm32(stm32f103c8T6)开发板只能通过串口烧录程序,而st—link居然不行描述:解决:st-link固件升级用stm32cubemx快速开发时没有配置好调试模式重新生成代码就可以了如果还是不行的话,就得升级一下stlink固件了,具体升级方法可百度
发表于 2019-07-19
解决stm32f103通过stlink不能烧录程序问题

STM32下载不成功问题汇总

在某宝上买了五个最小系统核心板是STM32F103C8T6的芯片,刚拿到手准备下载程序调试,上电后板子自带LED闪烁,这是商家自己下载的示例程序,说明芯片工作着,用KEIL4进行下载自己程序,把自己编译好的程序下载。用的JLINK的四线下载调试下载口,SW的调试接口,点击下载后发现擦除成功,下载失败,提示:Load "..\Output\STM32-DEMO.axf" Set JLink Project File to "F:文件RFID程序电机USERJLinkSettings.ini"* JLink Info: Device "STM32
发表于 2019-07-19
STM32下载不成功问题汇总

STM32高级开发(11)-使用GDB调试你的工程

/scripts/target/stm32f4x_stlink.cfg在执行完此条指令后该终端就会一直执行OpenOCD的程序了,不要关闭它,我们再打开一个终端界面,进入我们的工程目录,比如我这里进入的就是我的libopencm3样例工程下的blink子工程目录。$ cd '/home/yangliu/workspace/libopencm3-my-example/blink'然后我们使用指令输入调试文件并打开GDB程序。$ arm-none-eabi-gdb blink.elf 然后我们在GDB的指令界面中,输入连接指令,连接本地的3333端口。(gdb)target remote localhost:3333此时
发表于 2019-07-19
STM32高级开发(11)-使用GDB调试你的工程

STM32F4标准外设库模板工程建立与使用

SW4STM32安装其实固件库安装过程很简单,在第一次新建工程时会提示选择使用Stdperiph 驱动还是Cube HAL,由于Stm32官方大力推行Cube HAL固件库,所以Cube HAL的固件库直接可以从网上直接一键下载安装。然而对于老的StdPeriph固件库不能一键式下载安装,会提示出错。所以,我们需要自己下载一个.zip固件包,放在C:UsersLYAppDataRoamingAc6SW4STM32firmwares文件夹下,其中的LY就是计算机的用户名。然后新建工程时在选择Stdperiph固件时会自动解压缩,这样就能使用该库进行编译了。界面如下所示:工程配置器件与时钟或者,修改晶振与时钟,根据注释可以算得
发表于 2019-07-19
STM32F4标准外设库模板工程建立与使用

基于STM32的外设的GPIO外设设置总结

1、背景外设驱动的寄存器设置对于外设功能正常运行异常重要。现在对GPIO的配置进行总结。2、GPIO的配置总结复用GPIO配置GPIO设置为输出或者是复用模式时,需要设置输出速度;而无论设置为什么模式,都要对GPIO的内部上下拉进行设置。注意:在输入模式(普通输入/模拟输入)下,OTYPE和OSPEED参数无效!!
发表于 2019-07-19
基于STM32的外设的GPIO外设设置总结

小广播

何立民专栏

单片机及嵌入式宝典

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

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved