stm32—RCC使用HSE/HSI配置时钟

RCC :reset clock control 复位和时钟控制器

这里只需要理解时钟部分。

RCC主要作用

设置系统时钟 SYSCLK、设置 AHB 分频因子(决定 HCLK 等于多少)、设置 APB2 分频因子(决定 PCLK2 等于多少)、设置 APB1 分频因子(决定 PCLK1 等于多少)、设置各个外设的分频因子;控制 AHB、APB2 和 APB1 这三条总线时钟的开启、控制每个外设的时钟的开启。对于 SYSCLK、HCLK、PCLK2、PCLK1 这四个时钟的配置一般是:PCLK2 = HCLK = SYSCLK=PLLCLK = 72M,PCLK1=HCLK/2 = 36M。
![在这里RCC时钟树插入图片描述](https://img-blog.csdnimg.cn/4bRCCd3b5c91735457abd78ed39bbdb87be.png

系统时钟

根据时钟树的黄色部分来分析系统时钟的设置路径。

1.HSE:高速外部时钟信号
由有源晶振和无源晶振提供。有源晶振时,时钟从OSC_IN引脚进入,OSC_OUT引脚悬空,当选用无源晶振时,时钟从OSC_IN和OSC_OUT进入,并且要配谐振电容。
HSE 最常使用的就是 8M 的无源晶振。当确定 PLL 时钟来源的时候,HSE 可以不分频或者 2 分频,这个由时钟配置寄存器 CFGR 的位 17:PLLXTPRE 设置,我们设置为 HSE 不分频。
在这里插入图片描述

2.PLL时钟源
一个来自HSE,另一个来自HSI/2,由时钟配置寄存器CFGR 的位 16:PLLSRC 设置。HSI是内部高速的时钟信号,频率为8M(收环境和温度影响,频率会发生漂移,不用作PLL时钟来源)。

3.PLL时钟PLLCLK
设置PLLMUL倍率因子,可对PLL的时钟来源进行倍频,倍频因子【2,3,4,5,6,7,8,9,10,11,12,13,14,15,16】,具体倍率因子为多少,由时钟配置寄存器 CFGR 的位21-18:PLLMUL[3:0] 设置。设置为 9 倍频,设置 PLL 的时钟来源为HSE=8M,所以经过 PLL 倍频之后的 PLL 时钟:PLLCLK = 8M *9 = 72M。72M 是 ST 官方推荐的稳定运行时钟,如果你想超频的话,增大倍频因子即可。

4.系统时钟SYSCLK
系统时钟来源可以是:HSI、PLLCLK、HSE。的时钟配置寄存器 CFGR 的位 1-0:SW[1:0] 设置。我们这里设置系统时钟:SYSCLK = PLLCLK = 72M。

5.AHB总线时钟HCLK
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 APB 总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器 CFGR 的位 7-4 :HPRE[3:0]设置。设置为 1 分频,即 HCLK=SYSCLK=72M。

6.APB2 总线时钟 PCLK2
APB2 总线时钟 PCLK2 由 HCLK 经过高速 APB2 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 CFGR 的位 13-11:PPRE2[2:0] 决定。HCLK2 属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、USART1、SPI1 等。设置为 1 分频,即 PCLK2 = HCLK = 72M。

7.APB1 总线时钟 PCLK1
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,分频因子可以是:[1,2,4,8,16],具体的由时钟配置寄存器 CFGR 的位 10-8:PRRE1[2:0] 决定。

采用HSE作为外部时钟源时,编写RCC时钟的驱动文件,bsp_clkconfig.h 和 bsp_clkconfig.c。
编程要点对应着时钟树图中的序号。
1、开启 HSE/HSI ,并等待 HSE/HSI 稳定
2、设置 AHB、APB2、APB1 的预分频因子
3、设置 PLL 的时钟来源,和 PLL 的倍频因子,设置各种频率主要就是在这里设置
4、开启 PLL,并等待 PLL 稳定
5、把 PLLCK 切换为系统时钟 SYSCLK
6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟

bsp_clkconfig.c

#include "bsp_rccclkconfig.h"

void HSE_SetSysClk(uint32_t RCC_PLLMul_x)   //创建固件库函数,使用高速外部时钟HSE来设置系统时钟
{
	   ErrorStatus HSEStatus;
	  //把RCC寄存器复位成复位值 
	   RCC_DeInit();
	  //使能HSE
	  RCC_HSEConfig(RCC_HSE_ON);    
	  /* 等待HSE就绪并做超时处理 */
	  HSEStatus = RCC_WaitForHSEStartUp();
	  if(HSEStatus == SUCCESS)
		{
		   //使能预取指,开启缓存区
			FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
			
			//缓存区2个延时周期
			FLASH_SetLatency(FLASH_Latency_2);
			
			//设置  HCLK=72M PCLK1=36M PCLK2=72M  倍率因子
			RCC_HCLKConfig(RCC_SYSCLK_Div1);
            RCC_PCLK1Config(RCC_HCLK_Div2);
            RCC_PCLK2Config(RCC_HCLK_Div1);
			
			//锁相环配置: PLLCLK = HSE * RCC_PLLMul_x
			RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
			
			//使能PLL
            RCC_PLLCmd(ENABLE);
			
			//等待PLL稳定
			while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
			
			//选择系统时钟
			RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
			
			//判断PLL是否为时钟源
            while(RCC_GetSYSCLKSource() != 0x08);
		}
		else
		{
			 /* 如果HSE启动失败,用户可以在这里添加处理错误的代码 */
		}
}

MCO输出

MCO微控制器时钟输出,在 STM32 F1 系列中由PA8 复用所得,主要作用是可以对外提供时钟,相当于一个有源晶振。MCO 的时钟来源可以是:
PLLCLK/2、HSI、HSE、SYSCLK,具体选哪个由时钟配置寄存器 CFGR 的位 26-24:MCO[2:0] 决定。

bsp_clkconfig.c

void MCO_GPIO_Config()   //MCO主时钟输出函数
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //启用AP2外部时钟
	//配置GPIO_InitTypeDef初始化类型
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;   //GPIOA8引脚
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOA, &GPIO_InitStruct);  //将配置好的结构体成员配置到相应的寄存器里 
}

bsp_clkconfig.h

#ifndef __BSP_RCCCLKCONFIG_H_
#define __BSP_RCCCLKCONFIG_H_

#include "stm32f10x.h"
void HSE_SetSysClk(uint32_t RCC_PLLMul_x);
void MCO_GPIO_Config();

#endif

main()

#include "stm32f10x.h"    //相当于51单片中的#include <reg51.h>
#include "bsp_led.h"
#include "bsp_rccclkconfig.h"

void delay(unsigned int i)   //延时函数
{
	while(i--);
}

int main(void)
{
    //来到这里的时候,系统时钟已经被配置好72M.
    HSE_SetSysClk(RCC_PLLMul_9);   //超时频率配置
	
	MCO_GPIO_Config();    //MCO主时钟输出函数,PA8
	RCC_MCOConfig(RCC_MCO_SYSCLK);   //选择SYSCLK时钟源输出
	LED_GPIO_Config(); 

	while(1)
	{  
		  //GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
		  LED_G(OFF);
		  delay(0xFFFFF);
	    //GPIO_ResetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
		  LED_G(ON);
		  delay(0xFFFFF);
	}
}

初学者stm32,有何错误,欢迎指出改正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值