#申请原创#
@21小跑堂
前段时间有位坛友发帖咨询了一个问题,所用的MCU型号是GD32F45ZIT6,后经排查分析,其主要原因是系统时钟配置错误导致,即板子所用的外部晶振是16M,但软件上实际配置的是8M,通过PLL倍频以后,系统时钟不是正常的200M。软件为什么会配置错呢?是因为库文件里关于外部晶振的宏定义配置只有8M和25M两个,加上外部晶振是支持4~32M的,所以他们误将宏定义__SYSTEM_CLOCK_200M_PLL_8M_HXTAL理解为可以适配外部晶振4~32M而没有再去修改系统时钟配置函数里的PLL参数。 鉴于此,抽空写一篇有关GD32F4xx系列的MCU系统时钟配置的文章,让大家以后在配置系统时钟时有所参考。 查看了GD32F4xx的用户手册,应该能适用于GD32F405xx、GD32F407xx、GD32F425xx、GD32F427xx、 GD32F450xx 及GD32F470xx 系列。 我们先来看看用户手册里的时钟控制单元,主要提供了以下的时钟可供选择: 一个内部16M RC振荡器时钟(IRC16M); 一个内部48M RC振荡器时钟(IRC48M); 一个外部高速晶体振荡器时钟(HXTAL); 一个内部32K RC振荡器时钟(IRC32K); 一个外部低速晶体振荡器时钟(LXTAL)。 再打开文件system_gd32f4xx.c文件看下系统时钟的相关配置参数:
从这些代码可以看出,用来做系统时钟的时钟单元主要是IRC16M和HXTAL,并且代码里提供了120M、168M和200M的系统时钟配置选择,只要打开相应的宏定义即可。 当相应的宏定义被打开后,MCU上电初始化时就会执行相应的系统时钟配置函数:
比如我们打开了宏定义__SYSTEM_CLOCK_200M_PLL_8M_HXTAL,就会执行函数system_clock_200m_8m_hxtal:
而底层函数SystemInit是在哪里被执行的呢?是在启动文件里面被调用的:
如果你板子上用的外部晶振是8M。并且想将系统时钟配置为200M,那么按以上的代码配置就可以了,不需要再修改PLL参数了。 只要宏定义里面有与你的硬件和需求匹配的,那就按照上面的方法配置即可。 那如果是遇到文章开始说的那位坛友的情况呢?他为什么一定要用16M外部晶振?是因为公司现有平台都是用的16M晶振,那这个时候宏定义没有你想要的,怎么办?就需要去做一些更为详细的代码修改了。 第一步,可以继续使用宏定义__SYSTEM_CLOCK_200M_PLL_8M_HXTAL; 第二步,需要修改宏定义HXTAL_VALUE的值,由默认的8000000改为16000000:
第三步,需要修改函数system_clock_200m_8m_hxtal: 我们知道系统时钟是通过PLL锁相环参数(也就是M、N、P、Q)倍频而来的,因此需要修改PLL参数。 配置PLL,也就是配置PLL寄存器RCU_PLL,可以参考下面的公式来计算: 系统时钟=输入时钟*N/(M*P); 其中: 输入时钟:输入参考时钟频率,通常来自外部晶体振荡器; N:反馈分频器的倍频系数,PLL的乘法因子; M:输入分频器的分频系数,对参考时钟预分频; P:输出分频器的分频系数,对PLL输出后分频。 函数里面需要修改的代码主要是:
我们来计算看看: 以上代码是8M外部晶振,配置200M系统时钟: 输入时钟*N/(M*P)=8*400/(8*2)=200M。 如果是16M外部晶振,配置200M系统时钟的话,代码就是:
即只需要修改M参数。 以上通过对GD32F4xx系列的时钟介绍和代码实例说明阐述了如何根据自身需求进行系统时钟配置,以后在遇到类似配置时,一定要注意,否则会导致意想不到的程序问题。
|