STM32 HAL库学习(五)RCC时钟树分析

本文详细解析了STM32F070RB开发板的时钟系统,包括SYSCLK、RTC、USB、ADC、USART1等模块的时钟源配置,以及MCO时钟输出引脚的选项。介绍了STM32RCCHAL库中关键时钟配置函数的作用和使用方法,如HSI、HSE的初始化与旁路模式。

开发板采用STM32F070RB,最大时钟速率为48MHZ,在STM32Cube MX中可以选择对应的芯片,得到它的时钟树如下所示:

分析时钟树,几种主要的时钟源分析如下

1、SYSCLK系统时钟的时钟源

          —— 8MHZ HSI内部晶振

          —— 8MHZ HSE外部晶振

          —— PLLCLK(来源于倍频后的HSI或HSE)

2、RTC实时时钟的时钟源

           —— HSE晶振32分频  250KHZ

           —— LSE 外部低速晶振 32.768KHZ

           —— LSI 内部低速晶振 40KHZ

3、USB时钟源

           ——  HSI内部晶振倍频

           ——  HSE外部晶振倍频(更准确)

4、ADC时钟源

           ——  HSI14RC  14MHZ

           ——  APB时钟2分频或4分频

5、 USART1时钟源

           —— SYSCLK

           —— HSI

           —— LSE

            —— PCLK1即APB1

6、MCO时钟输出引脚(PA8)

      ——  PLLCLK、HSI、HSI14、HSE、LSI、LSE、SYSCLK

7、挂靠AHB高速总线的设备

      —— CPU、DMA、GPIO等

8、挂靠APB低速时钟线的设备

      —— USART、TIM等

时钟配置中有一个Enable CSS,即允许Clock security system,如果使能宏变量 _HAL_RCC_CSS_ENABLE()或者在Cube MX中配置了Enable CSS,则当HSE时钟启用失败时,系统会自动切换到HSI作为时钟源,并产生一个NMI不可屏蔽中断。

 

STM32 RCC HAL库驱动主要在stm32f0xx_hal_rcc.c/h中

  —— HAL_RCC_DeInit主要完成整个系统时钟的复位

  —— HAL_RCC_OscConfig则根据RCC_OscInitStruct结构体的值对晶振进行初始化(HSE、HSI、LSI、LSE、HSI14、HSI48、PLL)

           如果要通过这个函数实现HSI/HSE从打开到旁路(或旁路到打开)的转换,必须先关闭HSI/HSE

   —— HAL_RCC_ClockConfig初始化CPU、AHB和APB时钟

   —— HAL_RCC_MCOConfig选择MCO管脚输出的时钟源

   —— HAL_RCC_GetSysClockFreq获取当前的SYSCLK时钟频率

   —— HAL_RCC_EnableCSS/HAL_RCC_DisableCSS系统始终安全,选择HSE作为时钟源时可配置

   —— HAL_RCC_NMI_IRQHandler处理RCC CSS中断,回调函数HAL_RCC_CSSCallback()可供用户重写

 

时钟的旁路模式,即不启用内部时钟驱动组件,直接引用外部时钟源,关于这点。这个博客上有很详细的说明:https://blog.youkuaiyun.com/wuyusheng314/article/details/78947096

`HAL_RCC_GetClockConfig()` 是 HAL (Hardware Abstraction Layer) 中用于获取系统时钟配置信息的一个函数,在STM32微控制器上广泛使用,特别是处理与 RCC (RCC 构造器) 配置相关的任务。这个函数通常用于调试或确认硬件时钟设置是否如预期。 例如,下面是一个简单的范例,展示了如何在STM32F4项目中使用 `HAL_RCC_GetClockConfig()` 获取 APB1总线时钟频率: ```c #include "stm32f4xx_hal.h" // 初始化并启动时钟系统 void SystemClock_Config(void) { // 其他初始化步骤... // 获取APB1时钟配置 RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; // 填充时钟配置结构体 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_MCO; // 使用HSE、LSI作为主时钟源 RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 开启HSI振荡器 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 启动PLL RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // 设置PLL源为HSE RCC_OscInitStruct.PLL.PLLM = 8; // PLL倍频系数 RCC_OscInitStruct.PLL.PLLN = 336; // 输出频率(48MHz) RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 输出分频 RCC_OscInitStruct.PLL.PLLQ = 7; // 分频系数 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { // 处理错误... } // 根据配置应用时钟 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 这里假设APB1时钟需要除以4 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { // 处理错误... } // 现在可以获取APB1时钟频率 uint32_t hclk_Frequency = HAL_RCC_GetSysClockFreq(); // 获取系统时钟频率,即APB1频率(因为已配置为sysclk) uint32_t pclk1_Frequency = hclk_Frequency / RCC_APB1CLK_DIV4; // 计算APB1的实际频率 // 打印或记录APB1时钟频率 printf("APB1 Clock Frequency: %u MHz\n", pclk1_Frequency / 1000000); // ...其他后续操作 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值