• GD32F450的时钟笔记


    GD32F450 标称 200MHz,但是在手册中又说 它是 240MHz。本文以 手册中的 240MHz 进行举例,我保险起见,产品中使用还是在 200MHz 下使用。

    时钟树

    手册上的时钟树图如下
    在这里插入图片描述

    GD32F450的 外部时钟源 有2个

    • LXTAL 外部低速时钟源 32.768 kHz
    • HXTAL 外部高速时钟源 4~32 MHz

    GD32F450的 内部时钟源 有3个

    • IRC32K 内部 32KHz 时钟源
    • IRC16M 内部 16MHz 时钟源
    • IRC48M 内部 48MHz 时钟源

    重要时钟

    对于 GD32F450 的使用,主要关注

    • CK_SYS 系统时钟
      _
    • HCLK ( AHB bus,Cortex-M4,SRAM,DMA,peripherals )
    • PCLK1 ( APB1 peripherals )
    • CKTIMERx ( TIMER1,2,3,4,5,6,11,12,13 )
    • PCLK2 ( APB2 peripherals )
    • CKTIMERx ( TIMER0,7,8,9,10 )
    • CK_ADCX ( ADC 0,1,2 )

    主要的外设时钟还是下面这三个时钟,它们衍生出其它外设时钟。

    • AHB 最高时率为 240 MHz
    • APB2 最高时率为 120 MHz
    • APB1 最高时率为 60 MHz

    对于单片机内核,仅需要关注 HCLK
    上述的时钟 主要还是 通过 CK_SYS 时钟衍生出来的,因此需要先配置好它,才能对接下来的 外设时钟进行配置。

    GD32F450的PLL

    CK_SYS 有 3 个 时钟源,如下图所示:

    在这里插入图片描述
    即,

    • IRC16M 内部16MHz (默认)
    • HXTAL 外部高速时钟
    • PLLP 倍频时钟P

    CK_SYS 要想达到240MHz,必须要通过 倍频时钟P 得到。

    GD32F450有3个PLL,与CK_SYS有关的只有PLL,如下图所示

    在这里插入图片描述

    根据上图,可以明确倍频步骤了。

    1. 打开外部时钟源(HXTAL)
    2. 切换内核时钟为非PLL时钟(当前例程为选择内部16MHz时钟)
    3. 确定切换成功
    4. 关闭PLL
    5. 配置 PLLSEL 选择外部时钟源(鄙人的开发板外部晶振为8MHz)
    6. 配置输入分频系数,倍频系数N,输出P分频系数
    7. 使能 PLL
    8. 配置SCS切换时钟
    9. 确定切换成功

    查看相关寄存器,即可进行配置了。

    代码如下

    uint8_t CLock_Init(void)
    {
    	uint16_t overTimeCnt;
    
    	RCU_CTL |= RCU_CTL_HXTALEN;												// 高速晶体振荡器(HXTAL)使能
    	overTimeCnt = 0x0fff;
    	do
    	{
    		overTimeCnt--;
    		if(!overTimeCnt)
    			return FAILED;													// 等待超时
    	} while (!(RCU_CTL & RCU_CTL_HXTALSTB));								// 等待 外部晶振HXTAL 稳定
    
    	RCU_CFG0 = (RCU_CFG0 & ~RCU_CFG0_SCS) | RCU_CKSYSSRC_IRC16M;			// 系统时钟 选择内部16MHz
    	overTimeCnt = 0x0fff;
    	do
    	{
    		overTimeCnt--;
    		if(!overTimeCnt)
    			return FAILED;													// 等待超时
    	} while ((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_IRC16M);				// 等待 系统时钟 选择内部16MHz
    
    
    	RCU_CTL &= ~RCU_CTL_PLLEN;												// 关闭 PLL
    	overTimeCnt = 0x0fff;
    	do
    	{
    		overTimeCnt--;
    		if(!overTimeCnt)
    			return FAILED;													// 等待超时
    	} while ((RCU_CTL & RCU_CTL_PLLEN));									// 等待 关闭 PLL
    
    	RCU_PLL = 	( RCU_PLL & ~(RCU_PLL_PLLPSC | RCU_PLL_PLLN | RCU_PLL_PLLP | RCU_PLL_PLLSEL | RCU_PLL_PLLQ) ) | \
    								( 8 << 0)    | ( 480 << 6)  | ( 0 << 16)   | RCU_PLL_PLLSEL | ( 10 << 24);
    							// 输入8分频     | 倍频480倍    | PLLP 2分频   | 选择外部晶振   | PLLQ 10分频
    							// 输入 1MHz     | VCO=480MHz   | PLLP=240MHz  |                | PLLQ=48MHz
    
    	RCU_CTL |= RCU_CTL_PLLEN;												// 使能 PLL
    	overTimeCnt = 0x0fff;
    	do
    	{
    		overTimeCnt--;
    		if(!overTimeCnt)
    			return FAILED;													// 等待超时
    	} while (!(RCU_CTL & RCU_CTL_PLLSTB));									// 等待 PLL 稳定
    
    	RCU_CFG0 = (RCU_CFG0 & ~(RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC)) | \
    								(0 << 4)     | (5 << 10)        | (4 << 13);
    							// AHB不分频     | APB1 4分频       | APB2 2分频
    							// 240MHz        | 60MHz            | 120MHz
    	
    
    	RCU_CFG0 = (RCU_CFG0 & ~RCU_CFG0_SCS) | RCU_CKSYSSRC_PLLP;				// 系统时钟 选择PLLP
    	overTimeCnt = 0x0fff;
    	do
    	{
    		overTimeCnt--;
    		if(!overTimeCnt)
    			return FAILED;													// 等待超时
    	} while ((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLLP);					// 等待 系统时钟 选择PLLP
    
    	return SUCCEED;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    简单的方法

    其实厂家已经帮我们初始化好了时钟,在 system_gd32f4xx.c 文件中 通过 选择宏定义就能 将单片机 配置成常用的时钟频率了。

    AHB 不分频
    APB1 四分频
    APB2 二分频

    
    /* 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)
    //#define __SYSTEM_CLOCK_240M_PLL_IRC16M          (uint32_t)(240000000)
    // #define __SYSTEM_CLOCK_240M_PLL_8M_HXTAL        (uint32_t)(240000000)
    //#define __SYSTEM_CLOCK_240M_PLL_25M_HXTAL       (uint32_t)(240000000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    java如何初始化数组(如:int[]、byte[]等)
    python-opencv图像傅里叶变换
    Scss 基础语法
    go基础知识学习笔记-篇幅很长写的我想吐
    Prism框架学习
    MYSQL入门与进阶(四)
    云计算概论
    图扑软件数字孪生海上风电 | 向海图强,奋楫争先
    STL教程7-set、pair对组和仿函数
    java servlet校园闲置商品交易平台的设计与实现源码
  • 原文地址:https://blog.csdn.net/xl22126/article/details/127884333