0、前言 RCC-复位和时钟控制器 可以实现配置系统时钟SYSCLK,配置AHB(HCLK)总线时钟,配置外设APB1(PCLK1)和APB2(PCLK2)时钟 库函数的标准配置为PCLK2=HCLK=SYSCLK=PLLCLK=72M,PCLK1=HCLK/2=36M 系统初始化时会调用函数实现时钟配置。 - #ifdef SYSCLK_FREQ_HSE
- uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */
- #elif defined SYSCLK_FREQ_24MHz
- uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */
- #elif defined SYSCLK_FREQ_36MHz
- uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */
- #elif defined SYSCLK_FREQ_48MHz
- uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */
- #elif defined SYSCLK_FREQ_56MHz
- uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */
- #elif defined SYSCLK_FREQ_72MHz
- uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
复制代码- static void SetSysClock(void)
- {
- #ifdef SYSCLK_FREQ_HSE
- SetSysClockToHSE();
- #elif defined SYSCLK_FREQ_24MHz
- SetSysClockTo24();
- #elif defined SYSCLK_FREQ_36MHz
- SetSysClockTo36();
- #elif defined SYSCLK_FREQ_48MHz
- SetSysClockTo48();
- #elif defined SYSCLK_FREQ_56MHz
- SetSysClockTo56();
- #elif defined SYSCLK_FREQ_72MHz
- SetSysClockTo72();
- #endif
复制代码
在system_stm32f10x.c文件中可更改宏定义改变系统时钟频率 - #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
- /* #define SYSCLK_FREQ_HSE HSE_VALUE */
- #define SYSCLK_FREQ_24MHz 24000000
- #else
- /* #define SYSCLK_FREQ_HSE HSE_VALUE */
- /* #define SYSCLK_FREQ_24MHz 24000000 */
- /* #define SYSCLK_FREQ_36MHz 36000000 */
- /* #define SYSCLK_FREQ_48MHz 48000000 */
- /* #define SYSCLK_FREQ_56MHz 56000000 */
- #define SYSCLK_FREQ_72MHz 72000000
- #endif
复制代码
1、时钟树
主要时钟
HSE:高速外部时钟,可由有源晶振或无源晶振提供,4-16MHz PLL以HSE为来源时可设置不分频或2分频 PLL:锁相环时钟源,可配置来自HSE或HSI/2 PLLCLK:锁相环时钟,可设置倍频[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] SYSCLK:系统时钟 HCLK:AHB总线时钟,系统时钟经AHB预分频得到,分频因子[1,2,4,8,16,64,128,256,512] PCLK1:APB1总线时钟,由HCLK通过低速APB1预分频得到,分频因子[1,2,4,8,16] PCLK2:APB2总线时钟,由HCLK通过高速APB2预分频得到,分频因子[1,2,4,8,16]
其他时钟- USB时钟:由PLLCLK通过USB预分频器得到,分频因子[1,1.5]
- Cortex系统时钟:由HCLK8分频得到,用来驱动内核的系统定时器SysTick
- ADC时钟:由PCLK2经ADC预分频得到,分频因子[2,4,6,8]
- RTC时钟:由HSE/128或LSE或LSI得到
- MCO时钟:输出时钟,可由PLLCLK/2,HSI,HSE,SYSCLK配置
2、时钟配置
相关库函数
配置函数
- /*
- 将RCC外设初始化为复位状态
- */
- void RCC_DeInit(void);
- /*
- 使能HSE,可选参数RCC_HSE_OFF,RCC_HSE_ON,RCC_HSE_Bypass
- */
- void RCC_HSEConfig(uint32_t RCC_HSE);
- /*
- 等待时钟源启动稳定,返回SUCCESS,ERROR
- */
- ErrorStatus RCC_WaitForHSEStartUp(void);
- /*
- 配置PLL时钟源和PLL倍频因子
- RCC_RLLSource:RCC_PLLSource_HSE_Div1,RCC_PLLSource_HSE_Div2,RCC_PLLSource_HSI_Div2
- RCC_PLLMul:RCC_PLLMul_2 [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
- */
- void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul);
- /*
- 配置系统时钟,可选参数RCC_SYSCLKSource_HSI,RCC_SYSCLKSource_HSE,RCC_SYSCLKSource_PLLCLK
- */
- void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
- /*
- 配置HCLK,可选参数RCC_SYSCLK_Div1 [1,2,4,8,16,64,128,256,512]
- */
- void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
- /*
- 配置PCLK1,可选参数RCC_HCLK_Div1 [1,2,4,8,16]
- */
- void RCC_PCLK1Config(uint32_t RCC_HCLK);
- /*
- 配置PCLK2,可选参数RCC_HCLK_Div1 [1,2,4,8,16]
- */
- void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码
使用HSE配置系统时钟- 1、开启HSE ,并等待 HSE 稳定
- 2、设置 AHB、APB2、APB1的预分频因子
- 3、设置PLL的时钟来源,和PLL的倍频因子,设置各种频率主要就是在这里设置
- 4、开启PLL,并等待PLL稳定
- 5、把PLLCK切换为系统时钟SYSCLK
- 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟
使用HSI配置系统时钟- 1、开启HSI ,并等待 HSI 稳定
- 2、设置 AHB、APB2、APB1的预分频因子
- 3、设置PLL的时钟来源,和PLL的倍频因子,设置各种频率主要就是在这里设置
- 4、开启PLL,并等待PLL稳定
- 5、把PLLCK切换为系统时钟SYSCLK
- 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟
- /* 设置 系统时钟:SYSCLK, AHB总线时钟:HCLK, APB2总线时钟:PCLK2, APB1总线时钟:PCLK1
- * PCLK2 = HCLK = SYSCLK
- * PCLK1 = HCLK/2,最高只能是36M
- * 参数说明:pllmul是PLL的倍频因子,在调用的时候可以是:RCC_PLLMul_x , x:[2,3,...16]
- * 举例:HSI_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为:4MHZ * 9 = 72MHZ
- * HSI_SetSysClock(RCC_PLLMul_16); 则设置系统时钟为:4MHZ * 16 = 64MHZ
- *
- * HSI作为时钟来源,经过PLL倍频作为系统时钟,这是在HSE故障的时候才使用的方法
- * HSI会因为温度等原因会有漂移,不稳定,一般不会用HSI作为时钟来源,除非是迫不得已的情况
- * 如果HSI要作为PLL时钟的来源的话,必须二分频之后才可以,即HSI/2,而PLL倍频因子最大只能是16
- * 所以当使用HSI的时候,SYSCLK最大只能是4M*16=64M
- */
- void HSI_SetSysClock(uint32_t pllmul)
- {
- __IO uint32_t HSIStartUpStatus = 0;
- // 把RCC外设初始化成复位状态,这句是必须的
- RCC_DeInit();
- //使能HSI
- RCC_HSICmd(ENABLE);
- // 等待 HSI 就绪
- HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
- // 只有 HSI就绪之后则继续往下执行
- if (HSIStartUpStatus == RCC_CR_HSIRDY)
- {
- //----------------------------------------------------------------------//
- // 使能FLASH 预存取缓冲区
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
- // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
- // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
- // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
- // 0:0 < SYSCLK <= 24M
- // 1:24< SYSCLK <= 48M
- // 2:48< SYSCLK <= 72M
- FLASH_SetLatency(FLASH_Latency_2);
- //----------------------------------------------------------------------//
- // AHB预分频因子设置为1分频,HCLK = SYSCLK
- RCC_HCLKConfig(RCC_SYSCLK_Div1);
- // APB2预分频因子设置为1分频,PCLK2 = HCLK
- RCC_PCLK2Config(RCC_HCLK_Div1);
- // APB1预分频因子设置为1分频,PCLK1 = HCLK/2
- RCC_PCLK1Config(RCC_HCLK_Div2);
- //-----------------设置各种频率主要就是在这里设置-------------------//
- // 设置PLL时钟来源为HSE,设置PLL倍频因子
- // PLLCLK = 4MHz * pllmul
- RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);
- //------------------------------------------------------------------//
- // 开启PLL
- RCC_PLLCmd(ENABLE);
- // 等待 PLL稳定
- while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
- {
- }
- // 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
- // 读取时钟切换状态位,确保PLLCLK被选为系统时钟
- while (RCC_GetSYSCLKSource() != 0x08)
- {
- }
- }
- else
- {
- // 如果HSI开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
- // 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,
- // HSI是内部的高速时钟,8MHZ
- while (1)
- {
- }
- }
- }
复制代码
MCO输出MCO GPIO初始化 - /*
- * 初始化MCO引脚PA8
- * 在F1系列中MCO引脚只有一个,即PA8,在F4系列中,MCO引脚会有两个
- */
- void MCO_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- // 开启GPIOA的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- // 选择GPIO8引脚
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- //设置为复用功能推挽输出
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- //设置IO的翻转速率为50M
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- // 初始化GPIOA8
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
复制代码
输出 - // MCO 引脚初始化
- MCO_GPIO_Config();
- // 设置MCO引脚输出时钟,用示波器即可在PA8测量到输出的时钟信号,
- // 我们可以把PLLCLK/2作为MCO引脚的时钟来检测系统时钟是否配置准确
- // MCO引脚输出可以是HSE,HSI,PLLCLK/2,SYSCLK
- //RCC_MCOConfig(RCC_MCO_HSE);
- //RCC_MCOConfig(RCC_MCO_HSI);
- //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
- RCC_MCOConfig(RCC_MCO_SYSCLK);
复制代码
Systick系统定时器简介SysTick——系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。 系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。 因为 SysTick 是属于 CM3 内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。 相关库函数
|