目录
STM32第九节(中级篇):RCC(第二节)——讲解系统时钟配置函数SetSysClockTo72
前言
上节课我们讲了理论部分,那么我们这节课讲一下系统时钟配置函数SetSysClockTo72(固件库里面的系统时钟配置函数)。
创作不易,点个关注吧!
STM32第九节(中级篇):RCC(第二节)——讲解系统时钟配置函数SetSysClockTo72
代码内容位置及检索
首先我们拷贝一份之前固件库输出使得LED灯亮起的程序到一个新建的文件夹中,然后打开程序文件。找到其中的启动文件。在我们刚开始还没有stm32f10x.h文件时,我们曾写过一个函数但里面什么都没有,目的是为了骗过编译软件不报错。而这个函数就是 SystemInit 函数,那么他就是配置我们系统时钟的函数。
我们右键点开该函数,发现该函数下有一个 SetSysClock(void)函数,我们打开该函数发现里面就是我们要使用的时钟类型,包括从24MHz到72MHz。 我们点开SYSCLK_FREQ定义,我们可以发现这里配置了宏定义。官方默认为72MHz,所以我们这里默认为72MHz输出。
分析代码
代码展示
紧接着我们就分析系统时钟配置函数SetSysClockTo72的具体代码:
我们先看,#ifdef STM32F10X_CL这句代码写的是互联型的板子,而我们这里使用的是基础板,这里使用了条件编译的宏来区分代码。这里我们发现,我们不需要使用互联型的代码,那么我们可以对于这串代码进行瘦身并翻译注释:
/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#endif
时钟控制使能
我们从函数的开头来一步步分析代码的过程。首先定义函数static void SetSysClockTo72,然后下一行粗略控制总线时钟。 RCC->CR |= ((uint32_t)RCC_CR_HSEON)控制的是CR寄存器的HSEON 16位,该位置为1,16位启动完毕后17位也会置1,主要检测的是17位是否置为1来判断是否打开时钟:
接着就是使用一个do——while循环来实现对于HSE的检测是否置1(如果HSEStatus的值为1,则跳出循环,为0则继续循环)然后判断(RCC->CR & RCC_CR_HSERDY) != RESET是否成立,对其进行赋值:
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
我们继续看正常的流程是什么样子的? 我们下一段代码有什么作用?我们的STM32程序是不是正常是在Flash里面,读取代码是需要等待的。
/* 如果HSE启动成功,程序则继续往下执行 */
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
闪存控制寄存器
在这里所需要操作的就不是RCC的寄存器了,就是与Flash相关的寄存器。我们打开手册(闪存编程参考手册),我们找到位4:预取缓冲区使能,置1。
然后我们观察手册可知,时延我们一般选010状态下的72MHz,完成我们的时延操作。
配置AHP,APB1,APB2的总线时钟
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
这三行代码配置的是时钟配置寄存器中的4~13位 ,我们结合上节课的时钟树总图,我们就配置AHB为系统时钟72MHz,APB2为72MHz,APB1为36MHz:
配置锁相环时钟
配置好后,锁相环也有一个标志位 PLLRDY 25位。判断前一位是否为1。
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
/* 使能 PLL */
RCC->CR |= RCC_CR_PLLON;
/* 等待准备 */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* 选择pllclk为系统时钟 */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* 等待切换 */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
超频操作
我们只需要配置锁相环RCC_CFGR_PLLMULL9为RCC_CFGR_PLLMULL16,这样我们就会得到一个超频时钟(128最高频率)。
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
小结
到这里我们就写好了也分析了所有的代码,那么我们下节课学习使用HSE配置系统时钟并使用MCO输出监控系统时钟。
标签:SetSysClockTo72,HSE,CFGR,第九节,STM32,CR,时钟,uint32,RCC From: https://blog.csdn.net/2301_79641086/article/details/136768055