MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置

MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置

1、时钟初始化流程

一般流程为startup_mm32f3273g.s中调用system_mm32f3273g.c中的SystemInit函数完成系统时钟的初始,而system_mm32f3273g.c中函数是空的。
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第1张图片
原来MindSdk时钟初始化的流程放到了clock_init.c中。

2、采用外部高速时钟源

先弄清几个概念:
HSE (外部高速时钟信号)
HSI (芯片内部时钟信号)
LSE (外部低速时钟信号)
LSI (内部低速时钟信号)
PLL (锁相环)因为HSE HSI的频率都不是太高,所以ARM设计了PLL(锁相环)来进行倍频,把HSI和HSE频率拉高到百兆以上。
SycClk (系统时钟)
HCLK (AHB的时钟)
HCLK1 (APB1的时钟)
HCLK2 (APB2的时钟)
设置系统时钟SYSCLK、设置AHB分频因子(决定HCLK是多少)、设置APB2分频因子(设定PCLK2等于多少)、设置APB1分频因子(决定PCLK1等于多少);
火龙果mm32F3273开发板外接12M晶振,因此这里我们采用HSE+PLL的方式作为开发板的时钟输入信号。

3、时钟设置

关于PLL使能与设置,芯片手册上是这样写的。
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第2张图片
而PLL输出时钟与输入时钟的关系如图:
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第3张图片
假设我们PLLDIV设置1分频,输入时钟12M,想要获得的PLL输出时钟为120M,那么PLLMUN应为设置为19。
而PLL设置的寄存器如下:
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第4张图片
代码中关于pll的设置如下:

    /* enable HSE. */
    RCC->CR |= RCC_CR_HSEON_MASK;
    while ( RCC_CR_HSERDY_MASK != (RCC->CR & RCC_CR_HSERDY_MASK) )
    {
    }

    RCC->PLLCFGR = RCC_PLLCFGR_PLLSRC(1) /* (pllsrc == 1) ? HSE : HSI. */
                 | RCC_PLLCFGR_PLLMUL(19) /* (12 * (19 + 1)) / 2 = 120. */
                 | RCC_PLLCFGR_PLLDIV(1)   /*PLL分频系数*/
                 | RCC_PLLCFGR_PLLLDS(1) /*这个寄存器是个保留的,不设置亦可*/
                 | RCC_PLLCFGR_PLLICTRL(3) /*PLL Charge Pump电流控制信号*/
                 ;

    /* Enable PLL. */
    RCC->CR |= RCC_CR_PLLON_MASK;
    while((RCC->CR & RCC_CR_PLLRDY_MASK) == 0)
    {
    }

PLL设置完成,我们接下来要设置sysclk hclk hclk1 hclk2的时钟。
一般SYSCLK=PLLCLK=120MHz
HCLK,也就是AHB CLK,这里设置为1分频,即=SYSCLK=120M.
HCLK1,也就是APB1CLK,这里设置2分频,即=HCLK/2=60M。
HCLK2,也就是APB2CLK,这里设置2分频,即=HCLK/2=60M。
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第5张图片

相关寄存器设置如图:
MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第6张图片
相关设置代码如下:

 /* Setup the dividers for each bus. */
    RCC->CFGR = RCC_CFGR_HPRE(0)   /* div=1 for AHB freq. */
              | RCC_CFGR_PPRE1(0x4)  /* div=2 for APB1 freq. */
              | RCC_CFGR_PPRE2(0x4)  /* div=2 for APB2 freq. */
              | RCC_CFGR_MCO(7)    /* use PLL/2 as output. */
              ;

    /* Switch the system clock source to PLL. */
    RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW_MASK) | RCC_CFGR_SW(2); /* use PLL as SYSCLK */


    /* Wait till PLL is used as system clock source. */
    while ( (RCC->CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS(2) )
    {
    }

至此,经过上面设置,我们将开发板设置成了120M的时钟。

4、获取时钟函数

uint32_t CLOCK_GetBootHSEValue(void)
{
	uint32_t tmpreg = 0U, prediv = 0U, pllclk = 0U, pllmul = 0U;
    uint32_t sysclockfreq = 0U;
    
    tmpreg = RCC->CFGR;
    /* 获取系统时钟源 */
    switch(tmpreg & RCC_CFGR_SWS_MASK)
    {
        case RCC_SYSCLKSOURCE_STATUS_HSI:
        {
            sysclockfreq = HSI_VALUE;
            break;
        }
        case RCC_SYSCLKSOURCE_STATUS_HSE:
        {
            sysclockfreq = HSE_VALUE;
            break;
        }
        case RCC_SYSCLKSOURCE_STATUS_LSI:
        {
            sysclockfreq = LSI_VALUE;
            break;
        }
        case RCC_SYSCLKSOURCE_STATUS_PLLCLK:
        {
            /* 获取PLL的输入时钟源 */
            if(RCC->PLLCFGR&0x01)       // HSE用作PLL的输入时钟
            {
                if(RCC->PLLCFGR&0x02)   // HSE二分频后输入给PLL
                {
                    pllclk = HSE_VALUE>>1;
                }
                else                    // HSE部分变频直接输出给PLL
                {
                    pllclk = HSE_VALUE;
                }
            }
            else    // HSI用作PLL的输入时钟
            {
                pllclk = HSI_VALUE;
            }
            prediv = (RCC->PLLCFGR>>8)&0x07;    // PLL的分频系数:PLLCFGR[10:8]
            pllmul = (RCC->PLLCFGR>>16)&0x7F;   // PLL的倍频系数: PLLCFGR[22:16]
            sysclockfreq = pllclk * (pllmul+1) / (prediv+1);
            
            break;
        }
        default:break;
    }
    
    return sysclockfreq;

}

5、打印结果如下

MM32F3273G8P火龙果开发板MindSDK开发教程3 - Sysclk的配置_第7张图片

你可能感兴趣的:(火龙果MM32F3273G8P,单片机,fpga开发,stm32)