STM32标准库配置时钟(外部时钟和内部时钟)

发布这个博客的原因是在测试板子时发现一些问题,和时钟树有关,所以写在这里记录一下

问题背景:首先使用了STM32F411CEU6最小系统板商家提供的LED_DEMO(使用HAL库开发),程序运行无误,LED正常闪烁

然而在使用网上下载的工程文件(标准库开发)对STM32F411CEU6最小系统板进行LED_demo测试时,程序烧录后出现两个问题:

1.LED亮度明显不够

2.LED无法闪烁,执行delay函数或者串口打印函数都会导致程序无法顺利运行

最后发现是时钟问题,记录一下解决方法(配置成和商家DEMO一致的时钟)

一、时钟配置图

这是商家提供的DEMO,可以从CUBEMX中看到他使用的是内部时钟

以及三个预分频系数(PCLK1)、(PCLK2)、(HCLK)分别为2、1、1

以及M(8)、N(100)、P(2)、Q(4),这些都是关于时钟配置很重要的参数

二、接下来开始在标准库配置时钟:

这里介绍两种种配置方法,第一种是直接修改系统自带的时钟配置函数以及参数,虽然这里商家用的是外部时钟,但在这里我同时介绍内部时钟配置和外部时钟配置的方法。第二种方法是屏蔽系统自带的时钟配置函数,自己创建时钟配置函数然后在main函数中调用。

第一种:直接修改系统自带的时钟配置函数以及参数

找到.s文件中的SystemInit函数,并进入SystemInit函数

再进入SetSysClock函数,分析函数中的宏定义选择

如果选择外部时钟,则在该文件上方添加代码

#define USE_HSE_BYPASS 

我们要做的就是通过宏定义选择时钟源以及外修改重要参数。

由于我的目的是把网上的DEMO配置成和商家时钟一致,所以按照上面的时钟图配置(图中代码已经是配置好了的),其中分频系数可以直接查看定义去选择修改为怎样的分频,而M、N、P、Q其实也只需要去 查找宏定义修改就够了,参照下图

当然,使用外部时钟还有一个要注意,就是定义外部时钟晶振大小

为什么这里是8Mhz,这就要通过原理图看你自己的外部时钟源是多少了

选择内部时钟的做法和外部时钟基本一致

只要不要#define USE_HSE_BYPASS ,并且走的是这个分支(即这段代码不会是灰色的)就OK了。其他的参数修改和上述一致

第二种:自己写时钟配置函数

这种方法我也是参考了其他CSDN博客,这种方法我只介绍使用内部时钟,外部时钟不建议用这种,反正我没搞定

第一步注释系统时钟配置函数

第二步DIY自己的时钟配置函数

 
/*


*/
void Config_SystemClock(uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
{
	RCC_DeInit();  //让所有RCC时钟为缺省值等待我们配置
	RCC_HSICmd(ENABLE);	//让HSI作为时钟源 
	
	while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);


    RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);  // 配置系统时钟为HSI
  
    RCC_HCLKConfig(RCC_SYSCLK_Div1); //??AHB?????
    RCC_PCLK1Config(RCC_HCLK_Div2);  //??APB1?????
    RCC_PCLK2Config(RCC_HCLK_Div1);  //??APB2?????


    //配置PLL系统时钟 让HSI作为系统时钟源
    RCC_PLLConfig(RCC_PLLSource_HSI, m, n, p, q);
    RCC_PLLCmd(ENABLE); 启用PLL


//这一步是关键等待PLL就绪 等于SET时就是锁住了 可以用PLL作为系统时钟了
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
	
    //关于FLASH的操作(不同芯片似乎不同,不懂,看的别人的F4代码)
    FLASH->ACR = FLASH_ACR_PRFTEN 
                    | FLASH_ACR_ICEN 
                    | FLASH_ACR_DCEN 
                    | FLASH_ACR_LATENCY_5WS;


    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);// 选择PLL作为系统时钟源
    while(RCC_GetSYSCLKSource() != 0x08) ;// 读取时钟切换状态位,确保PLLCLK被切换为系统时钟
}
 
 

第三步加入到main函数钟

以上就是关于时钟配置的内容,本篇内容的思路是

通过给定的时钟树,然后自己在标准库中实现对应的时钟配置代码

### STM32标准库时钟配置 #### 配置概述 STM32时钟配置涉及多个方面,包括系统时钟 (SYSCLK)、AHB 总线时钟 (HCLK)、APB1 APB2 外设总线时钟等。这些时钟可以通过内部 RC 振荡器或外部晶振来驱动[^1]。 #### 方法一:修改现有函数 一种常见的做法是在 `stm32f10x.h` 文件中调整预处理器指令以适应所需的时钟频率设置。例如,默认情况下可能已经定义了宏 `SYSCLK_FREQ_72MHz` 来指定 72 MHz 的工作频率[^3]。如果需要更改此值,则可以在项目初始化阶段之前重新定义这个宏: ```c #define SYSCLK_FREQ_HSE HSE_VALUE /* External High Speed Oscillator */ #define SYSCLK_FREQ_24MHz ((uint32_t)24000000) // 更多其他频率选项... ``` 接着,在主程序文件里调用 `SetSysClock()` 函数前加入新的定义语句: ```c #ifdef USE_FULL_ASSERT #include "stm32_assert.h" #endif /* USE_FULL_ASSERT */ int main(void){ #if defined(USE_STM32F1XX_NUCLEO) || defined(USE_STM32F4_DISCOVERY) SystemInit(); // 初始化硬件资源 #ifdef SYSCLK_FREQ_24MHz SetSysClockTo24(); #elif defined(SYSCLK_FREQ_72MHz) SetSysClockTo72(); #endif #else #error "Please select first the evaluation board used" #endif while (1){...} } ``` 这种方法允许开发者快速切换不同的时钟源而无需大幅改动底层代码结构[^4]。 #### 方法二:自定义时钟配置函数 另一种更为灵活的方式是完全移除原有的时钟初始化逻辑,并编写自己的实现版本。这通常意味着要直接操作 RCC(Reset and Clock Control)寄存器来进行更精细的控制。下面给出一个简单的例子展示如何仅依赖于内部高速RC振荡器(HSI)作为系统时钟源并将其频率设定为8MHz: ```c void MyCustomSystemClockConfig(void){ __IO uint32_t StartUpCounter = 0, HSICalibrationValue = 0; // Enable HSION bit of CR register. RCC->CR |= (uint32_t)RCC_CR_HSION; // Wait till HSI is ready and if Time out is reached exit do{ StartUpCounter++; }while((RCC->CR & RCC_CR_HSIRDY)==0 && StartUpCounter != HSI_STARTUP_TIMEOUT); if ((RCC->CR & RCC_CR_HSIRDY)!=RESET){ // Configure Flash prefetch, Instruction cache, Data cache and wait state FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); FLASH_SetLatency(FLASH_Latency_2); // Select HSI as system clock source RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSI; // Wait till HSI is used as system clock source while ((RCC->CFGR & RCC_CFGR_SWS) != (uint32_t)0x00){} // 设置 AHB/APB 分频因子 RCC->CFGR |= (uint32_t)(RCC_CFGR_HPRE_DIV1 | \ RCC_CFGR_PPRE1_DIV2| \ RCC_CFGR_PPRE2_DIV1); // 更新全局变量 SystemCoreClock (由 CMSIS 提供) SystemCoreClockUpdate(); } } ``` 这段代码展示了如何启用HSI并通过适当分频使能各条总线上所需的工作速度。注意最后一步更新了 `SystemCoreClock` 变量,这对于确保后续任何基于 CPU 周期计数的操作都能获得正确的结果至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值