【STM32学习】-------- 时钟设置函数详解


stm32上电后默认使用的是内部8MHZ的HSI,速度比较慢,所以上电后要首先进行时钟的配置,让CPU工作在72MHZ的高速频率下。

一,涉及编程寄存器相关位详解

其中涉及到两个重要的时钟寄存器,时钟控制寄存器(RCC_CR),时钟配置寄存器(RCC_CFGR),RCC寄存器基地址为0x40021000

在这里插入图片描述

在这里插入图片描述

二,源代码及解析:

// 寄存器宏定义
// RCC寄存器基地址为0x40021000
#define RCC_BASE	0x40021000			// RCC部分寄存器的基地址
#define RCC_CR		(RCC_BASE + 0x00)	// RCC_CR的地址
#define RCC_CFGR	(RCC_BASE + 0x04)
#define FLASH_ACR	0x40022000

// 用C语言来访问寄存器的宏定义
#define rRCC_CR		(*((volatile unsigned int *)RCC_CR))
#define rRCC_CFGR	(*((volatile unsigned int *)RCC_CFGR))
#define rFLASH_ACR	(*((volatile unsigned int *)FLASH_ACR))

void Set_SysClockTo72M(void)
{                                   //定义三个局部变量在下面的do while 循环中做判断,
	unsigned int rccCrHserdy = 0;   //rccCrHserdy:外部高速时钟HSE是否就绪
	unsigned int rccCrPllrdy = 0;   //rccCrPllrdy:pll是否就绪
	unsigned int rccCfrSwsPll = 0;  //切换系统时钟是否完成
	unsigned int faultTime = 0;

	rRCC_CR = 0x00000083;            //时钟控制寄存器(RCC_CR)的复位值就是0x00000083
	rRCC_CR &= ~(1<<16);	  	    // 关闭HSEON
	rRCC_CR |= (1<<16);			    // 打开HSEON,让HSE工作

	do
	{
		rccCrHserdy = rRCC_CR & (1<<17);	//检测第17位是否为1,即HSERDY:外部高速时钟就绪标志
		faultTime++;                        //检测时间    
	}
	while ((faultTime<0x0FFFFFFF) && (rccCrHserdy==0));  //如果faultTime一直加到0x0FFFFFFF还没就绪就超时
                                      
	if ((rRCC_CR & (1<<17)) != 0)           //如果外部高速时钟就绪标志为1就往下
	{
		rFLASH_ACR |= 0x10;                 //flash部分不用管
		rFLASH_ACR &= (~0x03);
		rFLASH_ACR |= (0x02);

		// 到这里外部高速时钟HSE就ready了,下面再去配PLL并且等待他ready
		rRCC_CFGR &= (~((0x0f<<4) | (0x07<<8) | (0x07<<11)));  //时钟配置寄存器(RCC_CFGR)
		
		// AHB和APB2未分频,APB1被2分频,所以最终:AHB和APB2都是72M,APB1是36M
		rRCC_CFGR |= ((0x0<<4) | (0x04<<8) | (0x0<<11));

		// 选择HSE作为PLL输入并且HSE不分频,所以PLL输入为8M
		rRCC_CFGR &= (~((1<<16) | (1<<17)));   	// 清零bit17和bit16
		rRCC_CFGR |= ((1<<16) | (0<<17));		// 置1 bit16

		// 设置PLL倍频系数为9
		rRCC_CFGR &= (~(0x0f<<18));   			// 清零bit18-21
		rRCC_CFGR |= (0x07<<18);				// 9倍频

		// 打开PLL开关
		rRCC_CR |= (1<<24);

		// do while 循环等待PLL时钟稳定
		faultTime = 0;
		do
		{
			rccCrPllrdy = rRCC_CR & (1<<25);	//检测第25位是否为1
			faultTime++;//检测时间
		}
		while ((faultTime<0x0FFFFFFF) && (rccCrPllrdy==0));
		//while (rccCrPllrdy==0);

		if ((rRCC_CR & (1<<25)) == (1<<25))
		{
		  	// 到这里说明PLL已经稳定了,可以用了,下面就可以切换系统时钟了
			
			// 切换PLL输出为SYSCLK系统时钟
			rRCC_CFGR &= (~(0x03<<0));   
			rRCC_CFGR |= (0x02<<0);	

			faultTime = 0;
			do
			{
				rccCfrSwsPll = rRCC_CFGR & (0x03<<2);	//检测第25位是否为1
				faultTime++;//检测时间
			}
			while ((faultTime<0x0FFFFFFF) && (rccCfrSwsPll!=(0x02<<2)));
			
		   	if ((rRCC_CFGR & (0x03<<2))== (0x02<<2))
			{
				// 到这里我们的时钟整个就设置好了,可以结束了

			}
			else
			{
				// 到这里就说明PLL输出作为SYSCLK不成功
				while (1);
			}

		}
		else
		{
			// 到这里就说明PLL启动时出错了,PLL不能稳定工作
			while (1);
		}

	}
	else
	{
		// HSE配置超时,说明HSE不可用,一般硬件就有问题要去查
		while (1);
	}
}

三,时钟设置的框图步骤分解

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值