reset clock control 复位和时钟控制器 一、stm32时钟树
stm32时钟树:由时钟源到外设的结构框图。 基本时钟源(图中绿色箭头指出): (1)HSI高速内部时钟,RC振荡器,8MHz。 (2)HSE高速外部时钟,石英/陶瓷谐振器,8MHz。 (3)LSI低速内部时钟,RC振荡器,40kHz。 (4)LSE低速外部时钟,RTC石英晶振,32.768kHz。 注:内部指的是片上外设,外部指的是芯片外部。 (5)除了上述基本时钟源,还有num3中的PLL锁相环倍频时钟源,它是将HSI和HSE倍频后输出。 二、PLLCLK - PLL时钟(num4) 时钟来源:(1)HSI/2 (2)HSE 三、SYSCLK - 系统时钟(num5) 时钟来源:(1)HSI (2)PLLCLK (3)HSE SYSCLK经过分频后,得到AHB总线时钟HCLK; HCLK再分频得到APB1总线时钟PCLK1和APB2总线时钟PCLK2; PCLK2分频后得到ADCCLK最大14MHz。 四、RTCCLK(灰色框中) 时钟来源:(1)HSE/128 (2)LSE (3)LSI 五、系统时钟配置 系统时钟有三个来源,PLLCLK、HSE、HSI。 正常情况下,时钟配置是在system_stm32f10x.c中完成,这里的的时钟配置是直接控制寄存器完成的。 在 stm32f10x_rcc.c中定义了关于时钟配置的库函数,此时未用。 打开system_stm32f10x.c,找到void SystemInit (void),再找到 SetSysClock()并查看定义, 定义中可知是通过在system_stm32f10x.c中宏定义SYSCLK_FREQ_72MHz选择系统时钟配置函数SetSysClockTo72(), 即72MHz的系统时钟就是在此函数中配置的,函数如下:(HSE(不分频)->PLLCLK(9倍频)->72MHz系统时钟) - static void SetSysClockTo72(void)
- {
- __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
- /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
- /* 使能 HSE */
- RCC->CR |= ((uint32_t)RCC_CR_HSEON);
- /* 等待HSE就绪并做超时处理 */
- do
- {
- HSEStatus = RCC->CR & RCC_CR_HSERDY;
- StartUpCounter++;
- } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
- if ((RCC->CR & RCC_CR_HSERDY) != RESET)
- {
- HSEStatus = (uint32_t)0x01;
- }
- else
- {
- HSEStatus = (uint32_t)0x00;
- }
- // 如果HSE启动成功,程序则继续往下执行
- if (HSEStatus == (uint32_t)0x01)
- {
- /* 使能预取指 */
- FLASH->ACR |= FLASH_ACR_PRFTBE;
- /* Flash 2 wait state */
- FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
- FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
- /* HCLK = SYSCLK = 72M */
- RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
- /* PCLK2 = HCLK = 72M */
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
- /* PCLK1 = HCLK = 36M*/
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
- /* 锁相环配置: PLLCLK = HSE * 9 = 72 MHz */
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
- RCC_CFGR_PLLMULL));
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
- /* 使能 PLL */
- RCC->CR |= RCC_CR_PLLON;
- /* 等待PLL稳定 */
- while((RCC->CR & RCC_CR_PLLRDY) == 0)
- {
- }
- /* 选择PLLCLK作为系统时钟*/
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
- RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
- /* 等待PLLCLK切换为系统时钟 */
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
- {
- }
- }
- else
- { /* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */
- }
- }
复制代码
这里再以库函数形式中重新配置系统时钟和MCO: user中新建RCC文件夹,新建bsp_rccclkconfig.c和bsp_rccclkconfig.h文件,同时对main函数做补充。(GPIO&KEY例程继续写的) bsp_rccclkconfig.h - #ifndef __BSP_RCCCLKCONFIG_H
- #define __BSP_RCCCLKCONFIG_H
- #include "stm32f10x.h"
- void HSE_SetSysClk( uint32_t RCC_PLLMul_x );
- void MCO_GPIO_Config();
- void HSI_SetSysClk( uint32_t RCC_PLLMul_x );
- #endif /*__BSP_RCCCLKCONFIG_H */
复制代码bsp_rccclkconfig.c - #include "bsp_rccclkconfig.h"
- void HSE_SetSysClk( uint32_t RCC_PLLMul_x )
- {
- ErrorStatus HSEStatus;
- //把RCC寄存器复位成复位值
- RCC_DeInit();
- // 使能 HSE
- RCC_HSEConfig(RCC_HSE_ON);
- HSEStatus = RCC_WaitForHSEStartUp();
- if( HSEStatus == SUCCESS )
- {
- // 使能预取址
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
- FLASH_SetLatency(FLASH_Latency_2);
- RCC_HCLKConfig(RCC_SYSCLK_Div1);
- RCC_PCLK1Config(RCC_HCLK_Div2);
- RCC_PCLK2Config(RCC_HCLK_Div1);
- // 配置 PLLCLK = HSE * RCC_PLLMul_x
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
- // 使能PLL
- RCC_PLLCmd(ENABLE);
- // 等待PLL稳定
- while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
- // 选择系统时钟
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
- while( RCC_GetSYSCLKSource() != 0x08 );
- }
- else
- {
- /* 如果HSE启动失败,用户可以在这里添加错误的处理代码 */
- }
- }
- void HSI_SetSysClk( uint32_t RCC_PLLMul_x )
- {
- __IO uint32_t HSIStatus = 0;
- // 把RCC寄存器复位成复位值
- RCC_DeInit();
- // 使能 HSI
- RCC_HSICmd(ENABLE);
- HSIStatus = RCC->CR & RCC_CR_HSIRDY;
- if( HSIStatus == RCC_CR_HSIRDY )
- {
- // 使能预取址
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
- FLASH_SetLatency(FLASH_Latency_2);
- RCC_HCLKConfig(RCC_SYSCLK_Div1);
- RCC_PCLK1Config(RCC_HCLK_Div2);
- RCC_PCLK2Config(RCC_HCLK_Div1);
- // 配置 PLLCLK = HSI * RCC_PLLMul_x
- RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);
- // 使能PLL
- RCC_PLLCmd(ENABLE);
- // 等待PLL稳定
- while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
- // 选择系统时钟
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
- while( RCC_GetSYSCLKSource() != 0x08 );
- }
- else
- {
- /* 如果HSI启动失败,用户可以在这里添加处理错误的代码 */
- }
- }
- void MCO_GPIO_Config()//MCO时钟输出GPIO配置,PA8
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
复制代码
main.c - 1 #include "stm32f10x.h" //
- 2 #include "bsp_key.h"
- 3 #include "bsp_led.h"
- 4 #include "bsp_rccclkconfig.h"
- 5 void Delay( uint32_t count ) //软件延时函数,但是实际时间间隔取决于系统时钟
- 6 {
- 7 for(; count!=0; count--);
- 8 }
- 9
- 10 int main(void)
- 11 {
- 12 // 来到这里的时候,系统时钟已经被配置成72M
- 13 LED_GPIO_Config();
- 14 KEY_GPIO_Config();
- 15 //这里重新配置时钟,如果注释掉下面两条HSE和HSI语句,将使用默认的system_stm32f10x.c寄存器配置版72M16 //HSE=8MHZ,PLL九倍频=72MHZ
- 17 HSE_SetSysClk( RCC_PLLMul_9 );
- 18 //HSI/2=4MHZ,PLL十六倍频=64MHZ
- 19 //HSI_SetSysClk( RCC_PLLMul_16 );
- 20
- 21 //MCO的GPIO初始化
- 22 MCO_GPIO_Config();
- 23 //选择系统时钟作为MCO输出
- 24 RCC_MCOConfig(RCC_MCO_SYSCLK); //PA8接示波器可见
- 25 //RCC_MCOConfig(RCC_MCO_HSI);
- 26
- 27 while(1)//更改系统时钟频率,小灯的闪烁间隔出现变化
- 28 {
- 29 //
- 30 //if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) ==KEY_ON )
- 31 // LED_G_TOGGLE;
- 32
- 33 LED_G(OFF);
- 34 Delay(0xFFFFF);
- 35
- 36 LED_G(ON);
- 37 Delay(0xFFFFF);
- 38 }
- 39 }
复制代码
|