STM32之时钟

1. 什么是时钟

1.1 时钟和时钟树的概念

1.1.1 时钟:

• 时钟是指 为芯片内部的各个模块(片上外设)提供 时间基准 的信号源,是芯片正常工作的基础。我们在写程序之前,首先都需要给要使用的那个模块(外设)打开时钟。

• 时钟是一种方波信号,时钟的频率越快,外设工作效率就越高。

• 时钟其实也可以理解人的心跳。

1.1.2 时钟树,如图:


• 如上图,用一棵树的形式,生动形象表示单片机的时钟系统。

• 可以把时钟树理解为血液系统,为单片机的每个外设输送时钟信号(血液)。

• 时钟树上的树根表示晶振的来源(时钟的来源),树干表示产生SYSCLK那一部分,树枝表示的AHB,APB1和APB2这三条总线,树叶表示的片上外设。

• 其中时钟树可以为高速时钟树(几十MHz)和低速时钟树(几十kHz)。

1.2 分频器,锁相环和复用器,如图:

• 分频器:对频率做除法。

• 锁相环:对频率做乘法。

• 复用器:对频率做选择。

1.3 树根,如图:

• 树根就是时钟的来源,内部时钟有两个LSI,HSI但是内部的时钟精度不高。

• 时钟的来源有四种,LSI,LSE,HSI,HSE。

1.4 树干,如图:

• 树干:对时钟信号 进行加工 从而得到SYSCLK

• 如图,能得到的SYSCLK的三种情况:

• HSI得到的SYSCLK:方便,都是精度不高。

• 锁相环得到的SYSCLK:灵活,可以得到不同的 SYSCLK 频率。

• HSE得到的SYSCLK:精度高。

1.5 树枝,如图:

• 树枝其实就是上图的三条总线。

• 树叶指的就是片上外设,如图:

• 通过SYSCLK分频,可以进一步 得到 这三条总线相对应的时钟,也就是说对SYSCLK进行分频,得到的HCLK,PCLK1和PCLK2。

2. 时钟树编程

2.1 时钟树初始状态

• 初始状态:给单片机刚上电或者按了复位按钮之后,还没来得及执行相应代码,此时单片机的状态。如图:

• 此时在初始状态下,单片机上面的时钟为8MHz ,由HSI 提供,所以SYSCLK=HCLK=PCLK1=PCLK2=8MHz,此时的CPU(Cortex-M3的频率)也是8HMz。CPU 频率决定单片机代码的执行效率。

2.2 标准库的启动代码,如图:

• 在启动文件中,可以找到这一段的代码,其中单片机启动的时候,先是执行了SystemInit这一段代码,也就是先配置 系统时钟 为72MHz,然后在执行main里面的函数。

• 如图,经过SystemInit之后,时钟由 8HMz 变成 72MHz

2.3 时钟树的编程接口

• 这些编程接口一一对应时钟树的器件,总线等等。

• 配置的步骤,如图:

• 为什么那个3那里第三,而不是4那里第三。

• 4那里本质就是选择的SYSCLK信号源,3那里就是设置分配器系数,之后的分频系数不变,变仅仅就是信号源。而4就是改变的是信号源。

2.4 配置

2.4.1 步骤一

2.4.2 步骤二

2.4.3 步骤三

2.4.4 步骤四

2.5 代码

复制代码
#include "stm32f10x.h"


void SystemClock_Init();

int main(void)
{
   SystemClock_Init();
    
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
   
   GPIO_InitTypeDef gpio_initStruct = {0};
   
   gpio_initStruct.GPIO_Mode = GPIO_Mode_Out_OD;
   gpio_initStruct.GPIO_Pin = GPIO_Pin_13;
   gpio_initStruct.GPIO_Speed = GPIO_Speed_2MHz;
   
   GPIO_Init(GPIOC,&gpio_initStruct);
    
    
	while(1)
	{
        GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
        
        for(uint32_t i = 0;i < 666666;i++);
        
        GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
        
        for(uint32_t i = 0;i < 666666;i++);
        
	}
}


void SystemClock_Init(){
    
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//开启指令预取
    FLASH_SetLatency(FLASH_Latency_2);//设置访问延迟
    
    //1.选择晶振
    RCC_HSEConfig(RCC_HSE_ON);
    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);//等待HSE就绪
    
    //2.启动锁相环,并选择乘的系数
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
    RCC_PLLCmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL就绪
    
    
    //3.配置HCLK,PCLK1,PCLK2
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
    RCC_PCLK1Config(RCC_HCLK_Div2);
    RCC_PCLK2Config(RCC_HCLK_Div1);
    
    //4.配置SYSCLK的来源
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    while(RCC_GetSYSCLKSource() != 0x08);//判断当前来源是不是来自锁相环
    
  
}

2.6 配置FLASH指令预取

2.6.1 为什么会有指令预取

• 这是因为FLASH是存储代码(程序),而程序的执行是在CPU那里,但是又由于CPU的执行速度比FLASH快太多了,这就需要FLASH把要执行的指令放到一个缓冲区里面,等待CPU的执行,如图:

• 至于要不要访问延迟,就看时钟频率。但是本质还是Flash的速度比CPU慢太多了。

• 还有一点,这两端段代码需要在SYSCLK <= 8MHZ的时候执行。

2.6.2 片上外设开关和复位,如图:

• 注意如果调用复位电路,需要调用两次,一次是ENABLE,一次是DISABLE,相当于按下和松开的步骤。

相关推荐
想放学的刺客2 小时前
单片机嵌入式试题(第27期)设计可移植、可配置的外设驱动框架的关键要点
c语言·stm32·单片机·嵌入式硬件·物联网
天昊吖2 小时前
stc8H启用DMA发送后 卡住【踩坑日志】
单片机
李永奉2 小时前
杰理芯片SDK开发-ENC双麦降噪配置/调试教程
人工智能·单片机·嵌入式硬件·物联网·语音识别
BackCatK Chen2 小时前
第 1 篇:软件视角扫盲|TMC2240 软件核心特性 + 学习路径(附工具清单)
c语言·stm32·单片机·学习·电机驱动·保姆级教程·tmc2240
兆龙电子单片机设计2 小时前
【STM32项目开源】STM32单片机多功能电子秤
stm32·单片机·开源·毕业设计·智能家居
切糕师学AI3 小时前
ARM 架构中的复位(Reset)与复位流程
arm开发·单片机·嵌入式·复位
wotaifuzao3 小时前
STM32多协议网关-FreeRTOS事件驱动架构实战
stm32·嵌入式硬件·can·freertos·uart·modbus·spi
llilian_163 小时前
信号发生器 多通道多功能脉冲信号发生器应用解决方案 多功能脉冲发生器
功能测试·单片机·嵌入式硬件·测试工具
yuanmenghao4 小时前
Classic AUTOSAR深入浅出系列 - 【第十六篇】MCAL:为什么 MCU 换了,上层几乎不用动
单片机·嵌入式硬件·autosar
MickyCode5 小时前
嵌入式开发调试之Traceback
arm开发·stm32·单片机·mcu