【GD32开发学习】三、系统时钟选择配置

文章目录


前言

准备

1、GD32F系列开发版,我使用的事F427R-START开发版

2、安装有Keil的电脑,当前keil版本为v5.31.0.0


一、时钟树

二、配置步骤

1、时钟初始化配置过程,主要先配置和初始化RCU_CTL和RCU_CFG0两个寄存器

寄存器内容如下,具体介绍请查看芯片数据手册

 

void SystemInit (void)
{
    /* FPU settings */
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif
    /* Reset the RCU clock configuration to the default reset state */
    /* 开始先使能内部16M时钟 */
    RCU_CTL |= RCU_CTL_IRC16MEN;

    /*CK_AHB分频(CK_AHB = CK_SYS/4,但是不懂为什么先2分频再4分配)*/
    RCU_MODIFY

    /* 选择 CK_IRC16M 时钟作为 CK_SYS 时钟源 */
    RCU_CFG0 &= ~RCU_CFG0_SCS;
    
    /* 锁相环PLL关闭, 禁止高速时钟(HXTAL)时钟监视器 、关闭外部高速时钟HXTAL */
    RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);

    /* 禁止HXTAL旁路模式 */
    RCU_CTL &= ~(RCU_CTL_HXTALBPS);
    
    /* 复位RCU_CFG0寄存器(即内部16M作为时钟源,AHB、APB1、APB2等不分频)  */
    RCU_CFG0 = 0x00000000U;

    /* 等待内部高速时钟 IRC16M 作为系统时钟*/
    while(0 != (RCU_CFG0 & RCU_SCSS_IRC16M)){
    }

    /* 复位PLL寄存器(0x24003010U) */
    RCU_PLL = 0x24003010U;

    /* 禁用中断 */
    RCU_INT = 0x00000000U;
         
    /* 配置系统时钟源, PLL 倍频器 和分频因子,AHB/APBx 预分频器 、flsh设置*/
        
    system_clock_config();
}

总的来说就是SystemInit就是先初始化好内部高速时钟作为时钟源,然后再根据需求配置输出对应时钟

system_clock_200m_25m_hxtal()函数把外部25M高速时钟配置成200MCK_SYS时钟输出

static void system_clock_200m_25m_hxtal(void)
{
    uint32_t timeout = 0U;
    uint32_t stab_flag = 0U;
    
    /* 使能 HXTAL */
    RCU_CTL |= RCU_CTL_HXTALEN;

    /* 等待外部高速时钟稳定,超时退出或者判断时钟稳定则退出等待 */
    do{
        timeout++;
        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));

    /* 如果时钟还没有稳定说明时钟异常,则在这里死循环 */
    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
        while(1){
        }
    }
    /* 电源管理单元时钟使能 */     
    RCU_APB1EN |= RCU_APB1EN_PMUEN;
	
	/* LDO电压选择, 输出高电压模式 */
    PMU_CTL |= PMU_CTL_LDOVS;

    /* 不分频,AHB = SYSCLK,CK_SYS = CK_AHB (这里最大200M,不同的型号不一样) */
    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
    /* APB2 = AHB/2 则这里最大 100M*/
    RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
    /* APB1 = AHB/4 则这里最大 50M*/
    RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;

    /* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ 
	/* 配置PLLSEL选择HXTAL外部高速时钟作为PLL时钟源、
		配置 预分频器 PSC 分频系数为25,作为PLL VCO的输入时钟,如果外部晶振是8或12M晶振的话需改
		配置倍频因子 PLL_N = 400,输出频率分频系数PLL_P = 2, 输出频率的分频系数 PLL_Q = 9	
		根据公式 CK_PLLP = 25/25*400/2 = 200  */
    RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
                   (RCU_PLLSRC_HXTAL) | (9U << 24U));

    /* 使能PLL */
    RCU_CTL |= RCU_CTL_PLLEN;

    /* 等待PLL稳定 */
    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
    }
    
    /*在高频状态下,电源管理单元使能高驱动模式 */
    PMU_CTL |= PMU_CTL_HDEN;
    while(0U == (PMU_CS & PMU_CS_HDRF)){
    }
    
    /* 将LDO切换到高驱动模式 */
    PMU_CTL |= PMU_CTL_HDS;
    while(0U == (PMU_CS & PMU_CS_HDSRF)){
    } 
    
    /* 清空SCS寄存器,再配置SCS寄存器把CK_PLLP 作为系统时钟CK_SYS的时钟源 */
    RCU_CFG0 &= ~RCU_CFG0_SCS;
    RCU_CFG0 |= RCU_CKSYSSRC_PLLP;

    /* 等待选择 CK_PLLP 时钟作为 CK_SYS 时钟源 的状态切换完成 */
    while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
    }
}

注意,这个函数是以25M晶振配置,如果外部高速晶振接的不是25M有没有对应的配置函数,需要自己修改PSC的系数,如 外部晶振如果接的是 12M,则PSC改为12


总结

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值