007 - STM32学习笔记 - 系统时钟配置函数SetSysClock

文章详细分析了STM32F429开发板中系统时钟配置函数SetSysClock的实现过程,包括使能HSE,配置AHB、APB总线预分频因子,设置PLL分频因子并启用,以及选择PLL作为系统时钟源等步骤。在裁剪代码时,需注意条件编译语句和针对特定芯片的设置。
摘要由CSDN通过智能技术生成
007 - STM32学习笔记 - 系统时钟配置函数SetSysClock
1、代码分析

上节在学习RCC时钟树时,知道了开发板在上电后,会先执行启动代码中的复位程序Reset_Handler,在Reset_Handler中会执行系统初始化函数SystemInit,而在SystemInit中执行了SetSysClock函数,SetSysClock函数中则设置了系统时钟及锁相环等相关配置。

SetSysClock函数原型在system_stm32f4xx.c中,在SetSysClock中我们看到如下条件编译语句:

#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)|| defined(STM32F469_479xx)

说明此文件支持在代码中体现的F4系列的多个芯片,我这里使用的是野火的F429开发板,代码中STM32F429_439xx就能体现出来。在对SetSysClock进行分析前,先将此函数进行裁剪,删除与429不相关的语句,裁剪后的函数原型如下(为了保证库函数的完整性,将SetSysClock函数原型复制出来,新建bsp_rccclkconfig.c及bsp_rccclkconfig.h文件,再将这两个文件加入工程中,此处方法不再描述,不懂得看LED及KEY那两节)。

bsp_rccclkconfig.c

static void SetSysClock(void)
{
    /*-------------1、使能HSE,并等待HSE稳定---------------*/
    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

    /* 使能 HSE */
    RCC->CR |= ((uint32_t)RCC_CR_HSEON);

    /* 等待HSE振荡器启动完成,HSE_STARTUP_TIMEOUT当振荡器长时间没有稳定下来时(超时),则会跳出这个循环 */
    /* HSE振荡器稳定下来后, RCC_CR_HSERDY会置1,HSEStatus即为当前HSE的状态值,为0时则表示HSE振荡器未稳定 */
    do
    {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;
        StartUpCounter++;
    }while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

    /* 再次确认HSE状态 */
    if ((RCC->CR & RCC_CR_HSERDY) != RESET)
    {
        HSEStatus = (uint32_t)0x01;
    }
    else
    {
        HSEStatus = (uint32_t)0x00;
    }

    /* 如果HSE启动成功,则进入执行后续操作 */
    if(HSEStatus == (uint32_t)0x01)
    {

        /* 选择电压调节器输出为模式1 */
        /* 使能电源接口时钟 */
        RCC->APB1ENR |= RCC_APB1ENR_PWREN;
        PWR->CR |= PWR_CR_VOS;
        
        /*-------------2、配置AHB\APN2\APB1总线的预分频因子---------------*/
        /* 设置AHB总线分频因子 1分频 */
        RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
        /* 设置APB2总线分频因子 2分频 */
        RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
        /* 设置APB1总线分频因子 4分频 */
        RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

        /*-------------3、配置PLL的各种分频因子,并使能PLL---------------*/
        /* 配置主锁相环倍频因子 M = 25,N = 360,P = 2,Q = 7*/
        RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
        (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

        /* 使能主锁相环 */
        RCC->CR |= RCC_CR_PLLON;

        /* 等待锁相环稳定,稳定后硬件会将RCC_CR_PLLRDY置1 */
        while((RCC->CR & RCC_CR_PLLRDY) == 0)
        {
        }
        
        /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
        PWR->CR |= PWR_CR_ODEN;     //这个寄存器的说明在中文参考手册中没有,英文手册中描述大致意思为打开Over-drive模式以便达到180MHz
        //等待Over-drive模式启动成功
        while((PWR->CSR & PWR_CSR_ODRDY) == 0)
        {   
        }
        
        PWR->CR |= PWR_CR_ODSWEN;
        while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
        {
        }      
        /* 配置FLASH预取指,指令缓存,数据缓存及等待周期 */
        FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

        /*-------------4、选择PLL作为系统时钟来源---------------*/
        /* 选择主锁相环为系统时钟 */
        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
        RCC->CFGR |= RCC_CFGR_SW_PLL;

        /* 等待PLLCLK切换为主锁相环 */
        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
        {
        }
    }
    else
    { 
        //*如果启动不成功,则进入错误处理步骤,这里后续可以添加一些错误处理代码 */
    }
}

结合以上代码的分析,可以总结出,系统时钟的配置,需要以下几步操作:

  1. 使能HSE,并等待HSE稳定;
  2. 配置AHB\APN2\APB1总线的预分频因子;
  3. 配置PLL的各种分频因子,并使能PLL;
  4. 选择PLL作为系统时钟来源

1、在裁剪的时候,注意条件编译的#if defined...#endif是成对出现的,删除冗余的代码的时候一定要看清楚。

2、在裁剪SetSysClock时,里面有个条件编译#if defined(USE_HSE_BYPASS) ,这里的USE_HSE_BYPASS表示如果使用的时有源晶振的话,则执行下面的代码,但是在野火F429中,使用的是无源晶振,因此此段程序就删除掉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放学校门口见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值