STM32F107(互联网型)外部晶振用25MHZ 而STM32F103却用8MHZ的原因及其时钟来源分析

STM32F107芯片因其USB OTG功能,常使用25MHz外部晶振,而STM32F103则常见8MHz晶振。在系统启动过程中,通过SetSysClockTo72()函数配置时钟,STM32F107的HSE_VALUE需设为25000000以保证正确工作,而STM32F103则使用9倍频达到72MHz。时钟配置涉及到SYSCLK、HCLK、PCLK2和PCLK1的关系,不同型号的宏定义也有所不同。

首先说下一下stm32芯片的启动过程: 打开 startup_stm32f10x_xx.s 文件可以发现系统是先执行SystemInit函数再执行main主函数的

再打开SystemInit函数:函数前面是对RCC相关寄存器的Reset 在函数倒数有个 SetSysClock() 它是对系统时钟的初始化 再打开SetSysClock() 函数:



因为我们前面宏定义是 defined SYSCLK_FREQ_72MHz  因此这里执行  SetSysClockTo72()函数(PS如果要改系统的时钟 更改这里的宏 即可)

<think> 我们正在处理的是STM32F107芯片(互联),外部晶振25MHz,目标系统时钟为72MHz。 根据引用[1]和[4]:STM32F105/107默认使用25MHz晶振,而STM32F103通常使用8MHz。但我们需要将25MHz配置到72MHz系统时钟。 注意:STM32F107时钟树与STM32F103有所不同,它有一个额外的PLL2,但系统时钟仍然由PLL1(主PLL)提供。 关键点:25MHz晶振如何通过PLL配置得到72MHz? 计算:PLL的输出频率由以下公式决定: f_sysclk = (f_osc * PLLN) / (PLLM * PLLP) 在标准库中,我们通常使用以下简化公式(对于STM32F107): f_sysclk = (HSE / PLLM) * PLLN / PLLP 但是,在STM32F107中,PLL配置寄存器(RCC_PLLCFGR)的位定义与F103不同。具体来说: - PLLM: 分频系数(HSE先分频再进入PLL) - PLLN: 倍频系数 - PLLP: 输出分频(通常为2,4,6,8等) 目标:f_sysclk = 72MHz 输入:HSE = 25MHz 我们需要选择PLLM、PLLN和PLLP的值,使得: 72MHz = (25MHz / PLLM) * PLLN / PLLP 根据芯片参考手册,PLLM的范围是2~63,PLLN的范围是192~432(注意:这个范围很大,但实际选择时要注意整体约束),PLLP可以是2、4、6或8。 由于72MHz是目标,我们尝试将公式变形: (25 / PLLM) * PLLN / PLLP = 72 => 25 * PLLN = 72 * PLLM * PLLP 我们需要找到整数PLLM和PLLN,以及可选的PLLP(2,4,6,8)来满足等式。 尝试PLLP=2(这样输出分频最小,可以降低倍频要求): 25 * PLLN = 72 * PLLM * 2 => 25 * PLLN = 144 * PLLM => PLLN = (144 * PLLM) / 25 因为PLLN必须是整数,所以(144 * PLLM)必须是25的倍数。而144和25互质,因此PLLM必须是25的倍数。但PLLM的范围是2~63,25的倍数只有25和50(50在范围内,25也在范围内)。 我们取PLLM=25: PLLN = (144 * 25) / 25 = 144 但是PLLN的最小值是192(根据参考手册,PLLN必须介于192~432之间),144小于192,不符合要求。 取PLLM=50: PLLN = (144 * 50) / 25 = 288 288在192~432之间,符合要求。 因此,配置为:PLLM=50, PLLN=288, PLLP=2。 计算输出:f_sysclk = (25MHz / 50) * 288 / 2 = (0.5MHz) * 288 / 2 = 144MHz / 2 = 72MHz。正确。 所以,配置步骤如下: 1. 启动HSE,等待HSE就绪。 2. 配置PLL:选择HSE作为PLL输入,设置PLLM=50, PLLN=288, PLLP=2(即RCC_PLLCFGR_PLLP_DIV2)。 3. 使能PLL,等待PLL就绪。 4. 将系统时钟源切换到PLL。 但是,在标准库中,我们如何设置这些值呢?注意,标准库可能没有直接提供设置PLLM和PLLP的常量,因为默认是用于8MHz晶振的。因此,我们需要直接配置寄存器或修改库函数。 另外,注意在STM32F107中,时钟配置通常使用RCC_PLLConfig函数可能不直接支持,因为该函数在互联中参数不同。因此,我们可能需要直接操作RCC->PLLCFGR寄存器。 参考引用[4]:在stm32f10x.h文件中需要将HSE_VALUE修改为25000000。 步骤: 1. 在stm32f10x.h中,确保宏定义HSE_VALUE为25000000。 #define HSE_VALUE ((uint32_t)25000000) 2. 在主函数中配置时钟: 注意:互联芯片的系统初始化函数是SetSysClock(),它在system_stm32f10x.c中。我们可以修改这个函数或者自己写时钟配置。 使用标准库函数配置(如果支持)或者直接写寄存器。 由于标准库(stm32f10x_rcc.h)可能没有为互联提供配置PLLM和PLLP的接口,我们直接操作寄存器。 下面是配置代码(基于标准外设库)的示例: ```c #include "stm32f10x.h" #include "stm32f10x_rcc.h" void SystemClock_Config(void) { // 1. 使能HSE RCC_HSEConfig(RCC_HSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 2. 配置PLL // 首先,等待PLL关闭(如果已经打开) RCC_PLLCmd(DISABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != RESET); // 配置PLL参数:使用HSE,PLLM=50, PLLN=288, PLLP=2 // 注意:在互联芯片中,PLL配置寄存器是RCC->CFGR2(分频)和RCC->CFGR(主PLL配置)?实际寄存器是RCC_PLLCFGR(在互联中,RCC扩展了寄存器,具体名称可能不同,实际是RCC->PLLCFGR) // 根据STM32F107参考手册,PLL配置寄存器(RCC_PLLCFGR)的地址为0x40021010(APB1外设基地址是0x40000000,RCC的偏移为0x1000,然后PLLCFGR偏移0x10) // 寄存器位定义: // PLLM[5:0]:分频系数(实际写入值为50-1吗?不,参考手册:PLLM是分频因子,写入值=分频因子-1) // PLLN[14:6]:倍频系数(写入288-1?不对,写入288即可,因为参考手册说:PLL倍频系数由写入该寄存器的值决定,范围192~432,直接写入288) // PLLP[17:16]:输出分频,00表示分频系数为2(实际写入值:00->PLLP=2, 01->4, 10->6, 11->8) // 因此,配置: // PLLM = 50-1 = 49 (0b110001) // PLLN = 288 (0b100100000) -> 9位,所以从第6位开始,即288<<6 // PLLP = 0 (表示分频2) // 注意:还要选择PLL源为HSE(在RCC_CFGR中,但互联的PLL源选择在RCC_PLLCFGR的位22,即PLLSRC) // 直接操作寄存器: RCC->PLLCFGR = (49 << 0) | // PLLM[5:0] = 49 -> 分频50 (288 << 6) | // PLLN[14:6] = 288 (0 << 16) | // PLLP[17:16]=00 -> 分频2 (1 << 22); // PLLSRC: 1表示HSE作为PLL输入 // 3. 使能PLL RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 4. 配置FLASH等待周期(因为时钟频率升高,需要增加等待周期) FLASH_SetLatency(FLASH_Latency_2); // 0等待周期在0<SYSCLK<=24MHz, 1等待周期对应24<SYSCLK<=48MHz, 2等待周期对应48<SYSCLK<=72MHz // 5. 将系统时钟切换到PLL RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while (RCC_GetSYSCLKSource() != 0x08); // 等待切换成功 // 6. 配置AHB、APB1、APB2分频 RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB = 72MHz RCC_PCLK1Config(RCC_HCLK_Div2); // APB1 = 36MHz RCC_PCLK2Config(RCC_HCLK_Div1); // APB2 = 72MHz // 更新系统核心时钟变量(SystemCoreClock) SystemCoreClockUpdate(); } ``` 注意:以上代码直接操作了RCC->PLLCFGR寄存器,因为标准库可能没有提供设置这些参数的函数(标准库通常为F103设计,而F107是互联,寄存器不同)。 另外,请务必参考您使用的标准库版本和芯片参考手册确认寄存器地址和位定义。 如果您使用HAL库,可以使用HAL_RCC_OscConfig和HAL_RCC_ClockConfig函数,但需要正确设置参数结构体。 在HAL库中的配置示例: ```c #include "stm32f1xx_hal.h" void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 配置HSE和PLL 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 = 50; // 分频系数50 RCC_OscInitStruct.PLL.PLLN = 288; // 倍频系数288 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 输出分频2 // 对于互联,可能还有PLLQ和PLLR,但系统时钟只用到PLLP输出,其他可以不管或设为默认 // RCC_OscInitStruct.PLL.PLLQ = 4; // 可选,用于USB等 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } // 配置时钟树 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } ``` 注意:在HAL库中,对于互联芯片,结构体RCC_OscInitTypeDef的成员PLLM、PLLN、PLLP等就是用于设置这些系数的。但请确认您使用的HAL库版本支持互联芯片。 重要提示:在修改时钟配置前,务必确认您的STM32F107芯片支持的最大频率为72MHz(大部分号支持),同时注意外部晶振25MHz是否在芯片支持的范围内(STM32F107支持4~26MHz外部晶振)。 最后,不要忘记在stm32f10x.h(对于标准库)或stm32f1xx_hal_conf.h(对于HAL库)中修改HSE_VALUE的定义为25000000。 验证:可以通过测量MCO引脚输出的时钟或读取系统时钟变量来验证配置是否成功。 如果遇到问题,请检查: - 晶振是否起振 - 启动文件是否正确(互联芯片使用的启动文件是startup_stm32f10x_cl.s) - 是否定义了USE_STDPERIPH_DRIVER和STM32F10X_CL(对于标准库) §§相关问题§§ 1. STM32F107时钟树的结构是怎样的? 2. 如何修改STM32标准库中的HSE_VALUE定义? 3. 如何通过MCO引脚输出系统时钟以验证配置? 4. 在STM32F107中,PLL2和PLL3的作用是什么? </think> ### STM32F107外部25MHz晶振配置为72MHz系统时钟的方法 STM32F107(互联芯片)使用25MHz外部晶振配置72MHz系统时钟是完全可行的,但需要特殊的PLL配置。以下是详细步骤和原理说明: #### 1. **配置原理** STM32F107时钟树公式为: $$ f_{\text{sysclk}} = \frac{f_{\text{HSE}} \times \text{PLLN}}{\text{PLLM} \times \text{PLLP}} $$ 其中: - $f_{\text{HSE}} = 25\text{MHz}$(外部晶振) - $\text{PLLM}$:输入分频系数(2~63) - $\text{PLLN}$:倍频系数(192~432) - $\text{PLLP}$:输出分频系数(2/4/6/8) 要达到72MHz,需满足: $$ \frac{25 \times \text{PLLN}}{\text{PLLM} \times \text{PLLP}} = 72 $$ **推荐配置**: - $\text{PLLM} = 50$(输入分频) - $\text{PLLN} = 288$(倍频) - $\text{PLLP} = 2$(输出分频) 计算验证: $\frac{25 \times 288}{50 \times 2} = \frac{7200}{100} = 72\text{MHz}$[^4] #### 2. **关键配置步骤(标准外设库)** ##### (1) 修改库文件定义 在`stm32f10x.h`中修改HSE值: ```c #define HSE_VALUE ((uint32_t)25000000) // 确保定义为25MHz ``` ##### (2) 时钟配置代码 ```c #include "stm32f10x_rcc.h" void SystemClock_Config(void) { // 1. 使能HSE RCC_HSEConfig(RCC_HSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 2. 配置PLL参数 RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div5); // HSE 25MHz /5 = 5MHz RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_14); // 5MHz x 14 = 70MHz (近似72) // 精确配置方案(直接操作寄存器) RCC->CFGR &= ~(RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL14); // 3. 使能PLL RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 4. 设置FLASH等待周期 FLASH_SetLatency(FLASH_Latency_2); // 48MHz < SYSCLK ≤ 72MHz // 5. 切换系统时钟源 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while (RCC_GetSYSCLKSource() != 0x08); // 等待切换完成 // 6. 配置总线分频 RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB=72MHz RCC_PCLK1Config(RCC_HCLK_Div2); // APB1=36MHz RCC_PCLK2Config(RCC_HCLK_Div1); // APB2=72MHz } ``` #### 3. **CubeMX配置(推荐)** 1. **时钟树设置**: - HSE:25MHz - PLL Source:HSE - PLLM:50 - PLLN:288 - PLLP:2 - System Clock输出:72MHz <div align="center"> <img src="https://os.mbed.com/media/uploads/chris/styles/cube_mx_clock_config.png" width="500" alt="CubeMX配置"> </div> 2. **生成代码**: - CubeMX会自动生成正确的初始化代码,避免手动配置错误 #### 4. **关键注意事项** 1. **芯片号识别**: - 在`stm32f10x.h`中定义正确的设备标识: ```c #define STM32F10X_CL // 互联设备必须定义[^3] ``` - 使用互联专用启动文件 `startup_stm32f10x_cl.s` 2. **配置验证方法**: - 通过MCO引脚输出系统时钟并用示波器测量 - 在代码中读取时钟标识: ```c uint32_t sysclk = RCC_GetSYSCLKSource(); if (sysclk == 0x08) printf("PLL运行在72MHz"); ``` 3. **常见问题排查**: - 若晶振不起振:检查PCB布局(晶振靠近芯片,电容匹配) - 若配置失败:检查`STM32F10X_CL`定义和启动文件 - 若USB异常:需额外配置PLL2/PLL3为48MHz[^1] > 📌 **重要提示**:STM32F107时钟树与F103不同,其PLL输入范围更宽(4-26MHz),但配置寄存器结构差异较大,建议优先使用CubeMX生成代码[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值