STM32时钟体系、SetSysClock、PLL、时钟源

news/2024/9/12 21:15:31/文章来源:https://www.cnblogs.com/zqingyang/p/18304310

V1.0 2024年7月12日


目录
  • 一、时钟体系
    • 1、参考手册
    • 2、时钟源3种
    • 3、时钟树
    • 4. 时钟详解
      • HSE时钟
      • HSI时钟
      • 锁相环时钟
      • 系统时钟
      • HCLK时钟
      • PCLK1时钟
      • PCLK2时钟
      • RTC时钟
      • 独立看门狗时钟:
      • I2S时钟:
      • 以太网PHY时钟:
      • USB PHY时钟:
      • MCO时钟输出
    • 系统时钟配置函数SetSysClock()
    • 系统时钟配置流程
  • 二、PLL
    • 2.1 概述
    • 2.2 基本组成
    • 2.3 类比说明
    • 2.3 相位差[拓展]
  • 三、SystemInit系统初始化函数
    • 1.其实第一个执行的文件是汇编文件
    • 2.初始化Flash接口,更新PLL系统频率
    • 3.调用SetSysClock函数设置PLL时钟,然后进行分频
    • 4.阅读system_stm32f4xx.c文件的头部注释
  • 四、时钟源
  • 参考文章


一、时钟体系

给单片机提供一个时钟信号(一个非常稳定的频率信号),使单片机各内部组件同步工作,并且在和外部设备通信时是也能达到同步。

动态调整运行频率,就可以控制性能与功耗!

STM32 的时钟系统由外部晶振、PLL(锁相环)和内部 RC 振荡器组成。时钟系统主要提供了处理器时钟,以及可选的外设时钟和RTC模块时钟。

其作用包括:

  • 为处理器提供准确的时钟信号,保证处理器、总线和外设的正确工作。
  • 通过 PLL 的倍频功能,产生多种频率的时钟信号,满足不同外设的时钟需求。
  • 通过时钟系统提供的时钟分频器、预分频器等功能,进一步调整时钟频率,以适应不同的应用场景。

时钟系统在 STM32 的系统中扮演着关键的角色,它的稳定性和精度对整个系统的性能影响很大。

1、参考手册

STM32F4xx 中文参考手册.pdf 第 106 页

2、时钟源3种

a.可以使用三种不同的时钟源来驱动系统时钟 (SYSCLK),CPU 运行的频率为 168MHz:

HSI 振荡器时钟(16MHz),也就是高速内部时钟,一般来说很少用,因为精度没有外部高速时钟那么高。

HSE 振荡器时钟,也就是高速外部时钟,GECM4 开发板 8MHz。

主 PLL (PLL) 时钟

b.器件具有以下两个次级时钟源:

32 kHz 低速内部 RC (LSI RC),该 RC 用于驱动独立看门狗,也可选择提供给 RTC 用于停机/待机模式下的自动唤醒。

32.768 kHz 低速外部晶振(LSE 晶振),用于驱动 RTC 时钟 (RTCCLK)对于每个时钟源来说,在未使用时都可单独打开或者关闭,以降低功耗。

3、时钟树

时钟树就是关注时钟源和时钟的流向,嵌入式系统中的模块和外设工作都以时钟为基准。有了时钟树,就有了时钟域。嵌入式中除了内核,还有各个单元,每个单元工作在不同的时钟频率下,给每个单元提供不同的时钟。

实际应用中根据需要配置外设的时钟控制开关,选择需要的时钟频率,并可关闭不用外设时钟。

image

stm32对每个外设的时钟都设置了开关,让用户可以精确地控制,关闭不需要的设备,达到节省供电的目的。如果不用的就完全关闭,尽可能降低芯片功耗,以下以GPIO作为举例

  1. 降低功耗:STM32设计允许用户精确控制各个外设的电源管理,包括时钟的开关。当不使用某个外设时,通过关闭其时钟可以显著减少功耗。因此,GPIO的时钟默认是关闭的,以节省电力。
  2. 激活功能:使能GPIO的时钟是激活其功能的第一步。没有时钟,GPIO的寄存器无法读写,从而无法配置GPIO的工作模式(如输入、输出、上拉、下拉等)或读取输入状态。
  3. 同步操作硬件时钟为GPIO提供了必要的时序和同步信号,确保GPIO的操作与系统其他部分协调一致。这对于维持数据的稳定传输和处理非常重要。
  4. 支持高级功能:对于某些高级功能,如复用功能(GPIO复用为其他外设功能)、中断功能等,可能还需要额外使能AFIO(Alternate Function Input Output)的时钟。这是因为这些功能涉及到更复杂的内部信号路由和管理。

实际上,在这里面还涉及到一个时钟门控技术,而这又涉及到同步电路,我们都知道(默认你们都知道)在同步电路中总是有一个时钟控制。这里就不赘述了,回去翻翻一本叫《数字电子技术基础》的书,可以找到答案。

4. 时钟详解

查看<<中文参考手册 第六章, RCC寄存器>>

HSE时钟

HSE:High Speed External Clock signal,即高速的外部时钟。

来源:有源晶振(1-50M)、无源晶振(4-26M)

控制:RCC_CR 时钟控制寄存器的位16:HSEON控制

HSI时钟

HSI:Low Speed Internal Clock signal,即高速的内部时钟。

来源:芯片内部,大小为16M,当HSE故障时,系统时钟会自动切换到HSI,直到HSE启动成功。

控制: RCC_CR 时钟控制寄存器的位0:HSION控制

锁相环时钟

锁相环时钟:PLLCLK

来源:HSI、HSE。由PLLSRC位配置。(0HSI 1HSE)

HSE或者HSI先经过一个分频因子M进行分频,然后再经过一个倍频因子N,然后再经过一个分频因子P,最后成为锁相环时钟PLLCLK = (HSE/M) * N / P = 25/25 * 336 / 2 = 168M

控制: RCC_PLLCFGR :RCC PLL 配置寄存器

PLL48CK:USB_FS(USB全速接口)、RANG(随机发发生器)、SDIO提供时钟

image

HSI精度不高.

PLLM 分频因子

PLLN 倍频

PLLP分配

系统时钟

缩写:SYSCLK,最高为168M。

来源:HSI、HSE,PLLCLK。

控制: RCC_CFGR 时钟配置寄存器的SW位( 一般配置为10 选择PLL作为系统时钟)

image

HCLK时钟

HCLK:AHB高速总线时钟,最高为168M。为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟(SysTick, 一般会8分频)、为内核提供时钟(FCLK 自由运行时钟)。

AHB为advanced high-performance bus。

来源:系统时钟分频得到。

控制: RCC_CFGR 时钟配置寄存器的HPRE位

PCLK1时钟

PCLK1:APB1低速总线时钟,最高为42M,为APB1总线的外设提供时钟。

来源:HCLK分频得到,通常配置为4分频

控制: RCC_CFGR 时钟配置寄存器的PPRE1位

PCLK2时钟

PCLK1:APB高速总线时钟,最高为84M,为APB2总线的外设提供时钟。

来源:HCLK分频得到,通常配置为2分频。

控制: RCC_CFGR 时钟配置寄存器的PPRE2位

RTC时钟

RTC:为芯片内部的RTC提供时钟。

来源:HSE_RTC(HSE分频得到)、LSE(外部32.768KHZ的晶体提供)、LSI(32KHZ)。

控制: RCC备份域控制寄存器RCC_BDCR:RTCSEL位控制

独立看门狗时钟:

IWDGCLK,由LSI提供

image

I2S时钟:

由外部的引脚I2S_CKIN或者PLLI2SCLK提供。

以太网PHY时钟:

407没有集成PHY,只能外接PHY芯片,比如LAN8720,那PHY时钟就由外部的PHY芯片提供,大小为50M。

USB PHY时钟:

407的USB没有集成PHY,要想实现USB高速传输,只能外接PHY芯片,比如USB33000。那USB PHY时钟就由外部的PHY芯片提供。

MCO时钟输出

MCO:把控制器的时钟通过外部的引脚输出,可以外外部的设备提供时钟。MCO1为PA8,MCO2为PC9。

控制: RCC_CFGR 时钟配置寄存器的MCOX的PREx位

image

系统时钟配置函数SetSysClock()

打开汇编文件

image

找到时钟初始化

image

image

设置系统时钟

将下面这一段拷贝出, 进行裁剪:

/*** @brief  Configures the System clock source, PLL Multiplier and Divider factors, *         AHB/APBx prescalers and Flash settings* @Note   This function should be called only once the RCC clock configuration  *         is reset to the default reset state (done in SystemInit() function).   * @param  None* @retval None*/
static void SetSysClock(void)
{
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* 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){/* Select regulator voltage output Scale 1 mode */RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* HCLK = SYSCLK / 1*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1;#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)      /* PCLK2 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */#if defined (STM32F401xx)/* PCLK2 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
#endif /* STM32F401xx *//* Configure the main PLL */RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);/* Enable the main PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till the main PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}#if defined (STM32F427_437xx) || defined (STM32F429_439xx)/* Enable the Over-drive to extend the clock frequency to 180 Mhz */PWR->CR |= PWR_CR_ODEN;while((PWR->CSR & PWR_CSR_ODRDY) == 0){}PWR->CR |= PWR_CR_ODSWEN;while((PWR->CSR & PWR_CSR_ODSWRDY) == 0){}      /* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F427_437x || STM32F429_439xx  */#if defined (STM32F40_41xxx)     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F40_41xxx  */#if defined (STM32F401xx)/* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
#endif /* STM32F401xx *//* Select the main PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= RCC_CFGR_SW_PLL;/* Wait till the main PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);{}}else{ /* If HSE fails to start-up, the application will have wrong clockconfiguration. User can add here some code to deal with this error */}
#elif defined (STM32F411xE)
#if defined (USE_HSE_BYPASS) 
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* Enable HSE and HSE BYPASS */RCC->CR |= ((uint32_t)RCC_CR_HSEON | RCC_CR_HSEBYP);/* 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){/* Select regulator voltage output Scale 1 mode */RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* HCLK = SYSCLK / 1*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;/* Configure the main PLL */RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);/* Enable the main PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till the main PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;/* Select the main PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= RCC_CFGR_SW_PLL;/* Wait till the main PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);{}}else{ /* If HSE fails to start-up, the application will have wrong clockconfiguration. User can add here some code to deal with this error */}
#else /* HSI will be used as PLL clock source *//* Select regulator voltage output Scale 1 mode */RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* HCLK = SYSCLK / 1*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;/* Configure the main PLL */RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (PLL_Q << 24); /* Enable the main PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till the main PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;/* Select the main PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= RCC_CFGR_SW_PLL;/* Wait till the main PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);{}
#endif /* USE_HSE_BYPASS */  
#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */  
}

启动外部晶振, HSE高速的外部时钟

image

image


配置预分频器

RCC_CFGR

image

    /* HCLK = SYSCLK / 1 AHB高速总线的分配因子 1分频*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK / 2 APB2总线的分频因子 2分频*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;    /* PCLK1 = HCLK / 4 APB1总线的分频因子 4分频*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

image-20240711210830924

image

注释掉系统默认的系统时钟汇编代码, 系统默认使用HSI 16 MHz, 我们可以自定义的配置系统时钟函数

image
image

#include "bsp_clkconfig.h"void User_SetSysClock(void)
{/******************************************************************************//*            PLL (clocked by HSE) used as System clock source                *//******************************************************************************/__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* 复位RCC的所有寄存器 */RCC_DeInit();/* Enable HSE *//* 使能HSE 《中文参考手册 6.3.1 RCC时钟控制寄存器》 ((uint32_t)0x00010000) */RCC->CR |= ((uint32_t)RCC_CR_HSEON);/* Wait till HSE is ready and if Time out is reached exit *//* 等待HSE启动稳定,如果超时则退出  由RCC_CR HSERDY控制*/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;}/* HSE 启动成功 */if (HSEStatus == (uint32_t)0x01){/* Select regulator voltage output Scale 1 mode *//* 选择电压调节器的模式为1  和电源控制器PWR有关 PWR_CR寄存器VOS位, 实现功耗平衡*/RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* HCLK = SYSCLK / 1 AHB高速总线的分频因子*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK / 2 APB2总线的分频因子*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;/* PCLK1 = HCLK / 4 APB1总线的分频因子*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;/*** Configure the main PLL* 配置主PLL* PLL_M分频因子应该和外部时钟HSE一致, 分频后为1* 因此N为336 P为2(/2得到168M), Q是7(得到48Mhz)* RCC_PLLCFGR_PLLSRC_HSE 选择锁相环时钟来源, 这里选择HSE 8M** 可以设置N最大为432 《中文参考手册 6.3.2 》, 可超频到216M, 原168M*///    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |//                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);RCC->PLLCFGR = 25 | (336 << 6) | (((2 >> 1) - 1) << 16) |(RCC_PLLCFGR_PLLSRC_HSE) | (7 << 24);/* Enable the main PLL *//* 使能主PLL  因为使能后无法修改! */RCC->CR |= RCC_CR_PLLON;/* Wait till the main PLL is ready *//* 等待主PLL稳定 */while ((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Configure Flash prefetch, Instruction cache, Data cache and wait state *//* 配置FLASH预取指(将指令提前准备好),指令缓存,数据缓存,等待周期(速度越快等待周期越长, 见中文参考手册3.8.1)* 配置flash外设的acr寄存器*/FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;/* Select the main PLL as system clock source *//* 选择主PLL时钟作为系统时钟 */RCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_SW));RCC->CFGR |= RCC_CFGR_SW_PLL;/* Wait till the main PLL is used as system clock source *//* 确保主PLL时钟选为系统时钟, 若设置成功, 系统会硬件置1 《中文参考手册 6.3.3 》*/while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);{}}else{ /* If HSE fails to start-up, the application will have wrong clockconfiguration. User can add here some code to deal with this error *//* HSE 启动失败,在这里添加启动失败的处理代码 */}
}

若使用系统自带的系统配置文件, 需要做HSE修改, 默认是25M

image

系统时钟配置流程

二、PLL

2.1 概述

PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时钟信号,使高频器件正常工作,如内存的存取资料等。

PLL基于振荡器中的反馈技术,许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步。

一般的晶振由于工艺与成本原因,做不到很高的频率,而在需要高频应用时,由相应的器件VCO,实现转成高频,但并不稳定,故利用锁相环路就可以实现稳定且高频的时钟信号。

2.2 基本组成

锁相环路是一种反馈控制电路,简称锁相环(PLL,Phase-Locked Loop)。锁相环的特点是:利用外部输入的参考信号控制环路内部振荡信号的频率和相位。因锁相环可以实现输出信号频率对输入信号频率的自动跟踪,所以锁相环通常用于闭环跟踪电路。

锁相环在工作的过程中,当输出信号的频率与输入信号的频率相等时,输出电压与输入电压保持固定的相位差值,即输出电压与输入电压的相位被锁住,这就是锁相环名称的由来。锁相环通常由鉴相器(PD,Phase Detector)、环路滤波器(LF,Loop Filter)和压控振荡器(VCO,Voltage Controlled Oscillator)三部分组成。

锁相环的工作原理是检测输入信号和输出信号的相位差,并将检测出的相位差信号通过鉴相器转换成电压信号输出,经低通滤波器滤波后形成压控振荡器的控制电压,对振荡器输出信号的频率实施控制,再通过反馈通路把振荡器输出信号的频率、相位反馈到鉴相器。

锁相环在工作过程中,当输出信号的频率成比例地反映输入信号的频率时,输出电压与输入电压保持固定的相位差值,这样输出电压与输入电压的相位就被锁住了。

image

2.3 类比说明

我们刚开始学车的时候,在道路上开车,眼睛就好像一个鉴相器,负责发现车行驶的方向(反馈)和前方的路(输入)是否有差别,把差别输入大脑进行判断,然后指挥双手旋转方向盘,旋转方向盘的动作转换成车的行驶方向,如下图所示。

image

我们通过这么一个闭环过程不断地调节方向盘,保证车行驶在正道上。

2.3 相位差[拓展]

两个频率相同的交流电相位的差叫做相位差,或者叫做相差,又称“相角差”、“相差”、“周相差”或“位相差”。两个作周期变化的物理量的相之间的差值。它为正值时称前者超前于后者,为负值时则滞后于后者。它为零或π的偶数倍时,两物理量同相;为π的奇数倍时则称反相

这两个频率相同的交流电,可以是两个交流电流,可以是两个交流电压,可以是两个交流电动势,也可以是这三种量中的任何两个。两个同频率正弦量的相位差就等于初相之差。是一个不随时间变化的常数。也可以是一个元件上的电流与电压的相位变化。任意一个正弦量y = Asin(wt+ j0)的相位为(wt+ j0),两个同频率正弦量的相位差(与时间t无关)。设第一个正弦量的初相为 j01,第二个正弦量的初相为 j02,则这两个正弦量的相位差为j12 = j01 - j02。

image

2.4 PLL配置参数

image

不同的芯片,倍频(频率翻倍)公式是不一样的,需要查询芯片手册!

三、SystemInit系统初始化函数

1.其实第一个执行的文件是汇编文件

  • 栈的初始化,提供函数调用的时候进行现场保护和现场恢复
  • 堆的初始化,为申请内存提供空间,调用malloc
  • 执行Reset_Handler,意思说上电复位后执行的动作
  • 执行SystemInit函数
  • 跳转到main函数

2.初始化Flash接口,更新PLL系统频率

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the
  *         SystemFrequency variable.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{................/* Configure the System clock source, PLL Multiplier and Divider factors,
     AHB/APBx prescalers and Flash settings ----------------------------------*/SetSysClock();................}

3.调用SetSysClock函数设置PLL时钟,然后进行分频

/**
  * @brief  Configures the System clock source, PLL Multiplier and Divider factors,
  *         AHB/APBx prescalers and Flash settings
  * @Note   This function should be called only once the RCC clock configuration  
  *         is reset to the default reset state (done in SystemInit() function).   
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{...................../* Configure the main PLL */RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);.....................
}

system_stm32f4xx.c文件有以下倍频(PLL_N)与分频(PLL_M、PLL_P)因子:

/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8     //(记得修改为8)
/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7#if defined (STM32F40_41xxx)
#define PLL_N      336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2
#endif /* STM32F40_41xxx */

由于官方的代码是使用外部高速晶振25MHz,GEC-M4开发板是使用外部高速晶振8MHz,所以PLL的倍频因子要进行修改,只修改PLL_M为8

4.阅读system_stm32f4xx.c文件的头部注释

 *=============================================================================*=============================================================================*                    Supported STM32F40xxx/41xxx devices*-----------------------------------------------------------------------------*        System Clock source                    | PLL (HSE)*-----------------------------------------------------------------------------*        SYSCLK(Hz)                             | 168000000*-----------------------------------------------------------------------------*        HCLK(Hz)                               | 168000000*-----------------------------------------------------------------------------*        AHB Prescaler                          | 1*-----------------------------------------------------------------------------*        APB1 Prescaler                         | 4*-----------------------------------------------------------------------------*        APB2 Prescaler                         | 2*-----------------------------------------------------------------------------*        HSE Frequency(Hz)                      | 25000000   粤嵌开发板外部晶振是8MHz,我们要将25MHz修改为8MHz*-----------------------------------------------------------------------------*        PLL_M                                  | 25*-----------------------------------------------------------------------------*        PLL_N                                  | 336*-----------------------------------------------------------------------------*        PLL_P                                  | 2*-----------------------------------------------------------------------------*        PLL_Q                                  | 7*-----------------------------------------------------------------------------*        PLLI2S_N                               | NA*-----------------------------------------------------------------------------*        PLLI2S_R                               | NA*-----------------------------------------------------------------------------*        I2S input clock                        | NA*-----------------------------------------------------------------------------*        VDD(V)                                 | 3.3*-----------------------------------------------------------------------------*        Main regulator output voltage          | Scale1 mode*-----------------------------------------------------------------------------*        Flash Latency(WS)                      | 5*-----------------------------------------------------------------------------*        Prefetch Buffer                        | ON*-----------------------------------------------------------------------------*        Instruction cache                      | ON*-----------------------------------------------------------------------------*        Data cache                             | ON*-----------------------------------------------------------------------------*        Require 48MHz for USB OTG FS,          | Disabled*        SDIO and RNG clock                     |*-----------------------------------------------------------------------------*=============================================================================

去掉stm32f4xx.h的只读属性

image

接着修改stm32f4xx.h以下内容,行127将外部晶振频率值修改为8MHz。

#if !defined  (HSE_VALUE)
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

最后按照PLL的运算公式,最终得到输出频率为168MHz。

image

#注意事项

1.在《STM32F4xx中文参考手册》 P117页,PLL_M、PLL_N、PLL_P,这三个参数都有一定的范围限制,详细如下:

2≤ PLL_M ≤63
192≤ PLL_N ≤432
PLL_P:2、4、6、8

四、时钟源

在特殊的应用场景,为了达到最高的能效比,没有必要使用到PLL,可将HSE、HSI作为系统时钟源。例如,在智能手表锁屏的情况下,如果使用PLL配置过后输出的频率会造成过多的功耗,降低自身的续航能力;同时要维持计步与测量心率功能。因此,PLL在锁屏下的应用场景并不合适,在保证功能实现的前提下,尽可能降低功耗,可以切换频率更低的时钟源提供给系统时钟。

image

1.选择PLL作为系统时钟源

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;或RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);      	

2.选择HSI作为系统时钟源

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSI;或RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); 	

3.选择HSE作为系统时钟源

```c	              
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSE;或RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); 	
```

五、应用场景

调节 CPU 的运行频率,来控制系统的性能与功耗。比较典型的例子就是说手机/笔记本电脑都有高性能模式、平衡模式、低性能模式。

image

image

六、寄存器边界地址

详见《STM32F4xx中文参考手册》的P52 ~ P54页,部分展示如下:

image

参考文章

  • 温子祺笔记
  • 野火STM32库开发实战指南

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/744383.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YApi可视化接口管理平台部署

使用我们提供的 yapi-cli 工具,部署 YApi 平台是非常容易的。执行 yapi server 启动可视化部署程序,输入相应的配置和点击开始部署,就能完成整个网站的部署。部署完成之后,可按照提示信息,执行 node/{网站路径/server/app.js} 启动服务器。在浏览器打开指定url, 点击登录输…

八大作业管理流程

安全影响力的小编非常喜欢王老师的风格,抄了他的创意,把八大高危作业做了一个“一图看懂”系列。

玄机-第一章 应急响应-webshell查杀

作者是个垃圾,第一次玩玄机太紧张了,不知道flag是啥样找了半天,第二次开靶机多次尝试才知道格式。争取下次一次过。 靶机账号密码 root xjwebshell 1.黑客webshell里面的flag flag{xxxxx-xxxx-xxxx-xxxx-xxxx} 2.黑客使用的什么工具的shell github地址的md5 flag{md5} 3.黑客…

WordPress标签如何实现批量自定义链接

网站外链和内链都是非常重要的一项 SEO 工作,并且一个网站的反链建设也并非一朝一夕就能够做好,而是日积月累的增加才会更有优化效果,且不论是否为 nofollow 或者 dofollow 属性,对于很 SEOer 来说可能觉得建设 Do Follow 的反链更有用,但是我们不妨换个 SEO 思维方式,一…

Modbus转Ethernet IP网关模块与汇川PLC通讯在网关配置软件中的配置

通过Modbus转Ethernet/IP网关模块XD-MDEP100,实现汇川PLC与多种品牌Modbus设备的无缝通信,提高系统效率和稳定性。配置软件GWModbusBuilder完成网关与PLC通讯设置,支持EtherNet/IP协议,实现数据快速传输和实时监控。通过Modbus转Ethernet/IP网关模块(XD-MDEP100),可以实…

JavaScript系列:JS实现复制粘贴文字以及图片

目录一. 基于 Clipboard API 复制文字(推荐)基本概念主要方法使用限制实际应用示例二、基于 document.execCommand(copy)缺陷实际应用示例说明三、复制图片功能四、封装 一. 基于 Clipboard API 复制文字(推荐) 基本概念 Clipboard API 是一组用于在浏览器中操作剪贴板的 J…

数据分享|R语言决策树和随机森林分类电信公司用户流失churn数据和参数调优、ROC曲线可视化|附代码数据

原文链接:http://tecdat.cn/?p=26868 最近我们被客户要求撰写关于电信公司用户流失的研究报告,包括一些图形和统计输出。 在本教程中,我们将学习覆盖决策树和随机森林。这些是可用于分类或回归的监督学习算法 下面的代码将加载本教程所需的包和数据集。 library(tidyverse…

vue项目中使用axios(自用)

————流程参考在vscode的集成终端中输入npm install axios回车安装重启项目(重新运行) 在script中导入axiosimport axios from axios; 在default中的data同级mounted()中按如下获取数据mounted(){// 发送异步请求,获取数据// 输入thenc可用自动生成回调axios.get(数据地…

onnxruntime无法使用GPU加速 加速失败 解决方法【非常详细】

CreateExecutionProviderInstance CUDA_PATH is set but CUDA wasnt able to be loaded. Please install the correct version of CUDA andcuDNN as mentioned in the GPU requirements page onnxruntime GPU加速onnx 无法使用GPU加速 加速失败 解决方法【非常详细】应该是自目…

jsAPIS-DomEvent

APIs 申明变量const优先 对于变量申明,常见的申明方式包括:var、let、conts。由于var老旧,我们避免使用和var进行变量声明。 那么在定义变量时如何判断使用let还是const? 对于常量(后续不会改变)变量,使用const进行申明。对于会发生变化的变量,使用let进行声明。常见情…