目录
时钟控制单元(CCTL)
时钟控制单元提供了一系列频率的时钟功能,包括一个内部16M RC振荡器时钟(IRC16M)、一
个内部48M RC 振荡器时钟(IRC48M)、一个外部高速晶体振荡器时钟(HXTAL)、一个内部32K
RC振荡器时钟(IRC32K)、一个外部低速晶体振荡器时钟(LXTAL)、三个锁相环(PLL)、一个
HXTAL时钟监视器、时钟预分频器、时钟多路复用器和时钟门控电路。这几个时钟源的具体用途是什么呢?看下图的时钟树配置。
1. 32K RC震荡时钟(IRC32K):
IRC32K内部RC振荡器时钟担当一个低功耗时钟源的角色,它的时钟频率大约32 kHz,为独立
看门狗和实时时钟电路提供时钟。
2. 内部 16M RC 振荡器时钟(IRC16M)
内部16MHz RC振荡器时钟,简称IRC16M时钟,拥有16MHz的固定频率,设备上电后CPU默
认选择其做为系统时钟源。 IRC16M RC振荡器能够在不需要任何外部器件的条件下为用户提
供更低成本类型的时钟源。
3. 内部 48M RC 振荡器时钟(IRC48M)
内 部 48MHz RC 振 荡 器 时 钟 , 简 称 IRC48M 时 钟 , 拥 有 48MHz 的 固 定 频 率 , 当 使 用
USBFS/USBHS/TRNG/SDIO模块时, IRC48M振荡器在不需要任何外部器件的条件下为用户
提供了一种成本更低的时钟源选择。
4. 外部低速晶体振荡器时钟(LXTAL)
LXTAL是一个频率为32.768kHz的外部低速晶体或陶瓷谐振器。它为实时时钟电路提供一个低
功耗且高精准的时钟源。
5. 外部高速晶体振荡器时钟(HXTAL)
4到32MHz的外部高速晶体振荡器可为系统时钟提供更为精确时钟源。带有特定频率的晶体必
须靠近两个HXTAL的引脚连接。和晶体连接的外部电阻和电容必须根据所选择的振荡器来调整。
6. 锁相环(PLL)
存在三个内部锁相环, PLL、 PLLI2S和PLLSAI。 PLLP时钟可做为系统时钟(不超过
200MHz) ,PLLQ时钟可以做为USBFS/USBHS/TRNG/SDIO模块的时钟源。 PLLI2S时钟可以
做为I2S模块的时钟源。 PLLSAI可以做为CK48M或TLI模块的时钟源。
总结一下,这几个时钟源有不同的用途:
1. 内部或外部32K时钟主要用于RTC和看门狗的时钟。
2. 内部48M时钟主要用于USBFS/USBHS/TRNG/SDIO的时钟。
3. 内部16M时钟上电后作为系统默认时钟源,若没有使用外部时钟,则可以使用此时钟。
4. 外部时钟HXTAL提供根据接入的晶振提供4到32MHz的时钟信号。
由时钟树可知,AHB、 APB和Cortex®-M4时钟都源自系统时钟(CK_SYS),系统时钟的时钟源可以选择IRC16M、HXTAL或PLL。系统时钟的最大运行时钟频率可以达到200MHz。
另外,时钟树中还可以看到AHB、APB1和APB2总线的时钟需要配置。AHB和APB到底是什么?
AHB(Advanced High Performance Bus):高级性能总线,AHB用于高性能、高时钟频率的系统结构,典型的应用如ARM核与系统内部的高速RAM、NAND FLASH、DMA、Bridge的连接。
APB (Advanced Peripheral Bus):高级外设总线,APB用于连接外部设备,对性能要求不高,而考虑低功耗问题。
从时钟树可以看到,CK_AHB由CK_SYS时钟分频而来,最大频率可以等于CK_SYS。
CK_AHB出来后,给到
1. HCLK AHB总线的时钟信号
2. CK_CST SysTick系统滴答定时器的时钟(分频8)
3. 分频后给到CK_APB1,也就是PCLK1
4. 分频后给到CK_APB2,也就是PCLK2
5. 分频后给到ADC
GD32F405时钟配置代码解析
GD32F405在启动过程的时钟配置在SystemIni函数(system_gd32f4xx.c),SystemInit函数会对MCU的复位和时钟单元RCU进行配置,复位后调用system_clock_config()。可以看到根据定义的宏选择不同的时钟配置函数,一下是官方预定义的一些配置。主要是时钟源和频率的组合。因此,如果想在MCU启动过程中完成系统时钟的配置,只需要修改相关宏定义即可。
static void system_clock_config(void)
{
#ifdef __SYSTEM_CLOCK_IRC16M
system_clock_16m_irc16m();
#elif defined (__SYSTEM_CLOCK_HXTAL)
system_clock_hxtal();
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC16M)
system_clock_120m_irc16m();
#elif defined (__SYSTEM_CLOCK_120M_PLL_8M_HXTAL)
system_clock_120m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_120M_PLL_25M_HXTAL)
system_clock_120m_25m_hxtal();
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC16M)
system_clock_168m_irc16m();
#elif defined (__SYSTEM_CLOCK_168M_PLL_8M_HXTAL)
system_clock_168m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
system_clock_168m_25m_hxtal();
#elif defined (__SYSTEM_CLOCK_200M_PLL_IRC16M)
system_clock_200m_irc16m();
#elif defined (__SYSTEM_CLOCK_200M_PLL_8M_HXTAL)
system_clock_200m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
system_clock_200m_25m_hxtal();
#endif /* __SYSTEM_CLOCK_IRC16M */
}
/* select a system clock by uncommenting the following line */
//#define __SYSTEM_CLOCK_IRC16M (uint32_t)(__IRC16M)
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_120M_PLL_IRC16M (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_120M_PLL_8M_HXTAL (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_120M_PLL_25M_HXTAL (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_168M_PLL_IRC16M (uint32_t)(168000000)
//#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL (uint32_t)(168000000)
//#define __SYSTEM_CLOCK_168M_PLL_25M_HXTAL (uint32_t)(168000000)
// #define __SYSTEM_CLOCK_200M_PLL_IRC16M (uint32_t)(200000000)
//#define __SYSTEM_CLOCK_200M_PLL_8M_HXTAL (uint32_t)(200000000)
#define __SYSTEM_CLOCK_200M_PLL_25M_HXTAL (uint32_t)(200000000)
除此之外还需要注意,当使用外部高速晶体振荡器HXTAL作为系统时钟源时,还需要根据使用的HXTAL的具体时钟频率来修改宏定义HXTAL_VALUE的值,该值会影响SystemCoreClock、AHB、APB1、APB2等时钟的计算,最终会影响部分外设的使用,如USART、I2C等。