嵌入式开发学习之--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,这个是超频,要慎用。


总结

  时钟很关键,他是各个设备的生命线,一旦时钟没有正确配置,那么基于时钟的所有外设都会出问题。以后经常用经常配置就熟悉了。

### 汽车电子嵌入式开发学习资源与入门方法 #### 一、学习路径概述 对于零基础的小白来说,进入汽车电子嵌入式开发领域需要从基础知识入手并逐步深入。这不仅涉及到软件编程技能,还涵盖了硬件知识以及系统设计能力。建议按照以下顺序展开学习: 1. **掌握基本的编程语言** C语言是嵌入式开发的核心语言之一,在汽车电子领域尤为重要。推荐阅读《C Primer Plus》[^1]来夯实语法基础。 2. **理解微控制器(MCU)** STM32系列MCU因其广泛的应用场景成为初学者的理想选择。可以通过参考书籍如《零死角玩转STM32—F103霸道》[^2]或者官方文档《STM32F10x-中文参考手册》进行理论与实践相结合的学习。 3. **熟悉嵌入式系统的特性** 嵌入式系统具有低功耗、高可靠性等特点,需特别关注其运行环境下的特殊需求。例如,《嵌入式系统 硬件软件及软硬件协同》提供了关于如何构建高效能嵌入式架构的具体指导[^3]。 4. **探索AUTOSAR框架及相关标准** AUTOSAR(Automotive Open System Architecture)已成为现代车辆控制系统的重要组成部分。针对此方向可查阅由伍德雁主编的基础教材[^4],它能够提供有关AUTOSAR多核操作系统初步认识的内容。 #### 二、具体实施步骤中的注意事项 - 在实际动手过程中遇到困难时不要气馁,积极寻求社区支持并与同行交流经验是非常有益的做法。 - 实践环节非常重要,尝试完成一些小型项目比如利用STM32f103ZE制作简单的LED流水灯控制程序可以帮助巩固所学知识点。 ```c // 示例代码:使用GPIO口驱动单片机上的LED闪烁 #include "stm32f1xx_hal.h" int main(void){ HAL_Init(); // 初始化HAL库 __HAL_RCC_GPIOA_CLK_ENABLE(); // 开启GPIOA时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); while (1){ HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); HAL_Delay(500); // 设置延迟时间为500ms } } ``` 上述代码展示了如何配置一个通用输入输出端口(Pin),并通过循环改变该pin的状态从而点亮熄灭连接在其上的发光二极管(LED)--- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值