赞
踩
1、stm32程序怎么设置apb2总线时钟_一目了然!图文教你理解单片机STM32时钟
2、stm32程序怎么设置apb2总线时钟_STM32固件库system文件介绍
3、STM32cubeIDE学习之MX时钟配置_m0_71259837的博客
4、STM32时钟系统的配置寄存器和源码分析 - 浇筑菜鸟 - 博客园
6、STM32 CubeIDE(五)AMBA与时钟树_Asigned的博客-CSDN博客
8、STM32时钟系统_韦东山的博客-CSDN博客_stm32时钟系统
9、stm32 时钟配置——外部时钟倍频、内部时钟倍频 - 走看看
任何单片机的外设使用时都需要时钟信号,包括51单片机,stm32,430等等,因为寄存器是由D触发器组成的,往触发器里面写东西,前提条件是。
为什么51单片机不需要配置时钟,那是因为在51单片机中,一个时钟开启后51单片机里面的功能都可以直接使用了,为了使用方便就把这个时钟设置为默认开启的,
stm32相比起51单片机之所以是低功耗,他将所有的外设都是关闭的,使用者需要用哪个外设的时候,再对应的去开启外设就可以了,这样做就能减少耗能。
在51单片机中一个时钟把所有外设的都包含在内,而stm32的时钟是有分工的,不同外设使用的时钟频率是不一样的,因为没必要所有的时钟都是最高频率,只要够用就行,目的就是节能,所以不同的时钟也会有频率差别,或者在配置的时候可以配置时钟分频。同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。
不同芯片的时钟树不一样,参考手册/用户手册
(1)STM32F42X/F43X时钟树 如下图:系统时钟最高180MHz
(2)STM32F407时钟树 如下图:系统时钟最高168MHz
关于PLL_M值,网上说一定要调节PLL_M分频因子,使输入到PLL的之前的时钟为1M,说法不一定准确
【STM32】晶振,主时钟,外设频率介绍 - 夜桜が舞う - 博客园
“首先很重要的一点,提供给PLL的时钟一定要是1M,不可以是2M、4M...之类的
所以呢,就有了图上的绿圈,除M(代码为PLL_M)
如果是内部晶振(16M)提供,这个除M的值,就必须设16,16M / 16 = 1M
如果是外部晶振提供,假设接了8M的晶振,这个除M的值,就要设8,8M / 8 = 1M”
个人实际配置证明此结论不一定正确,F407配置如下
MX配置时钟树选的PLL_M为4,不是8,也没有飘红提示报错,说明PLL输入端时钟不是一定要为1MHz。
(3)STM32F10x时钟系统图如下: 系统时钟最高72MHz
周知STM32有5个时钟源HSI、HSE、LSI、LSE、PLL,其实他只有四个,因为从上图中可以看到PLL都是由HSI或HSE提供的。
其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低速时钟(LSE和LSI)只是提供给芯片中的RTC(实时时钟)及独立看门狗使用,图中可以看出高速时钟也可以提供给RTC。内部时钟是在芯片内部RC振荡器产生的,起振较快,所以时钟在芯片刚上电的时候,默认使用内部高速时钟。而外部时钟信号是由外部的晶振输入的,在精度和稳定性上都有很大优势,所以上电之后我们再通过软件配置,转而采用外部时钟信号.
高速外部时钟(HSE):以外部晶振作时钟源,晶振频率可取范围为4~16MHz,我们一般采用8MHz的晶振。
高速内部时钟(HSI):由内部RC振荡器产生,频率为8MHz,但不稳定。
低速外部时钟(LSE):以外部晶振作时钟源,主要提供给实时时钟模块,所以一般采用32.768KHz。
低速内部时钟(LSI):由内部RC振荡器产生,也主要提供给实时时钟模块,频率大约为40KHz。
OSC_OUT和OSC_IN开始,这两个引脚分别接到外部晶振8MHz,第一个分频器PLLXTPRE,遇到开关PLLSRC(PLL entry clock source),我们可以选择其输出,输出为外部高速时钟(HSE)或是内部高速时钟(HSI)。这里选择输出为HSE,接着遇到锁相环PLL,具有倍频作用,在这里我们可以输入倍频因子PLLMUL,要是想超频,就得在这个寄存器上做手脚啦。经过PLL的时钟称为PLLCLK。倍频因子我们设定为9倍频,也就是说,经过PLL之后,我们的时钟从原来8MHz的 HSE变为72MHz的PLLCLK。
PLLCLK在输入到SW前,还流向了USB预分频器,这个分频器输出为USB外设的时钟(USBCLK)。
紧接着又遇到了一个开关SW,经过这个开关之后就是STM32的系统时钟(SYSCLK)了。通过这个开关,可以切换SYSCLK的时钟源,可以选择为HSI、PLLCLK、HSE。我们选择为PLLCLK时钟,所以SYSCLK就为72MHz了。
SYSCLK经过AHB预分频器,分频后再输入到其它外设。如输出到称为HCLK、FCLK的时钟,还直接输出到SDIO外设的SDIOCLK时钟、存储器控制器FSMC的FSMCCLK时钟,和作为APB1、APB2的预分频器的输入端。GPIO外设是挂载在APB2总线上的, APB2的时钟是APB2预分频器的输出,而APB2预分频器的时钟来源是AHB预分频器。因此,把APB2预分频器设置为不分频,那么我们就可以得到GPIO外设的时钟也等于HCLK,为72MHz了。
SYSCLK:系统时钟,STM32大部分器件的时钟来源。主要由AHB预分频器分配到各个部件。
HCLK:由AHB预分频器直接输出得到,它是高速总线AHB的时钟信号,提供给存储器,DMA及cortex内核,是cortex内核运行的时钟,cpu主频就是这个信号,它的大小与STM32运算速度,数据存取速度密切相关。
FCLK:同样由AHB预分频器输出得到,是内核的“自由运行时钟”。“自由”表现在它不是来自时钟 HCLK,因此在HCLK时钟停止时 FCLK 也继续运行。它的存在,可以保证在处理器休眠时,也能够采样和到中断和跟踪休眠事件 ,它与HCLK互相同步。
PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总线上的外设,APB1总线上的外设如下:
RCC_APB1Periph_TIM2 TIM2时钟
RCC_APB1Periph_TIM3 TIM3时钟
RCC_APB1Periph_TIM4 TIM4时钟
RCC_APB1Periph_WWDG WWDG时钟
RCC_APB1Periph_SPI2 SPI2时钟
RCC_APB1Periph_USART2 USART2时钟
RCC_APB1Periph_USART3 USART3时钟
RCC_APB1Periph_I2C1 I2C1时钟
RCC_APB1Periph_I2C2 I2C2时钟
RCC_APB1Periph_USB USB时钟
RCC_APB1Periph_CAN CAN时钟
RCC_APB1Periph_BKP BKP时钟
RCC_APB1Periph_PWR PWR时钟
RCC_APB1Periph_ALL 全部APB1外设时钟
PCLK2:外设时钟,由APB2预分频器输出得到,最大频率可为72MHz,提供给挂载在APB2总线上的外设,APB2总线上的外设如下:
RCC_APB2Periph_AFIO 功能复用IO时钟
RCC_APB2Periph_GPIOA GPIOA时钟
RCC_APB2Periph_GPIOB GPIOB时钟
RCC_APB2Periph_GPIOC GPIOC时钟
RCC_APB2Periph_GPIOD GPIOD时钟
RCC_APB2Periph_GPIOE GPIOE时钟
RCC_APB2Periph_ADC1 ADC1时钟
RCC_APB2Periph_ADC2 ADC2时钟
RCC_APB2Periph_TIM1 TIM1时钟
RCC_APB2Periph_SPI1 SPI1时钟
RCC_APB2Periph_USART1 USART1时钟
RCC_APB2Periph_ALL 全部APB2外设时钟
STM32 CUBE MX 配置时钟树的PLL各参数,看完本文豁然开朗
当然,每个MCU型号不同,其PLL数量,及功能也有差异,具体需要看相应手册。
STM32CubeMX配置时钟不用担心出错。
原因很简单,这个工具配置时钟树,如果出错,会有红色警告。
如下图:
具体每一个红色警告错误的原因,将光标移到红色警告过会有相应提示信息。
比如,输出PLLP值超过规定范围:
有这个提示信息,再也不怕配置出错了。
PLL的倍频和分频值
有人觉得前面倍频N值很大(如下图),这样会不会出问题?
答案肯定是不会。但不建议将参数N设置为最大值。
特定时钟频率
有些时候,我们要求有特定时钟频率,比如USB,ETH等。这个时候PLL参数就需要合理才行。
STM32的时钟,在之前使用标准库,或者寄存器时,使用的晶振频率不是官方推荐的,很多人就会搞晕。
那么,就只有参看对应手册,手册上是有明确说明的。比如F4手册RCC章节,详细说明的PLL各参数值范围 PLLM,PLLN,PLLP,PLLQ。
时钟信号的产生是由时钟发生器所提供的,并将信号提供给CPU和外部硬件设备。
系统时钟分为以下三种。
(1)主系统时钟
通过连接一个振荡器到X1和X2,该振荡电路产生fx=1到20MHZ的时钟;
使用内部高速振荡器产生fRH=8MHZ的时钟。
(2)副系统时钟
通过在XT1和XT2之间连接一个fXT=32.768KHZ的振荡器;
通过XT2引脚提供一个外部副系统时钟fexclks=32.768KHZ。
(3)内部低速振荡时钟(看门狗定时器时钟)
内部低速振荡器,以fRL=240KHZ的时钟振荡。该时钟不能作为CPU时钟。
一、在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。
①HSI是高速内部时钟,RC振荡器,频率为8MHz。
②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
③LSI是低速内部时钟,RC振荡器,频率为40kHz。
④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
二、在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法:如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理:
①对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。
②对于少于100脚的产品,有2种接法:第1种:OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能;第2种:分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面)节省2个外部电阻。
三、用HSE时钟,程序设置时钟参数流程:
01、将RCC寄存器重新设置为默认值 RCC_DeInit;
02、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON);
03、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp();
04、设置AHB时钟 RCC_HCLKConfig;
05、设置高速AHB时钟 RCC_PCLK2Config;
06、设置低速速AHB时钟 RCC_PCLK1Config;
07、设置PLL RCC_PLLConfig;
08、打开PLL RCC_PLLCmd(ENABLE);
09、等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟 RCC_SYSCLKConfig;
11、判断是否PLL是系统时钟 while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()
四、下面是STM32软件固件库的程序中对RCC的配置函数(使用外部8MHz晶振)
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : RCC配置(使用外部8MHz晶振)
* Input : 无
* Output : 无
* Return : 无
*******************************************************************************/
void RCC_Configuration(void)
{
/*将外设RCC寄存器重设为缺省值*/
RCC_DeInit();
/*设置外部高速晶振(HSE)*/
RCC_HSEConfig(RCC_HSE_ON); //RCC_HSE_ON——HSE晶振打开(ON)
/*等待HSE起振*/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS) //SUCCESS:HSE晶振稳定且就绪
{
/*设置AHB时钟(HCLK)*/
RCC_HCLKConfig(RCC_SYSCLK_Div1); //RCC_SYSCLK_Div1——AHB时钟= 系统时钟
/* 设置高速AHB时钟(PCLK2)*/
RCC_PCLK2Config(RCC_HCLK_Div1); //RCC_HCLK_Div1——APB2时钟= HCLK
/*设置低速AHB时钟(PCLK1)*/
RCC_PCLK1Config(RCC_HCLK_Div2); //RCC_HCLK_Div2——APB1时钟= HCLK / 2
/*设置FLASH存储器延时时钟周期数*/
FLASH_SetLatency(FLASH_Latency_2); //FLASH_Latency_2 2延时周期
/*选择FLASH预取指缓存的模式*/
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // 预取指缓存使能
/*设置PLL时钟源及倍频系数*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// PLL的输入时钟= HSE时钟频率;RCC_PLLMul_9——PLL输入时钟x 9
/*使能PLL */
RCC_PLLCmd(ENABLE);
/*检查指定的RCC标志位(PLL准备好标志)设置与否*/
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/*设置系统时钟(SYSCLK)*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//RCC_SYSCLKSource_PLLCLK——选择PLL作为系统时钟
/* PLL返回用作系统时钟的时钟源*/
while(RCC_GetSYSCLKSource() != 0x08) //0x08:PLL作为系统时钟
{
}
}
/*使能或者失能APB2外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC , ENABLE);
//RCC_APB2Periph_GPIOA GPIOA时钟
//RCC_APB2Periph_GPIOB GPIOB时钟
//RCC_APB2Periph_GPIOC GPIOC时钟
//RCC_APB2Periph_GPIOD GPIOD时钟
}
五、时钟频率
STM32F103内部8M的内部震荡,经过倍频后最高为72M。目前TI的M3系列芯片最高频率可以达到80M。
在stm32固件库3.0中对时钟频率的选择进行了大范围的简化,原先的一大堆操作都在后台进行。系统给出的函数为SystemInit()。但在调用前还需要进行一些宏定义的设置,具体的设置在system_stm32f10x.c文件中。
文件开头就有一个这样的定义:
//#define SYSCLK_FREQ_HSE HSE_Value
//#define SYSCLK_FREQ_20MHz 20000000
//#define SYSCLK_FREQ_36MHz 36000000
//#define SYSCLK_FREQ_48MHz 48000000
//#define SYSCLK_FREQ_56MHz 56000000
#define SYSCLK_FREQ_72MHz 72000000
ST 官方推荐的外接晶振是 8M,所以库函数的设置都是假定你的硬件已经接了 8M 晶振来运算的.以上东西就是默认晶振 8M 的时候,推荐的 CPU 频率选择.在这里选择了:
#define SYSCLK_FREQ_72MHz 72000000
也就是103系列能跑到的最大值72M
然后这个 C文件继续往下看
#elif defined SYSCLK_FREQ_72MHz
const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_SysClk = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_APB1Clk = (SYSCLK_FREQ_72MHz/2);
const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz;
这就是在定义了CPU跑72M的时候,各个系统的速度了.他们分别是:硬件频率,系统时钟,AHB总线频率,APB1总线频率,APB2总线频率.再往下看,看到这个了:
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
这就是定义 72M 的时候,设置时钟的函数.这个函数被 SetSysClock ()函数调用,而
SetSysClock ()函数则是被 SystemInit()函数调用.最后 SystemInit()函数,就是被你调用的了
所以设置系统时钟的流程就是:
首先用户程序调用 SystemInit()函数,这是一个库函数,然后 SystemInit()函数里面,进行了一些寄存器必要的初始化后,就调用 SetSysClock()函数. SetSysClock()函数根据那个#define SYSCLK_FREQ_72MHz 72000000 的宏定义,知道了要调用SetSysClockTo72()这个函数,于是,就一堆麻烦而复杂的设置~!@#$%^然后,CPU跑起来了,而且速度是 72M. 虽然说的有点累赘,但大家只需要知道,用户要设置频率,程序中就做的就两个事情:
第一个: system_stm32f10x.c 中 #define SYSCLK_FREQ_72MHz 72000000
第二个:调用SystemInit()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。