本帖最后由 TLLED 于 2018-12-8 14:42 编辑
通过第16章节 -- RCC-使用HSE/HSI配置时钟 的学习来重新认识系统总线和外设时钟的配置。
一、手册中有关时钟配置的内容
1.1、系统时钟框图:
里面显示出STM32芯片所有时钟和有关配置的寄存器位
二、系统启动有关时钟配置代码
2.1、系统启动分析
上篇介绍启动代码分析,会执行Reset Handler服务处理程序。
里面有执行SystemInit系统初始化程序
里面调用SetSysClock函数设置系统时钟
SetSysClock函数配置为72MHz后调用SetSysClockTo72函数
上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。
三、时钟配置实例
3.1、配置HSE时钟
了解系统时钟配置流程后,来实践使用时钟配置。
在系统时钟框图中,HSE时钟配置
>选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振
>通过PLLXTPRE来选择HSE时钟不分频还是2分频。
>通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。
>通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz
>通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。
3.2、程序源码
3.2.1、HSE时钟初始化
PLL时钟倍频到72MHz
- static void HSE_SetSysClock(void)
- {
- __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
- RCC_DeInit(); //RCC恢复默认状态
- RCC_HSEConfig(RCC_HSE_ON); //打开HSE时钟
-
- HSEStatus=RCC_WaitForHSEStartUp(); //等待HSE时钟稳定
- if (HSEStatus == SUCCESS)
- {
- /* Enable Prefetch Buffer */
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能FLASH预存取缓冲区
- FLASH_SetLatency(FLASH_Latency_2);
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB - HCLK=SYSCLK
- RCC_PCLK1Config(RCC_HCLK_Div2); //APB1 -- PCLK1=HCLK/2
- RCC_PCLK2Config(RCC_HCLK_Div1); //APB2 -- PCLK2=HCLK
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLL倍频
- RCC_PLLCmd(ENABLE); //使能PLL
-
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET) //等待PLL稳定
- {
- }
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //PLL稳定后,时钟切换到SYSCLK
-
-
- while(RCC_GetSYSCLKSource()!=0x08) //读取时钟切换状态位,确保PLLCLK被选为系统时钟
- {
- }
- }
- else
- {
- }
- }
复制代码 3.2.2、MCO引脚初始化
- //MCO引脚配置
- void MCO_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
复制代码 3.2.3、LED引脚初始化
- void LED_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PA端口时钟
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
复制代码 3.2.4、主程序
- int main(void)
- {
- uint32_t i;
- HSE_SetSysClock();
- MCO_GPIO_Config();
- RCC_MCOConfig(RCC_MCO_SYSCLK);
- LED_GPIO_Config();
- while (1)
- {
-
- for(i=0;i<0xffff;i++);
- GPIO_SetBits(GPIOB, GPIO_Pin_9);
- for(i=0;i<0xffff;i++);
- GPIO_ResetBits(GPIOB, GPIO_Pin_9);
- }
- }
复制代码
四、程序执行结果
4.1、PLL时钟设置为72MHz,倍频系数设置为9
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLL倍频
4.1.1、MCO输出时钟频率72M
4.1.2、LED引脚输出
4.2、PLL时钟设置为56MHz,倍频系数设置为7 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7); //PLL倍频
4.2.1、MCO输出时钟频率56M
4.2.2、LED引脚输出
LED输出宽度比72M时钟时,宽度变宽
4.3、PLL时钟设置为88MHz,倍频系数设置为11 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11); //PLL倍频
4.3.1、MCO输出时钟频率88M
4.3.2、LED引脚输出
LED输出宽度比72M时钟时,宽度变窄
五、结论
使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。
|
RCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
这句话是把第16-21位清零
由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。
0:HSI振荡器时钟经2分频后作为PLL输入时钟
1:HSE时钟作为PLL输入时钟。
以上是手册里说的
这句话是不是把相应的位置1 这样就能配置了