STM32时钟树之编程实践(补充)

📅 发布时间:2026/7/5 17:40:16 👁️ 浏览次数:
STM32时钟树之编程实践(补充)
引言本次基于铁头山羊up介绍的基于标准库进行的时钟树编程内容完成笔者一贯的寄存器方式开发程序编写时钟树配置的测试程序完整测试源码见文章末尾。1、时钟树初始初始上电时的时钟状态。初始SYSCLK来自HSI 8MHz分频系数AHB APB1 APB2 均为/1内核从HCLK获取时钟。内核时钟速度决定程序执行速度。默认情况下一句代码执行速度约6个时钟周期。2、标准库启动代码在启动文件也就是汇编文件中可以找到单片机上电启动首先执行的内容如下先执行SystemInit()在执行main函数。其中SystemInit()中做好了时钟树编程将时钟频率提升至72MHz以极大发挥出单片机的性能。HSE-锁相环-AHB-APB1(/1) APB2(/2)所以想要使用上电默认的时钟树则需要注释汇编中的SystemInit()执行部分。使得系统时钟编程默认时钟即均8MHz。由于一条语句执行约6个时钟周期故循环666666次则可得到比较精准的500ms以此可实现简易的LED闪烁。3、时钟树编程接口RCC_开头Reset And Clock Controller复位和时钟控制器。灰色可开关默认关绿色默认开启PLL配置时钟来源、倍频系数SYSCLK配置配置系统时钟SYSCLK来源HCLK配置分频系数PCLK1配置分频系数PCLK2配置分频系数RCC标志位状态获取查询某些状态用于判断原因是开关需消耗时间。获取SYSCLK来源获取当前SYSCLK时钟来源用于判断切换情况。4、配置时钟树四大步骤1开启HSE时钟2配置PLL锁相环参数HSE、9倍频并启动3分频器配置AHB APB1 APB24选择系统时钟SYSCLK来源#1开启HSE部分对于寄存器配置即CR寄存器中。对于标准库配置则下述接口。#2配置并开启PLL锁相环对于寄存器配置CFGR寄存器和CR寄存器中。对于标准库配置如下述接口。#3配置AHB APB1 APB2分频器对于寄存器配置在CFGR寄存器中。对于标准库配置使用下述函数接口。#4选择SYSCLK来源使用寄存器配置在CFGR寄存器中使用标准库配置使用下述函数接口。5、配置Flash指令预取赶不上Flash速度。利用缓冲区提前准备Flash数据给内核指令预取开启条件SYSCLK频率8MHz所以需要在最初开启更为合适。设置访问延时72MHz需要2个周期的访问延迟。关于Flash的配置还不知道如何查阅相关寄存器描述但在STM32系统文件中确实存在FLASH的寄存器结构体定义及配置内容。6、本次测试核心源代码/* * Descripttion: 时钟树编程 * Author: JaRyon * version: * Date: 2026-01-22 19:50:52 */ #include stm32f10x.h // 系统时钟初始化配置函数需要先注释掉原先汇编启动文件中的SystmInit()执行逻辑 void System_ClockInit(void); int main(void) { System_ClockInit(); // led闪烁观察现象 PA2 RCC-APB2ENR | RCC_APB2ENR_IOPAEN; GPIOA-CRL | GPIO_CRL_MODE2; GPIOA-CRL ~GPIO_CRL_CNF2; // 默认熄灭 GPIOA-ODR | GPIO_ODR_ODR2; while (1) { GPIOA-ODR ~GPIO_ODR_ODR2; // 一条语句执行约6个时钟周期,一个时钟周期8MHz即1/8us // 故500ms即500000us需要执行500000/6*8≈666666次 for (uint32_t i 0; i 666666; i); GPIOA-ODR | GPIO_ODR_ODR2; for (uint32_t i 0; i 666666; i); } } // 72MHz void System_ClockInit(void) { // 0. 开启Flash指令预取与访问延迟 // 0.1 解锁Flash寄存器STM32F1修改ACR必须先解锁 FLASH-KEYR 0x45670123; FLASH-KEYR 0xCDEF89AB; // 0.2 设置访问延迟与Flash预取 FLASH-ACR ~(0x1F); // 清0相关位 FLASH-ACR | (FLASH_ACR_LATENCY_2); // 2个等待周期 FLASH-ACR | FLASH_ACR_PRFTBE; // 使能预取缓冲区 // 0.3 等待预取缓冲区就绪 while (!(FLASH-ACR FLASH_ACR_PRFTBS)); // 1. 开启HSE时钟 RCC-CR | RCC_CR_HSEON; // 等待HSE是否稳定 while ((RCC-CR RCC_CR_HSERDY) 0); // 2. 配置PLL锁相环 // 2.1 选择PLL输入源HSE 不分频 RCC-CFGR | RCC_CFGR_PLLSRC; RCC-CFGR ~RCC_CFGR_PLLXTPRE; // 2.2 设置倍频系数x9 RCC-CFGR ~RCC_CFGR_PLLMULL; RCC-CFGR | RCC_CFGR_PLLMULL9; // 2.3 开启PLL锁相环 RCC-CR | RCC_CR_PLLON; while ((RCC-CR RCC_CR_PLLRDY) 0); // 3. 设置总线分频系数 RCC-CFGR ~(RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2); RCC-CFGR | RCC_CFGR_HPRE_DIV1; // AHB DIV1 RCC-CFGR | RCC_CFGR_PPRE1_DIV2; // APB1 DIV2 RCC-CFGR | RCC_CFGR_PPRE2_DIV1; // APB2 DIV1 // 4. 配置系统时钟源:使用PLL来的 RCC-CFGR ~RCC_CFGR_SW; RCC-CFGR | RCC_CFGR_SW_PLL; while((RCC-CFGR RCC_CFGR_SWS) ! RCC_CFGR_SWS_PLL); }