发布这个博客的原因是在测试板子时发现一些问题,和时钟树有关,所以写在这里记录一下
问题背景:首先使用了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函数钟
以上就是关于时钟配置的内容,本篇内容的思路是
通过给定的时钟树,然后自己在标准库中实现对应的时钟配置代码