时钟树

一图胜千言。照例先上一张时钟树的图。

来自:RM0090,STM32F40xxx、STM32F41xxx、STM32F42xxx、STM32F43xxx参考手册

配置时钟流程

  • 使能外部高速时钟(HSE)
  • 等待HSE时钟信号稳定
  • 配置锁相环PLL
  • 等待PLL就绪
  • 选择PLL作为主时钟源(配置SW)
  • 等待系统时钟切换完成(检查SWS)
  • 配置外设总线的分频系数

具体配置方法

官方提供了三种配置方法。

KEIL-MDK4使用寄存器配置

参考文档:

C:\Keil\ARM\Startup\ST\STM32F4xx\startup_stm32f40xx.s

C:\Keil\ARM\Startup\ST\STM32F4xx\system_stm32f4xx.c

复位后,CPU执行Reset_Handler函数。在startup_stm32f40xx.s文件中。

先执行SystemInit(),再执行__main()。在__main()函数中会跳转到用户的main()函数。

; Reset handler
Reset_Handler    PROCEXPORT  Reset_Handler             [WEAK]IMPORT  SystemInitIMPORT  __mainLDR     R0, =SystemInitBLX     R0LDR     R0, =__mainBX      R0ENDP

在SystemInit()函数中,会调用SetSysClock()函数。

  /* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/SetSysClock();

SetSysClock()函数的官方标准模板为:

/*** @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)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* Enable HSE */    // 使能外部高速时钟HSERCC->CR |= ((uint32_t)RCC_CR_HSEON);/* Wait till HSE is ready and if Time out is reached exit */    // 等待HSE时钟信号稳定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;        // HSE启动成功}else{HSEStatus = (uint32_t)0x00;        // HSE启动失败}if (HSEStatus == (uint32_t)0x01)    // HSE成功{/* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */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_DIV2;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;/* 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_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 */ // 等待系统时钟就绪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 */}}

关于主锁相环的配置,有以下参数:

/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      25
#define PLL_N      336/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7/******************************************************************************/

KEIL-MDK5使用LL外设驱动配置

在KEIL5的标准模板中,时钟是在main()函数中配置的。

参考文档:

C:\Keil_v5\ARM\Packs\Keil\STM32F4xx_DFP\2.14.0\MDK\Templates_LL\Src\main.c

main()函数:

/*** @brief  Main program* @param  None* @retval None*/
int main(void)
{/* Configure the system clock to 168 MHz */SystemClock_Config();SystemCoreClockUpdate();/* Add your application code here */
#ifdef RTE_CMSIS_RTOS2/* Initialize CMSIS-RTOS2 */osKernelInitialize ();/* Create thread functions that start executing, Example: osThreadNew(app_main, NULL, NULL); *//* Start thread execution */osKernelStart();
#endif/* Infinite loop */while (1){}
}

main()函数的第一件事就是配置系统时钟:

/*** @brief  System Clock Configuration*         The system Clock is configured as follow :*            System Clock source            = PLL (HSE)*            SYSCLK(Hz)                     = 168000000*            HCLK(Hz)                       = 168000000*            AHB Prescaler                  = 1*            APB1 Prescaler                 = 4*            APB2 Prescaler                 = 2*            HSE Frequency(Hz)              = 8000000*            PLL_M                          = 8*            PLL_N                          = 336*            PLL_P                          = 2*            VDD(V)                         = 3.3*            Main regulator output voltage  = Scale1 mode*            Flash Latency(WS)              = 5* @param  None* @retval None*/
void SystemClock_Config(void)
{/* Enable HSE oscillator */LL_RCC_HSE_Enable();while(LL_RCC_HSE_IsReady() != 1){};/* Set FLASH latency */LL_FLASH_SetLatency(LL_FLASH_LATENCY_5);/* Main PLL configuration and activation */LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_8, 336, LL_RCC_PLLP_DIV_2);LL_RCC_PLL_Enable();while(LL_RCC_PLL_IsReady() != 1){};/* Sysclk activation on the main PLL */LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL){};/* Set APB1 & APB2 prescaler */LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_4);LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);/* Set systick to 1ms */SysTick_Config(168000000 / 1000);/* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */SystemCoreClock = 168000000;
}

注意:官方例程中开发板使用的外部晶振是8M的,PLL的预分频系数M是8,倍频系数N是336,再2分频到得168M。

如果外部晶振是25M的,则需要更改M系数为25.

KEIL-MDK5使用HAL外设驱动配置

文档模板:

参考文档:

C:\Keil_v5\ARM\Packs\Keil\STM32F4xx_DFP\2.14.0\MDK\Templates\Src\main.c

与LL配置方法类似,也是在main()函数中,HAL_Init()之后就调用SystemClock_Config()来配置系统时钟。

/*** @brief  System Clock Configuration*         The system Clock is configured as follow : *            System Clock source            = PLL (HSE)*            SYSCLK(Hz)                     = 168000000*            HCLK(Hz)                       = 168000000*            AHB Prescaler                  = 1*            APB1 Prescaler                 = 4*            APB2 Prescaler                 = 2*            HSE Frequency(Hz)              = 8000000*            PLL_M                          = 25*            PLL_N                          = 336*            PLL_P                          = 2*            PLL_Q                          = 7*            VDD(V)                         = 3.3*            Main regulator output voltage  = Scale1 mode*            Flash Latency(WS)              = 5* @param  None* @retval None*/
static void SystemClock_Config(void)
{RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;/* Enable Power Control clock */__HAL_RCC_PWR_CLK_ENABLE();/* The voltage scaling allows optimizing the power consumption when the device is clocked below the maximum system frequency, to update the voltage scaling value regarding system frequency refer to product datasheet.  */__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/* Enable HSE Oscillator and activate PLL with HSE as source */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){/* Initialization Error */Error_Handler();}/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){/* Initialization Error */Error_Handler();}/* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported */if (HAL_GetREVID() == 0x1001){/* Enable the Flash prefetch */__HAL_FLASH_PREFETCH_BUFFER_ENABLE();}
}/*** @brief  This function is executed in case of error occurrence.* @param  None* @retval None*/
static void Error_Handler(void)
{/* User may add here some code to deal with this error */while(1){}
}

后两种方法,需要勾选RCC等组件:

需要引用的文件有:

STM32F4xx时钟配置的三种方法相关推荐

  1. 最后一次正确配置计算机,win10进入最后一次正确配置的三种方法

    电脑使用时间久都会出现一些小问题,如果实在无法解决的问题的时候可以通过进入最后一次正确配置来解决,那么win10如何进入最后一次正确配置?相信大部分新手都不懂怎么操作?就此疑问,小编分享win10进入 ...

  2. 怎么查看台式计算机系统,怎么查看电脑配置呢?三种方法知道电脑详细配置

    怎么查看电脑配置呢?很多朋友想要了解自己电脑详细的配置的时候,一般都是通过第三方的工具检测的,那么有没有其他更好的方法呢?下面小白系统带你认识下查看电脑配置的三种方法. 以下方法针对win7.win8 ...

  3. win8如何查看电脑配置呢?三种方法知道电脑详细配置

    怎么查看电脑配置呢?很多朋友想要了解自己电脑详细的配置的时候,下面带你认识下查看电脑配置的方法. 以下方法针对win7.win8.win10系统有效果 方法一:设备管理器 我们通过鼠标右击此电脑(我的 ...

  4. springboot学习(一)IDEA简单使用以及数据源配置的三种方法

    Springboot的简单使用 1 运行环境 2 maven的配置如下 3 如何使用springboot 4.配置数据源 4.1基本的配置方法 4.2springboot对数据源配置的优化(第一种) ...

  5. yum配置文件 重启后还原_yum源配置的三种方法

    (一)yum源概述 yum需要一个yum库,也就是yum源.默认情况下,CentOS就有一个yum源.在/etc/yum.repos.d/目录下有一些默认的配置文件(可以将这些文件移到/opt下,或者 ...

  6. RHEL7.0 配置网络IP的三种方法

    导读 RHEL7里面的网卡命名方式从eth0,1,2的方式变成了enoXXXXX的格式. en代表的是enthernet (以太网),o 代表的是onboard (内置),那一串数字是主板的某种索引编 ...

  7. Pycharm社区版运行Django的三种方法(Pycharm添加配置参数快捷启动Django、Pycharm社区版Django项目创建)

    目录 Pycharm社区版运行Django的三种方法 Django安装和环境变量的配置(MacOS) 创建Project 启动Django Webserver 方法一:终端启动 方法二:pycharm ...

  8. linux配置yum源的三种方法:

    linux配置yum源的三种方法: 1.配置网络yum源 2.通过上传镜像文件配置本地yum源 3.通过连接存储或本地镜像文件配置本地yum源(虚拟机) 配置各种yum源的时候,需要提前知道自己的li ...

  9. 计算机配置高低怎么看,怎么查看电脑配置?(查看电脑配置高低的三种方法!)...

    电脑配置的高低直接影响着使用电脑时候的体验度,要是配置过低,电脑用起来就会很卡,稍微打开大一点的程序或者多开几个网页就卡死,非常不好用,那么,怎么查看电脑配置呢?电脑配置多高才合适呢?下面来告诉你. ...

最新文章

  1. 面向对象的C语言开发框架:Nesty
  2. ajax 返回数组某个属性值,js中sort方法根据数组中对象的某一个属性值进行排序...
  3. php 自定义条件,php – 使用两个条件自定义排序数组数组
  4. android 开发常见问题,Android 开发常见问题汇总
  5. 尝试修改源码需要用到git存一下
  6. sas infile和filename
  7. 报错Unable to resolve target android-5
  8. 判断显卡好坏的步骤、新买显卡装机后不亮解决
  9. 两种模式的资源管理器代码之———— 重命名文件夹
  10. i5功耗最低的cpu_探寻低电压CPU性能 i5-3330S对比测试
  11. 终止代码:DRIVER_IRQL_NOT_LESS_OR_EQUAL 失败的操作:CH341S64.SYS
  12. 电脑变卡DOS解决方案
  13. 计算机技术的发展包括几个阶段,目前电子计算机处于哪个阶段?计算机发展的四个阶段...
  14. 520程序员的浪漫表白
  15. 硅芯思见:SystemVerilog中的packedarray和unpacked array
  16. python实现视频音频同步
  17. DB查询分析器7.01新增的周、月SQL执行计划功能
  18. C++ Traits编程技法--从迭代器的设计看参数推导与类型推导
  19. MateRS能不能升级鸿蒙,华为MateRS只是开胃菜:麒麟980+1536G+5G芯片,网友:确实很吓人!...
  20. cisco理论---以太通道端口会聚协议(PAgP)与LACP的区别

热门文章

  1. 产业园区需要塑造的“六”大品牌
  2. 快捷安装Mac系统下安装/卸载brew
  3. 解决win10点击开始按钮无反应
  4. 各大日语学习网站整理
  5. Calendar 获得当前日期是这一年的第几天
  6. green power 设备入网过程
  7. 如何编辑程序(一个简单的程序)
  8. 镁光nor flash 开源控制器调教记录
  9. FFmpeg从视频中提取音频保存为mp3文件
  10. Android中3D gallary的实现