首页 > 其他分享 >STM32第九节(中级篇):RCC(第二节)——讲解系统时钟配置函数SetSysClockTo72

STM32第九节(中级篇):RCC(第二节)——讲解系统时钟配置函数SetSysClockTo72

时间:2024-03-16 21:00:11浏览次数:16  
标签:SetSysClockTo72 HSE CFGR 第九节 STM32 CR 时钟 uint32 RCC

目录

前言

STM32第九节(中级篇):RCC(第二节)——讲解系统时钟配置函数SetSysClockTo72

代码内容位置及检索

分析代码 

代码展示

时钟控制使能

闪存控制寄存器

配置AHP,APB1,APB2的总线时钟

配置锁相环时钟 

超频操作

小结


前言

        上节课我们讲了理论部分,那么我们这节课讲一下系统时钟配置函数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

相关文章

  • 【课设】/【毕设】ESP32上传温湿度至新版Onenet云平台并由新版Onenet云平台下发命令控
    一、uniapp设计  1、APP生成token秘钥:  1.1.下载HBuider软件:     直接搜索HBuider,进入官网下载软件:  2.新建项目-选择默认模版3.打开index.vue4.点击运行至内置浏览器;2.1获取Onenet云平台API接口 2.1.1进入Onenet云平台点击服务与支持-文档......
  • STM32F105双路隔离型CAN总线转4G控制板 - 把CAN数据发送到TCP服务器,实现通过TCP透传
    <p><iframename="ifd"src="https://mnifdv.cn/resource/cnblogs/product/STM32F105_2CAN/index.html"frameborder="0"scrolling="auto"width="100%"height="1500"></iframe></p>......
  • STM32CubeMX没有生成Keil工程问题
    1. Project中选择IDE为MDK-ARM 2.你可能没有联网,所以在GENERATECODE时没有弹窗提示需要下载stm32cube_fw_XXX.zip软件包,根据提示登录(没有账号就注册一个)后按提示下载对应软件包即可,下图为下载中的stm32F4xx软件包。  安装后,重新GENERATECODE,即可生成MDK-ARM目录......
  • STM32入门(三):配置STM32项目环境
    配置STM32项目环境1. 选择合适的开发板首先我们需要选择一块合适简单的开发板,学习的板子选择stm32—f103系列板子。这一系列器件具有以下优势:性能:STM32F103F系列提供了一个强大的32位ARMCortex-M3内核,具有足够的处理能力来处理大多数嵌入式应用。外设丰富:这些芯片提供......
  • stm32-编码器测速
    一、编码器简介 编码电机 旋转编码器 A,B相分别接通道一和二的引脚,VCC,GND接单片机VCC,GND二、正交编码器工作原理1.计数方式 2.框图分析 由图可知,只有CH1和CH2有编码器接口,且编码器只用到了输入捕获结构体的输入滤波和边沿检测器,则其余的结构体成员都不......
  • STM32G431RBT6LED灯02
    cubeMX根据引脚 选取这些引脚,设置为GPIO_Output除复用引脚之外的需要设置输出为HighLED控制语句<led.c>#include<led.c>voidLED_Disp(uchardsLED){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);HAL_G......
  • STM32标准库低功耗
    STM32标准库低功耗1.睡眠模式1.1.进入以及退出方法睡眠模式较为简单,仅需要简单调用函数即可,且函数定义处于内核层,不需要引用多余的头文件。睡眠模式:仅内核停止,所有外设仍旧运行。调用"__WFI()"函数,退出方式为任意中断。调用"__WFE()"函数,退出方式为唤醒事件。2.停......
  • stm32F103 移植Free RTOS
    #stm32F103移植FreeRTOS1.下载FreeRTOS源码[官网下载](http://www.freertos.org)[代码托管网站下载](https://sourceforge.net/projects/freertos/files/FreeRTOS)2.FreeRTOS文件介绍进入Source文件夹进入portable文件夹进入RVDS3.FreeRTOS移......
  • stm32 foc 库输出波形
    前言本文为学习st的FOC库笔记,记录FOC库实际输出的PWM波形之间的区别。关键词:SPWM,SVPWM,Overmodulation,DiscontinuousPWM标准波形输出对应Modulationflags为None可以看到,输出波形为马鞍波,即生成波形为SVPWM。对比逆克拉克变换生成的SPWM,生成的波形两者幅值相同。......
  • STM32模拟IIC读取ACD10红外二氧化碳数据
    引脚介绍ACD10通过IIC来通信我们使用下图右边四个引脚就可以了,系统默认模式为IIC通信方式,他也支持USART串口通信不过需要配置pin5引脚(低电平)。模拟IIC通信配置比较简单,在单片机上面随便找两个引脚就可以。用来配置SDA数据与SCL时钟引脚。读取数据命令官方给我们命令行列......