备注
1)Cortex系统定时器Systick的时钟源可以是AHB时钟HCLK或HCLK的 8 分频。具体配置参考 Systick 定时器配置。
2)在以上的时钟输出中,有很多是带使能控制的,例如 AHB 总线时钟、内核时钟、各种 APB1 外设、 APB2 外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。
二、STM32L4 时钟系统初始化配置
在系统启动之后,程序会先执行 HAL 库定义的 SystemInit 函数(该函数位于system_stm32l4xx.c源文件里),进行一些初始化配置:
- /*********************************************************************
- 函数名称:void SystemInit(void)
- 函数功能:1) FPU 设置
- 2) 复位 RCC 时钟配置为默认复位值(默认开启 MSI)
- 3) 中断向量表地址配置
- 入口参数:无
- 返回参数:无
- **********************************************************************/
- void SystemInit(void)
- {
- #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
- SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); // 如果需要 FPU 的话就使能 FPU,设置 CP10 和 CP11 为全访问
- #endif
- /* 复位 RCC 时钟配置为默认配置-----------*/
- RCC->CR |= RCC_CR_MSION; // 打开 MSION 位
- RCC->CFGR = 0x00000000U; // 复位 CFGR 寄存器
- RCC->CR &= 0xEAF6FFFFU; // 清除 HSEON,CSSON,HSION ,PLLON 位
- RCC->PLLCFGR = 0x00001000U; // 复位 PLLCFGR 寄存器
- RCC->CR &= 0xFFFBFFFFU; // 复位 HSEBYP 位
- RCC->CIER = 0x00000000U; // 关闭所有的中断
- /* 配置中断向量表地址=基地址+偏移地址 ------------------*/
- #ifdef VECT_TAB_SRAM
- SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
- #else
- SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
- #endif
- }
复制代码
HAL 库的 SystemInit 函数除了打开 MSI 之外,没有任何时钟相关配置,所以必须编写自己的时钟配置函数。这里,看下正点原子在工程SYSTEM分组下提供的sys.c文件中的时钟初始化函数 SystemClock_Config 的内容:
- /*********************************************************************
- 函数名称:void SystemClock_Config(void)
- 函数功能:SYSCLK = HSE / PLLM * PLLN / PLLR
- SYSCLK = 8M / 1 * 20 /2 = 80M
- 入口参数:无
- 返回参数:无
- **********************************************************************/
- void SystemClock_Config(void)
- {
- HAL_StatusTypeDef ret = HAL_OK;
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- __HAL_RCC_PWR_CLK_ENABLE(); // 第一步,使能PWR时钟
- /*Initializes the CPU, AHB and APB busses clocks*/
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;// 时钟源选择为 HSE
- RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打开 HSE
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 打开 PLL
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 时钟源为 HSE
- RCC_OscInitStruct.PLL.PLLM = 1;
- RCC_OscInitStruct.PLL.PLLN = 20;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
- RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
- RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
- ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); // 第二步,配置时钟源相关参数
- /* 第二步主要功能,开启了HSE时钟源,同时选择PLL时钟源为HSE,同时也配置了PLL的参数 M,N,M,P和Q的值,这样就达到了设置PLL时钟源相关参数的目的。设置好PLL时钟源参数,也就是确定了PLL的时钟频率 */
- if(ret != HAL_OK) while(1);
- /*选中 PLL 作为系统时钟源并且配置 AHB、APB1、APB2*/
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
- | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // 配置SYSCLK,HCLK、PCLK2、PCLK1四个时钟。
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 选择系统时钟源为 PLL
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 分频系数为 1
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 分频系数为 1
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 分频系数为 1
- ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); // 第三步, 配置系统时钟源以及SYSCLK、AHB,APB1和APB2的分频系数
- /* 第三步配置后,可以计算出:
- PLL时钟为 PLLCLK=HSE*N/(M*R)=8MHz*20/(1*2)=80MHz;
- 选择系统时钟源为 PLL,所以系统时钟SYSCLK=80MHz;
- AHB 分频系数为 1,故其频率为 HCLK=SYSCLK/1=80MHz;
- APB1 分频系数为 1,故其频率为PCLK1=HCLK/1=80MHz;
- APB2 分频系数为 1,故其频率为 PCLK2=HCLK/1=80MHz。*/
- if(ret != HAL_OK) while(1);
- /*配置主内部调压器输出电压级别*/
- ret = HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 第四步, 设置调压器输出电压级别
- if(ret != HAL_OK) while(1);
- }
复制代码
|