嵌入式开发学习之--RCC(下)
前言
这一篇记录一下时钟的具体实验。
提示:以下是本篇文章正文内容,下面案例可供参考
一、使用HSE
一般情况下,我们都是使用 HSE,然后 HSE 经过 PLL 倍频之后作为系统时钟。F429系统时钟最高为 180M,这个是官方推荐的最高的稳定时钟,如果你想铤而走险,也可以超频,超频最高能到 216M。
如果我们使用库函数编程,当程序来到 main 函数之前,启动文件:
startup_stm32f429_439xx.s 已经调用 SystemInit()函数把系统时钟初始化成 180MHZ,SystemInit()在库文件:system_stm32f4xx.c 中定义。如果我们想把系统时钟设置低一点或者超频的话,可以修改底层的库文件,但是为了维持库的完整性,我们可以根据时钟树的流程自行写一个。
二、使用HSI
当 HSE 直接或者间接(HSE 经过 PLL 倍频)的作为系统时钟的时候,如果 HSE 发生故障,不仅 HSE 会被关闭,连 PLL 也会被关闭,这个时候系统会自动切换 HSI 作为系统时钟,此时 SYSCLK=HSI=16M,如果没有开启 CSS 和 CSS 中断的话,那么整个系统就只能在低速率运行,这是系统跟瘫痪没什么两样。
如果开启了 CSS 功能的话,那么可以当 HSE 故障时,在 CSS 中断里面采取补救措施,使用 HSI,重新设置系统频率为 180M,让系统恢复正常使用。但这只是权宜之计,并非万全之策,最好的方法还是要采取相应的补救措施并报警,然后修复 HSE。临时使用 HSI 只是为了把损失降低到最小,毕竟 HSI 较于 HSE 精度还是要低点。
F103 系列中,使用 HSI 最大只能把系统设置为 64M,并不能跟使用 HSE 一样把系统时钟设置为 72M,究其原因是 HSI 在进入 PLL 倍频的时候必须 2 分频,导致 PLL 倍频因子调到最大也只能到 64M,而 HSE 进入 PLL 倍频的时候则不用 2 分频。
在 F429 中,无论是使用 HSI 还是 HSE 都可以把系统时钟设置为 180M,因为 HSE 或 者 HSI 在进入 PLL 倍频的时候都会被分频为 1M 之后再倍频。还有一种情况是,有些用户不想用 HSE,想用 HSI,但是又不知道怎么用 HSI 来设置
系统时钟,因为调用库函数都是使用 HSE,下面我们给出个使用 HSI 配置系统时钟例子,起个抛砖引玉的作用。
三、代码编写
代码如下(示例):
/* 2 * m: VCO 输入时钟 分频因子,取值 2~63 3 * n: VCO 输出时钟 倍频因子,取值 192~432 4 * p: SYSCLK 时钟分频因子 ,取值 2,4,6,8 5 * q: OTG FS,SDIO,RNG 时钟分频因子,取值 4~15 6 * 函数调用举例,使用 HSE 设置时钟 7 * SYSCLK=HCLK=180M,PCLK2=HCLK/2=90M,PCLK1=HCLK/4=45M 8 * HSE_SetSysClock(25, 360, 2, 7); 9 * HSE 作为时钟来源,经过 PLL 倍频作为系统时钟,这是通常的做法 10 11 * 系统时钟超频到 216M 爽一下 12 * HSE_SetSysClock(25, 432, 2, 9); 13 */ 14 void HSE_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q) 15 { 16 __IO uint32_t HSEStartUpStatus = 0; 17 18 // 使能 HSE,开启外部晶振,野火 F429 使用 HSE=25M 19 RCC_HSEConfig(RCC_HSE_ON); 20 21 // 等待 HSE 启动稳定 22 HSEStartUpStatus = RCC_WaitForHSEStartUp(); 23 24 if (HSEStartUpStatus == SUCCESS) { 25 // 调压器电压输出级别配置为 1,以便在器件为最大频率 26 // 工作时使性能和功耗实现平衡 27 RCC->APB1ENR |= RCC_APB1ENR_PWREN; 28 PWR->CR |= PWR_CR_VOS; 29 30 // HCLK = SYSCLK / 1 31 RCC_HCLKConfig(RCC_SYSCLK_Div1); 32 33 // PCLK2 = HCLK / 2 34 RCC_PCLK2Config(RCC_HCLK_Div2); 35 36 // PCLK1 = HCLK / 4 37 RCC_PCLK1Config(RCC_HCLK_Div4); 38 39 // 如果要超频就得在这里下手啦 40 // 设置 PLL 来源时钟,设置 VCO 分频因子 m,设置 VCO 倍频因子 n, 41 // 设置系统时钟分频因子 p,设置 OTG FS,SDIO,RNG 分频因子 q 42 RCC_PLLConfig(RCC_PLLSource_HSE, m, n, p, q); 43 44 // 使能 PLL 45 RCC_PLLCmd(ENABLE); 46 47 // 等待 PLL 稳定 48 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { 49 } 50 51 /*-----------------------------------------------------*/ 52 //开启 OVER-RIDE 模式,以能达到更高频率 53 PWR->CR |= PWR_CR_ODEN; 54 while ((PWR->CSR & PWR_CSR_ODRDY) == 0) { 55 } 56 PWR->CR |= PWR_CR_ODSWEN; 57 while ((PWR->CSR & PWR_CSR_ODSWRDY) == 0) { 58 } 59 // 配置 FLASH 预取指,指令缓存,数据缓存和等待状态 60 FLASH->ACR = FLASH_ACR_PRFTEN 61 | FLASH_ACR_ICEN 62 | FLASH_ACR_DCEN 63 | FLASH_ACR_LATENCY_5WS; 64 /*-----------------------------------------------------*/ 65 66 // 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK 67 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 68 69 // 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟 70 while (RCC_GetSYSCLKSource() != 0x08) { 71 } 72 } else { 73 // HSE 启动出错处理 74 75 while (1) { 76 } 77 } 78 }
形参说明:
HSI 为 16M,参数 m 我们一般也设置为 16,所以我们需要修改系统时钟的时候只需要修改参数 n 和 p 即可,SYSCLK=PLLCLK=HSI/m*n/p。
函数调用举例:HSI_SetSysClock(16, 360, 2, 7) 把系统时钟设置为 180M,这个跟库里面的系统时钟配置是一样的。HSI_SetSysClock(16, 432, 2, 9)把系统时钟设置为 216M,这个是超频,要慎用。
总结
时钟很关键,他是各个设备的生命线,一旦时钟没有正确配置,那么基于时钟的所有外设都会出问题。以后经常用经常配置就熟悉了。