13.1 RCC 主要作用—时钟部分:
设置系统时钟 SYSCLK、设置 AHB 分频因子(决定 HCLK 等于多少) 、 设置 APB2 分频因子(决定 PCLK2 等于多少)、设置 APB1 分频因子(决定 PCLK1 等于多少)、设置各个外设的分频因子;控制 AHB、 APB2 和 APB1 这三条总线时钟的开启、控制每个外设的时钟的开启。对于 SYSCLK、 HCLK、 PCLK2、 PCLK1 这四个时钟的配置一般是: HCLK =SYSCLK=PLLCLK = 180M,PCLK1=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M。这个时钟配置也是库函数的标准配置,我们用的最多的就是这个。
13.2 RCC 框图剖析—时钟树:
时钟树单纯讲理论的话会比较枯燥,如果选取一条主线,并辅以代码,先主后次讲解的话会很容易,而且记忆还更深刻。我们这里选取库函数时钟系统时钟函数:SetSysClock(); 以这个函数的编写流程来讲解时钟树,这个函数也是我们用库的时候默认的系统时钟设置函数。该函数的功能是利用 HSE 把时钟设置为: HCLK = SYSCLK=PLLCLK= 180M, PCLK1=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M 下面我们就以这个代码的流程为主线, 来分析时钟树,对应的是图中的黄色部分,代码流程在时钟树中以数字的大小顺序标识。
13.2.1 系统时钟:
1. ①HSE 高速外部时钟信号:
HSE 是高速的外部时钟信号,可以由有源晶振或者无源晶振提供,频率从 4-26MHZ不等。当使用有源晶振时,时钟从 OSC_IN 引脚进入, OSC_OUT 引脚悬空,当选用无源晶振时,时钟从 OSC_IN 和 OSC_OUT 进入,并且要配谐振电容。 HSE 我们使用 25M 的无源晶振。 如果我们使用 HSE 或者 HSE 经过 PLL 倍频之后的时钟作为系统时钟 SYSCLK,当 HSE 故障时候,不仅 HSE 会被关闭, PLL 也会被关闭,此时高速的内部时钟时钟信号HSI 会作为备用的系统时钟,直到 HSE 恢复正常, HSI=16M。
2. ②锁相环 PLL:
PLL 的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。 PLL 有两个,一个是主 PLL,另外一个是专用的 PLLI2S,他们均由 HSE 或者 HSI 提供时钟输入信号。
主 PLL 有两路的时钟输出,第一个输出时钟 PLLCLK 用于系统时钟, F429 里面最高是 180M,第二个输出用于 USB OTG FS 的时钟(48M)、 RNG 和 SDIO 时钟(《=48M)。专用的 PLLI2S 用于生成精确时钟,给 I2S 提供时钟。
HSE 或者 HSI 经过 PLL 时钟输入分频因子 M(2~63)分频后,成为 VCO 的时钟输入,VCO 的时钟必须在 1~2M 之间, 我们选择 HSE=25M 作为 PLL 的时钟输入, M 设置为 25,那么 VCO 输入时钟就等于 1M。
VCO 输入时钟经过 VCO 倍频因子 N 倍频之后,成为 VCO 时钟输出, VCO 时钟必须在 192~432M 之间。我们配置 N 为 360,则 VCO 的输出时钟等于 360M。如果要把系统时钟超频,就得在 VCO 倍频系数 N 这里做手脚。 PLLCLK_OUTMAX =VCOCLK_OUTMAX/P_MIN = 432/2=216M,即 F429 最高可超频到 216M。
VCO 输出时钟之后有三个分频因子: PLLCLK 分频因子 p, USB OTG FS/RNG/SDIO时钟分频因子 Q,分频因子 R(F446 才有,F429 没有)。 p 可以取值 2、 4、 6、 8,我们配置为 2,则得到 PLLCLK=180M。 Q 可以取值 4~15,但是 USB OTG FS 必须使用 ,Q=VCO 输出时钟 360/48=7.5,出现了小数这明显是错误,权衡之策是是重新配置 VCO 的倍频因子 N=336,VCOCLK=1M*336=336M, PLLCLK=VCOCLK/2=168M,USBCLK=336/7=48M,细心的读者应该发现了,在使用 USB 的时候, PLLCLK 被降低到了 168M,不能使用 180M,这实乃 ST 的一个奇葩设计。有关 PLL 的配置有一个专门的RCC PLL 配置寄存器 RCC_PLLCFGR,具体描述看手册即可。
PLL 的时钟配置经过,稍微整理下可由如下公式表达:
VCOCLK_IN = PLLCLK_IN / M = HSE / 25 = 1M
VCOCLK_OUT = VCOCLK_IN * N = 1M * 360 = 360M
PLLCLK_OUT=VCOCLK_OUT/P=360/2=180M
USBCLK = VCOCLK_OUT/Q=360/7=51.7。暂时这样配置,到真正使用 USB 的时候会重新配置。
3. ③系统时钟 SYSCLK:
系统时钟来源可以是: HSI、 PLLCLK、 HSE,具体的由时钟配置寄存器 RCC_CFGR的 SW 位配置。我们这里设置系统时钟: SYSCLK = PLLCLK = 180M。 如果系统时钟是由HSE 经过 PLL 倍频之后的 PLLCLK 得到,当 HSE 出现故障的时候,系统时钟会切换为HSI=16M,直到 HSE 恢复正常为止。
4. ④AHB 总线时钟 HCLK:
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 APB 总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器RCC_CFGR 的 HPRE 位设置。片上大部分外设的时钟都是经过 HCLK 分频得到,至于 AHB总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB 的时钟即可。 我们这里设置为 1 分频,即 HCLK=SYSCLK=180M。
5. ⑤APB2 总线时钟 HCLK2:
APB2 总线时钟 PCLK2 由 HCLK 经过高速 APB2 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE2 位设置。 HCLK2 属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、 USART1、 SPI1等。至于 APB2 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB2 的时钟即可。我们这里设置为 2 分频,即 PCLK2 =HCLK /2= 90M。
6. ⑥APB1 总线时钟 HCLK1:
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE1 位设置。HCLK1 属于低速的总线时钟,最高为 45M,片上低速的外设就挂载到这条总线上,比如
USART2/3/4/5、 SPI2/3, I2C1/2 等。至于 APB1 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB1 的时钟即可。我们这里设置为 4 分频,即 PCLK1 = HCLK/4 = 45M。
7. 设置系统时钟库函数:
上面的 6 个步骤对应的设置系统时钟库函数如下,为了方便阅读,已经把跟 429 不相关的代码删掉,把英文注释翻译成了中文,并把代码标上了序号,总共 6 个步骤。该函数是直接操作寄存器的,有关寄存器部分请参考数据手册的 RCC 的寄存器描述部分。
13.2.2 其他时钟:
通过对系统时钟设置的讲解,整个时钟树我们已经把握的有六七成,剩下的时钟部分我们讲解几个重要的。
1. A、 RTC 时钟:
RTCCLK 时钟源可以是 HSE 1 MHz(HSE 由一个可编程的预分频器分频)、 LSE 或者 LSI 时钟。选择方式是编程 RCC 备份域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC 时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只能通过复位备份域的方式修改。 我们通常的做法是由 LSE 给 RTC 提供时钟,大小为 32.768KHZ。 LSE由外接的晶体谐振器产生,所配的谐振电容精度要求高,不然很容易不起震。
2. B、独立看门狗时钟:
独立看门狗时钟由内部的低速时钟 LSI 提供,大小为 32KHZ。
3. C、 I2S 时钟:
I2S 时钟可由外部的时钟引脚 I2S_CKIN 输入,也可由专用的 PLLI2SCLK 提供,具体的由 RCC 时钟配置寄存器 (RCC_CFGR)的 I2SSCR 位配置。我们在使用 I2S 外设驱动W8978 的时候,使用的时钟是 PLLI2SCLK,这样就可以省掉一个有源晶振。
4. D、 PHY 以太网时钟:
F429 要想实现以太网功能,除了有本身内置的 MAC 之外,还需要外接一个 PHY 芯片,常见的 PHY 芯片有 DP83848 和 LAN8720,其中 DP83848 支持 MII 和 RMII 接口,LAN8720 只支持 RMII 接口。 野火 F429 开发板用的是 RMII 接口,选择的 PHY 芯片是LAB8720。使用 RMII 接口的好处是使用的 IO 减少了一半,速度还是跟 MII 接口一样。当使用 RMII 接口时, PHY 芯片只需输出一路时钟给 MCU 即可,如果是 MII 接口, PHY 芯片则需要提供两路时钟给 MCU。
5. E、 USB PHY 时钟:
F429 的 USB 没有集成 PHY,要想实现 USB 高速传输的话,必须外置 USB PHY 芯片,常用的芯片是 USB3300。当外接 USB PHY 芯片时, PHY 芯片需要给 MCU 提供一个时钟。外扩 USB3300 会占用非常多的 IO,跟 SDRAM 和 RGB888 的 IO 会复用的很厉害,鉴于 USB 高速传输用的比较少, 野火 429 就没有外扩这个芯片。
6. F、 MCO 时钟输出:
MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,主要作用是可以对外提供时钟, 相当于一个有源晶振。 F429 中有两个 MCO,由 PA8/PC9 复用所得。MCO1 所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的 MCO1PRE[2:0] 和MCO1[1:0]位选择。 MCO2 所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的MCO2PRE[2:0] 和 MCO2 位选择。
13.3 配置系统时钟实验:
13.3.1 使用 HSE:
一般情况下,我们都是使用 HSE,然后 HSE 经过 PLL 倍频之后作为系统时钟。 F429系统时钟最高为 180M,这个是官方推荐的最高的稳定时钟,如果你想铤而走险,也可以超频,超频最高能到 216M。
如果我们使用库函数编程,当程序来到 main 函数之前,启动文件:startup_stm32f429_439xx.s 已经调用 SystemInit()函数把系统时钟初始化成 180MHZ,SystemInit()在库文件: system_stm32f4xx.c 中定义。如果我们想把系统时钟设置低一点或者超频的话,可以修改底层的库文件,但是为了维持库的完整性,我们可以根据时钟树的流程自行写一个。
13.3.2 使用 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 配置系统时钟例子,起个抛砖引玉的作用。
13.3.3 硬件设计
1、 RCC
2、 LED 一个
RCC 是单片机内部资源,不需要外部电路。通过 LED 闪烁的频率来直观的判断不同系统时钟频率对软件延时的效果。
13.3.4 软件设计:
我们编写两个 RCC 驱动文件, bsp_clkconfig.h 和 bsp_clkconfig.c,用来存放 RCC 系统时钟配置函数。
1. 编程要点:
1、开启 HSE/HSI , 并等待 HSE/HSI 稳定
2、设置 AHB、 APB2、 APB1 的预分频因子
3、设置 PLL 的时钟来源, 设置 VCO 输入时钟 分频因子 PLL_M,设置 VCO 输出时钟倍频因子 PLL_N,设置 PLLCLK 时钟分频因子 PLL_P,设置 OTG FS,SDIO,RNG时钟分频因子 PLL_Q
4、开启 PLL,并等待 PLL 稳定
5、把 PLLCK 切换为系统时钟 SYSCLK
6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
2. 代码分析:
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。
使用 HSE 配置系统时钟
代码 14 HSE 作为系统时钟来源
:
形参形参说明取值范围
mVCO 输入时钟 分频因子2~63
nVCO 输出时钟 倍频因子192~432
pPLLCLK 时钟分频因子2/4/6/8
qOTG FS,SDIO,RNG 时钟分频因子4~15
HSE 我们使用 25M,参数 m 我们一般也设置为 25,所以我们需要修改系统时钟的时候只需要修改参数 n 和 p 即可,SYSCLK=PLLCLK=HSE/m*n/p。函数调用举例: HSE_SetSysClock(25, 360, 2, 7) 把系统时钟设置为 180M,这个跟库里面的系统时钟配置是一样的。 HSE_SetSysClock(25, 432, 2, 9)把系统时钟设置为 216M,这个是超频,要慎用。
使用 HSI 配置系统时钟
形参形参说明取值范围
mVCO 输入时钟 分频因子2~63
nVCO 输出时钟 倍频因子192~432
pPLLCLK 时钟分频因子2/4/6/8
qOTG FS,SDIO,RNG 时钟分频因子4~15
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,这个是超频,要慎用。
软件延时
void Delay(__IO uint32_t nCount){for (; nCount != 0; nCount--);} 软件延时函数,使用不同的系统时钟,延时时间不一样,可以通过 LED 闪烁的频率来判断。
MCO 输出
在 F429 中, PA8/PC9 可以复用为 MCO1/2 引脚,对外提供时钟输出,我们也可以用示波器监控该引脚的输出来判断我们的系统时钟是否设置正确。
野火 F429 中 PA8 并没有引出,只引出了 PC9,如果要用示波器监控 MCO,只能用PC9。
代码 16 MCO 输出时钟选择
// MCO1 输出 PLLCLKRCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_1);// MCO1 输出 SYSCLKRCC_MCO2Config(RCC_MCO2Source_SYSCLK, RCC_MCO1Div_1); 我们初始化 MCO 引脚之后,可以直接调用库函数 RCC_MCOxConfig()来选择 MCO 时钟来源,同时还可以分频,这两个参数的取值参考库函数说明即可。
主函数
在主函数中,可以调用 HSE_SetSysClock()或者 HSI_SetSysClock()这两个函数把系统时钟设置成各种常用的时钟,然后通过 MCO 引脚监控,或者通过 LED 闪烁的快慢体验不同的系统时钟对同一个软件延时函数的影响。
13.3.5 下载验证
把编译好的程序下载到开发板,可以看到设置不同的系统时钟时, LED 闪烁的快慢不一样。更精确的数据我们可以用示波器监控 MCO 引脚看到。
13.4 总结:
1、时钟树:
2、HSE时钟:
HSE: High Speed External Clock signal, 即高速的外部时钟。
来源:有源晶振(1-50M)价格贵一般不采用、无源晶振( 4-26M)
控制: RCC_CR 时钟控制寄存器的位16: HSEON控制
3、HSI时钟:
HSI: Low Speed Internal Clock signal, 即高速的内部时钟。
来源:芯片内部,大小为16M,当HSE故障时,系统时钟会自动切换到HSI, 直到HSE启动成功。
控制: RCC_CR 时钟控制寄存器的位0: HSION控制
4、锁相环时钟PLL:
锁相环时钟: PLLCLK
来源: HSI、 HSE。由PLLSRC位配置。
HSE或者HSI先经过一个分频因子M进行分频,然后再经过一个倍频因子N,然后再经过一个分频因子P,最后成为锁相环时钟
PLLCLK = (HSE/M) * N / P = 25/25 * 360 / 2 = 180M
控制: RCC_PLLCFGR :RCC PLL 配置寄存器
PLL48CK: USB_FS、 RANG、 SDIO提供时钟
5、系统时钟:
缩写: SYSCLK,最高为180M, F407最高为168M。
来源: HSI、 HSE, PLLCLK。
控制: RCC_CFGR 时钟配置寄存器的SW位
6、HCLK时钟;
HCLK: AHB高速总线时钟, 最高为180M。为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟( SysTick)、为内核提供时钟( FCLK)。
AHB为advanced high-performance bus。
来源:系统时钟分频得到。
控制: RCC_CFGR 时钟配置寄存器的HPRE位
7、PCLK1时钟:
PCLK1: APB1低速总线时钟,最高为45M。 为APB1总线的外设提供时钟。 2倍频之后则为APB1总线的定时器提供时钟,最大为90M。
来源: HCLK分频得到。
控制: RCC_CFGR 时钟配置寄存器的PPRE1位
8、PCLK2时钟:
PCLK2: APB2高速总线时钟,最高为90M。为APB2总线的外设提供时钟。 2倍频之后则为APB2总线的定时器提供时钟,最大为180M。
来源: HCLK分频得到。
控制: RCC_CFGR 时钟配置寄存器的PPRE2位
9、RTC时钟
RTC:为芯片内部的RTC提供时钟。
来源: HSE_RTC( HSE分频得到)、 LSE(外部32.768KHZ的晶体提供)、 LSI( 32KHZ)。
控制: RCC备份域控制寄存器RCC_BDCR: RTCSEL位控制
独立看门狗时钟: IWDGCLK,由LSI提供
10、其他时钟:
I2S时钟:由外部的引脚I2S_CKIN或者PLLI2SCLK提供。以太网PHY时钟: 429没有集成PHY,只能外接PHY芯片,比如LAN8720,那PHY时钟就由外部的PHY芯片提供,大小为50M。
USB PHY时钟: 429的USB没有集成PHY, 要想实现USB高速传输,只能外接PHY芯片,比如USB33000。那USB PHY时钟就由外部的PHY芯片提供。
11、MCO时钟输出:
MCO:把控制器的时钟通过外部的引脚输出,可以外外部的设备提供时钟。 MCO1为PA8, MCO2为PC9。
控制: RCC_CFGR 时钟配置寄存器的MCOX的PREx位
13.1 RCC 主要作用—时钟部分:
设置系统时钟 SYSCLK、设置 AHB 分频因子(决定 HCLK 等于多少) 、 设置 APB2 分频因子(决定 PCLK2 等于多少)、设置 APB1 分频因子(决定 PCLK1 等于多少)、设置各个外设的分频因子;控制 AHB、 APB2 和 APB1 这三条总线时钟的开启、控制每个外设的时钟的开启。对于 SYSCLK、 HCLK、 PCLK2、 PCLK1 这四个时钟的配置一般是: HCLK =SYSCLK=PLLCLK = 180M,PCLK1=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M。这个时钟配置也是库函数的标准配置,我们用的最多的就是这个。
13.2 RCC 框图剖析—时钟树:
时钟树单纯讲理论的话会比较枯燥,如果选取一条主线,并辅以代码,先主后次讲解的话会很容易,而且记忆还更深刻。我们这里选取库函数时钟系统时钟函数:SetSysClock(); 以这个函数的编写流程来讲解时钟树,这个函数也是我们用库的时候默认的系统时钟设置函数。该函数的功能是利用 HSE 把时钟设置为: HCLK = SYSCLK=PLLCLK= 180M, PCLK1=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M 下面我们就以这个代码的流程为主线, 来分析时钟树,对应的是图中的黄色部分,代码流程在时钟树中以数字的大小顺序标识。
13.2.1 系统时钟:
1. ①HSE 高速外部时钟信号:
HSE 是高速的外部时钟信号,可以由有源晶振或者无源晶振提供,频率从 4-26MHZ不等。当使用有源晶振时,时钟从 OSC_IN 引脚进入, OSC_OUT 引脚悬空,当选用无源晶振时,时钟从 OSC_IN 和 OSC_OUT 进入,并且要配谐振电容。 HSE 我们使用 25M 的无源晶振。 如果我们使用 HSE 或者 HSE 经过 PLL 倍频之后的时钟作为系统时钟 SYSCLK,当 HSE 故障时候,不仅 HSE 会被关闭, PLL 也会被关闭,此时高速的内部时钟时钟信号HSI 会作为备用的系统时钟,直到 HSE 恢复正常, HSI=16M。
2. ②锁相环 PLL:
PLL 的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。 PLL 有两个,一个是主 PLL,另外一个是专用的 PLLI2S,他们均由 HSE 或者 HSI 提供时钟输入信号。
主 PLL 有两路的时钟输出,第一个输出时钟 PLLCLK 用于系统时钟, F429 里面最高是 180M,第二个输出用于 USB OTG FS 的时钟(48M)、 RNG 和 SDIO 时钟(《=48M)。专用的 PLLI2S 用于生成精确时钟,给 I2S 提供时钟。
HSE 或者 HSI 经过 PLL 时钟输入分频因子 M(2~63)分频后,成为 VCO 的时钟输入,VCO 的时钟必须在 1~2M 之间, 我们选择 HSE=25M 作为 PLL 的时钟输入, M 设置为 25,那么 VCO 输入时钟就等于 1M。
VCO 输入时钟经过 VCO 倍频因子 N 倍频之后,成为 VCO 时钟输出, VCO 时钟必须在 192~432M 之间。我们配置 N 为 360,则 VCO 的输出时钟等于 360M。如果要把系统时钟超频,就得在 VCO 倍频系数 N 这里做手脚。 PLLCLK_OUTMAX =VCOCLK_OUTMAX/P_MIN = 432/2=216M,即 F429 最高可超频到 216M。
VCO 输出时钟之后有三个分频因子: PLLCLK 分频因子 p, USB OTG FS/RNG/SDIO时钟分频因子 Q,分频因子 R(F446 才有,F429 没有)。 p 可以取值 2、 4、 6、 8,我们配置为 2,则得到 PLLCLK=180M。 Q 可以取值 4~15,但是 USB OTG FS 必须使用 ,Q=VCO 输出时钟 360/48=7.5,出现了小数这明显是错误,权衡之策是是重新配置 VCO 的倍频因子 N=336,VCOCLK=1M*336=336M, PLLCLK=VCOCLK/2=168M,USBCLK=336/7=48M,细心的读者应该发现了,在使用 USB 的时候, PLLCLK 被降低到了 168M,不能使用 180M,这实乃 ST 的一个奇葩设计。有关 PLL 的配置有一个专门的RCC PLL 配置寄存器 RCC_PLLCFGR,具体描述看手册即可。
PLL 的时钟配置经过,稍微整理下可由如下公式表达:
VCOCLK_IN = PLLCLK_IN / M = HSE / 25 = 1M
VCOCLK_OUT = VCOCLK_IN * N = 1M * 360 = 360M
PLLCLK_OUT=VCOCLK_OUT/P=360/2=180M
USBCLK = VCOCLK_OUT/Q=360/7=51.7。暂时这样配置,到真正使用 USB 的时候会重新配置。
3. ③系统时钟 SYSCLK:
系统时钟来源可以是: HSI、 PLLCLK、 HSE,具体的由时钟配置寄存器 RCC_CFGR的 SW 位配置。我们这里设置系统时钟: SYSCLK = PLLCLK = 180M。 如果系统时钟是由HSE 经过 PLL 倍频之后的 PLLCLK 得到,当 HSE 出现故障的时候,系统时钟会切换为HSI=16M,直到 HSE 恢复正常为止。
4. ④AHB 总线时钟 HCLK:
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 APB 总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器RCC_CFGR 的 HPRE 位设置。片上大部分外设的时钟都是经过 HCLK 分频得到,至于 AHB总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB 的时钟即可。 我们这里设置为 1 分频,即 HCLK=SYSCLK=180M。
5. ⑤APB2 总线时钟 HCLK2:
APB2 总线时钟 PCLK2 由 HCLK 经过高速 APB2 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE2 位设置。 HCLK2 属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、 USART1、 SPI1等。至于 APB2 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB2 的时钟即可。我们这里设置为 2 分频,即 PCLK2 =HCLK /2= 90M。
6. ⑥APB1 总线时钟 HCLK1:
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE1 位设置。HCLK1 属于低速的总线时钟,最高为 45M,片上低速的外设就挂载到这条总线上,比如
USART2/3/4/5、 SPI2/3, I2C1/2 等。至于 APB1 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB1 的时钟即可。我们这里设置为 4 分频,即 PCLK1 = HCLK/4 = 45M。
7. 设置系统时钟库函数:
上面的 6 个步骤对应的设置系统时钟库函数如下,为了方便阅读,已经把跟 429 不相关的代码删掉,把英文注释翻译成了中文,并把代码标上了序号,总共 6 个步骤。该函数是直接操作寄存器的,有关寄存器部分请参考数据手册的 RCC 的寄存器描述部分。
13.2.2 其他时钟:
通过对系统时钟设置的讲解,整个时钟树我们已经把握的有六七成,剩下的时钟部分我们讲解几个重要的。
1. A、 RTC 时钟:
RTCCLK 时钟源可以是 HSE 1 MHz(HSE 由一个可编程的预分频器分频)、 LSE 或者 LSI 时钟。选择方式是编程 RCC 备份域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC 时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只能通过复位备份域的方式修改。 我们通常的做法是由 LSE 给 RTC 提供时钟,大小为 32.768KHZ。 LSE由外接的晶体谐振器产生,所配的谐振电容精度要求高,不然很容易不起震。
2. B、独立看门狗时钟:
独立看门狗时钟由内部的低速时钟 LSI 提供,大小为 32KHZ。
3. C、 I2S 时钟:
I2S 时钟可由外部的时钟引脚 I2S_CKIN 输入,也可由专用的 PLLI2SCLK 提供,具体的由 RCC 时钟配置寄存器 (RCC_CFGR)的 I2SSCR 位配置。我们在使用 I2S 外设驱动W8978 的时候,使用的时钟是 PLLI2SCLK,这样就可以省掉一个有源晶振。
4. D、 PHY 以太网时钟:
F429 要想实现以太网功能,除了有本身内置的 MAC 之外,还需要外接一个 PHY 芯片,常见的 PHY 芯片有 DP83848 和 LAN8720,其中 DP83848 支持 MII 和 RMII 接口,LAN8720 只支持 RMII 接口。 野火 F429 开发板用的是 RMII 接口,选择的 PHY 芯片是LAB8720。使用 RMII 接口的好处是使用的 IO 减少了一半,速度还是跟 MII 接口一样。当使用 RMII 接口时, PHY 芯片只需输出一路时钟给 MCU 即可,如果是 MII 接口, PHY 芯片则需要提供两路时钟给 MCU。
5. E、 USB PHY 时钟:
F429 的 USB 没有集成 PHY,要想实现 USB 高速传输的话,必须外置 USB PHY 芯片,常用的芯片是 USB3300。当外接 USB PHY 芯片时, PHY 芯片需要给 MCU 提供一个时钟。外扩 USB3300 会占用非常多的 IO,跟 SDRAM 和 RGB888 的 IO 会复用的很厉害,鉴于 USB 高速传输用的比较少, 野火 429 就没有外扩这个芯片。
6. F、 MCO 时钟输出:
MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,主要作用是可以对外提供时钟, 相当于一个有源晶振。 F429 中有两个 MCO,由 PA8/PC9 复用所得。MCO1 所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的 MCO1PRE[2:0] 和MCO1[1:0]位选择。 MCO2 所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的MCO2PRE[2:0] 和 MCO2 位选择。
13.3 配置系统时钟实验:
13.3.1 使用 HSE:
一般情况下,我们都是使用 HSE,然后 HSE 经过 PLL 倍频之后作为系统时钟。 F429系统时钟最高为 180M,这个是官方推荐的最高的稳定时钟,如果你想铤而走险,也可以超频,超频最高能到 216M。
如果我们使用库函数编程,当程序来到 main 函数之前,启动文件:startup_stm32f429_439xx.s 已经调用 SystemInit()函数把系统时钟初始化成 180MHZ,SystemInit()在库文件: system_stm32f4xx.c 中定义。如果我们想把系统时钟设置低一点或者超频的话,可以修改底层的库文件,但是为了维持库的完整性,我们可以根据时钟树的流程自行写一个。
13.3.2 使用 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 配置系统时钟例子,起个抛砖引玉的作用。
13.3.3 硬件设计
1、 RCC
2、 LED 一个
RCC 是单片机内部资源,不需要外部电路。通过 LED 闪烁的频率来直观的判断不同系统时钟频率对软件延时的效果。
13.3.4 软件设计:
我们编写两个 RCC 驱动文件, bsp_clkconfig.h 和 bsp_clkconfig.c,用来存放 RCC 系统时钟配置函数。
1. 编程要点:
1、开启 HSE/HSI , 并等待 HSE/HSI 稳定
2、设置 AHB、 APB2、 APB1 的预分频因子
3、设置 PLL 的时钟来源, 设置 VCO 输入时钟 分频因子 PLL_M,设置 VCO 输出时钟倍频因子 PLL_N,设置 PLLCLK 时钟分频因子 PLL_P,设置 OTG FS,SDIO,RNG时钟分频因子 PLL_Q
4、开启 PLL,并等待 PLL 稳定
5、把 PLLCK 切换为系统时钟 SYSCLK
6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
2. 代码分析:
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。
使用 HSE 配置系统时钟
代码 14 HSE 作为系统时钟来源
:
形参形参说明取值范围
mVCO 输入时钟 分频因子2~63
nVCO 输出时钟 倍频因子192~432
pPLLCLK 时钟分频因子2/4/6/8
qOTG FS,SDIO,RNG 时钟分频因子4~15
HSE 我们使用 25M,参数 m 我们一般也设置为 25,所以我们需要修改系统时钟的时候只需要修改参数 n 和 p 即可,SYSCLK=PLLCLK=HSE/m*n/p。函数调用举例: HSE_SetSysClock(25, 360, 2, 7) 把系统时钟设置为 180M,这个跟库里面的系统时钟配置是一样的。 HSE_SetSysClock(25, 432, 2, 9)把系统时钟设置为 216M,这个是超频,要慎用。
使用 HSI 配置系统时钟
形参形参说明取值范围
mVCO 输入时钟 分频因子2~63
nVCO 输出时钟 倍频因子192~432
pPLLCLK 时钟分频因子2/4/6/8
qOTG FS,SDIO,RNG 时钟分频因子4~15
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,这个是超频,要慎用。
软件延时
void Delay(__IO uint32_t nCount){for (; nCount != 0; nCount--);} 软件延时函数,使用不同的系统时钟,延时时间不一样,可以通过 LED 闪烁的频率来判断。
MCO 输出
在 F429 中, PA8/PC9 可以复用为 MCO1/2 引脚,对外提供时钟输出,我们也可以用示波器监控该引脚的输出来判断我们的系统时钟是否设置正确。
野火 F429 中 PA8 并没有引出,只引出了 PC9,如果要用示波器监控 MCO,只能用PC9。
代码 16 MCO 输出时钟选择
// MCO1 输出 PLLCLKRCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_1);// MCO1 输出 SYSCLKRCC_MCO2Config(RCC_MCO2Source_SYSCLK, RCC_MCO1Div_1); 我们初始化 MCO 引脚之后,可以直接调用库函数 RCC_MCOxConfig()来选择 MCO 时钟来源,同时还可以分频,这两个参数的取值参考库函数说明即可。
主函数
在主函数中,可以调用 HSE_SetSysClock()或者 HSI_SetSysClock()这两个函数把系统时钟设置成各种常用的时钟,然后通过 MCO 引脚监控,或者通过 LED 闪烁的快慢体验不同的系统时钟对同一个软件延时函数的影响。
13.3.5 下载验证
把编译好的程序下载到开发板,可以看到设置不同的系统时钟时, LED 闪烁的快慢不一样。更精确的数据我们可以用示波器监控 MCO 引脚看到。
13.4 总结:
1、时钟树:
2、HSE时钟:
HSE: High Speed External Clock signal, 即高速的外部时钟。
来源:有源晶振(1-50M)价格贵一般不采用、无源晶振( 4-26M)
控制: RCC_CR 时钟控制寄存器的位16: HSEON控制
3、HSI时钟:
HSI: Low Speed Internal Clock signal, 即高速的内部时钟。
来源:芯片内部,大小为16M,当HSE故障时,系统时钟会自动切换到HSI, 直到HSE启动成功。
控制: RCC_CR 时钟控制寄存器的位0: HSION控制
4、锁相环时钟PLL:
锁相环时钟: PLLCLK
来源: HSI、 HSE。由PLLSRC位配置。
HSE或者HSI先经过一个分频因子M进行分频,然后再经过一个倍频因子N,然后再经过一个分频因子P,最后成为锁相环时钟
PLLCLK = (HSE/M) * N / P = 25/25 * 360 / 2 = 180M
控制: RCC_PLLCFGR :RCC PLL 配置寄存器
PLL48CK: USB_FS、 RANG、 SDIO提供时钟
5、系统时钟:
缩写: SYSCLK,最高为180M, F407最高为168M。
来源: HSI、 HSE, PLLCLK。
控制: RCC_CFGR 时钟配置寄存器的SW位
6、HCLK时钟;
HCLK: AHB高速总线时钟, 最高为180M。为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟( SysTick)、为内核提供时钟( FCLK)。
AHB为advanced high-performance bus。
来源:系统时钟分频得到。
控制: RCC_CFGR 时钟配置寄存器的HPRE位
7、PCLK1时钟:
PCLK1: APB1低速总线时钟,最高为45M。 为APB1总线的外设提供时钟。 2倍频之后则为APB1总线的定时器提供时钟,最大为90M。
来源: HCLK分频得到。
控制: RCC_CFGR 时钟配置寄存器的PPRE1位
8、PCLK2时钟:
PCLK2: APB2高速总线时钟,最高为90M。为APB2总线的外设提供时钟。 2倍频之后则为APB2总线的定时器提供时钟,最大为180M。
来源: HCLK分频得到。
控制: RCC_CFGR 时钟配置寄存器的PPRE2位
9、RTC时钟
RTC:为芯片内部的RTC提供时钟。
来源: HSE_RTC( HSE分频得到)、 LSE(外部32.768KHZ的晶体提供)、 LSI( 32KHZ)。
控制: RCC备份域控制寄存器RCC_BDCR: RTCSEL位控制
独立看门狗时钟: IWDGCLK,由LSI提供
10、其他时钟:
I2S时钟:由外部的引脚I2S_CKIN或者PLLI2SCLK提供。以太网PHY时钟: 429没有集成PHY,只能外接PHY芯片,比如LAN8720,那PHY时钟就由外部的PHY芯片提供,大小为50M。
USB PHY时钟: 429的USB没有集成PHY, 要想实现USB高速传输,只能外接PHY芯片,比如USB33000。那USB PHY时钟就由外部的PHY芯片提供。
11、MCO时钟输出:
MCO:把控制器的时钟通过外部的引脚输出,可以外外部的设备提供时钟。 MCO1为PA8, MCO2为PC9。
控制: RCC_CFGR 时钟配置寄存器的MCOX的PREx位
举报