嵌入式_GD32F10x外部晶振配置108MHz系统时钟
文章目录
- 嵌入式_GD32F10x外部晶振配置108MHz系统时钟
- 前言
- 一、时钟树与配置思路
- 二、时钟配置过程
- 三、晶振故障排查
- 总结
前言
由于公司更改硬件设计选择使用新的型号兆易创新国产芯片,需要把以前的软件进行移植,新板子要求新的板子使用的外部8兆晶振,系统时钟要求达到108兆,在配置过程中踩了别人的坑,在此简单记录一下。
注:本项目基于GD32F103CBT6硬件平台, 使用标准库GD32F10x_Firmware_Library_V1.0.0(提示:此库坑多、慎用!
)
一、时钟树与配置思路
GD32F10x使用M1内核时钟树如图所示,先根据构时钟树构想的配置思路如图上红线路径所示:
A:此处决定PREDV0的时钟源是外部时钟还是PLL1(CL型芯片才有PLL1和PLL2,时钟配置寄存器 1的第16位),我们是HD型芯片,所以配置不了该位,选择默认值0。
B:此处为PREDV0分频因子,时钟配置寄存器 0的第17位,我们选择为外部时钟2分频,得到4MHz时钟
C:此位决定PLL使用0(内部高速时钟)还是1(外部高速时钟),时钟配置寄存器 0的第16位,选择配置为1
D:PLL的倍频因子,时钟配置寄存器 0的第18到21位、29位,我们选择倍频27,4MHz*27 = 108MHz
E:系统时钟选择,决定系统用那一路时钟,时钟配置寄存器 0的第0位与第1位,我们配置为10即可
最终得到108兆系统时钟
二、时钟配置过程
● 1.在gd32f10x.h文件中修改HSE_VALUE宏的值为:8000000
#if !defined HSE_VALUE
#ifdef GD32F10X_CL
#define HSE_VALUE ((uint32_t)25000000)
#else
#define HSE_VALUE ((uint32_t)8000000)
#endif
#endif
● 2.在system_gd32f10x.c文件中修改需要的系统时钟频率宏为:SYSCLK_FREQ_108MHz
代码如下(示例):
#define SYSCLK_FREQ_108MHz 108000000
然后在system_gd32f10x.c文件中你就可以看到108兆时钟配置函数
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#elif defined SYSCLK_FREQ_96MHz
SetSysClockTo96();
#elif defined SYSCLK_FREQ_108MHz
SetSysClockTo108();
#elif defined SYSCLK_FREQ_48MHz_HSI
SetSysClockTo48HSI();
#elif defined SYSCLK_FREQ_72MHz_HSI
SetSysClockTo72HSI();
#elif defined SYSCLK_FREQ_108MHz_HSI
SetSysClockTo108HSI();
#endif
}
● 3.在system_gd32f10x.c 文件中修改SetSysClockTo108();
一般情况下是不用修改该函数的,但是我直接使用时踩了个坑,时钟频率不对,然后返回来检查寄存器时分析了这个函数,这里简单说一下作为个人笔记,大佬可以自动跳过。
最主要是这里:
RCC->GCFGR |= (uint32_t)( RCC_GCFGR_PLLPREDV_HSE_DIV2 | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF27);
RCC_GCFGR_PLLPREDV_HSE_DIV2:这里配置时钟树图的 B处
RCC_GCFGR_PLLSEL_HSE:这里配置时钟树图的 C处
RCC_GCFGR_PLLMF27:这里配置时钟树图的 D处
检查了一遍根据寄存器,显示的值都没问题,但调试到选择则PLL作为系统时钟这句就有问题:
RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL;
通过函数RCC_GetClocksFreq(&RCC_Clockstruct)抓出来的时钟频率全是乱的
代码如下(示例):
static void SetSysClockTo108(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN);
do
{
HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1;
RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1;
RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2;
#ifdef GD32F10X_CL
RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF);
RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_PREDIV1 | RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF9);
RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF |
RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL);
RCC->GCFGR2 |= (uint32_t)( RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF12 |
RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5);
RCC->GCCR |= RCC_GCCR_PLL2EN;
while((RCC->GCCR & RCC_GCCR_PLL2STB) == 0)
{
}
#else
RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF));
RCC->GCFGR |= (uint32_t)( RCC_GCFGR_PLLPREDV_HSE_DIV2 | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF27);
#endif
RCC->GCCR |= RCC_GCCR_PLLEN;
while((RCC->GCCR & RCC_GCCR_PLLSTB) == 0)
{
}
RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS));
RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL;
while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08)
{
}
}
else
{
}
}
三、晶振故障排查
软件排查基本没问题那就只能看硬件了,晶振使用的是晶科JX-S25A系列的一个8兆贴片晶振其原理图为:
使用示波器打一下晶振并联电阻两端都没有波形,然后测了一下并联电阻阻值只有9.8千欧,原理图为1M欧,所以阻值太小了,多半是焊错了,然后把电阻挑了继续拿示波器打,波形一下就出来了,周期为125ns,也确实是8MHz
后面专门去查了原因,给晶振并联一个M级电阻是为了使本来为逻辑反相器的器件工作在线性区, 以获得增益, 在饱和区不存在增益, 而在没有增益的条件下晶振不起振。简而言之,并联1M电阻增加了电路中的负性阻抗(-R),即提升了增益,缩短了晶振起振时间,达到了晶振起振更容易之目的。但是因为晶振本身阻抗是很大的,所以也可以不焊接并联电阻,如果要焊并联电阻就必须足够大,刚刚的1千欧就太小了,等效电阻小于1千欧就没有波形。
也有给晶振串联K级别电阻用来预防晶振过驱,限制振荡幅度。
总结
无
如有错误,欢迎指正,原创不易,转载留名!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)