×
单片机 > 单片机程序设计 > 详情

STM32F4时钟初始化配置

发布时间:2020-05-19 发布时间:
|

STM32F4 时钟系统初始化是在system_stm32f4xx.c中的 SystemInit()函数中完成的。 对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体:

void SystemInit(void)

{

  

   #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

     SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); 

   #endif

 

  

   RCC->CR |= (uint32_t)0x00000001;

  

   RCC->CFGR = 0x00000000;

  

   RCC->CR &= (uint32_t)0xFEF6FFFF;

  

   RCC->PLLCFGR = 0x24003010;

  

   RCC->CR &= (uint32_t)0xFFFBFFFF;

  

   RCC->CIR = 0x00000000;

#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)

   SystemInit_ExtMemCtl();  

#endif

          

  

    SetSysClock();

  

#ifdef VECT_TAB_SRAM

   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;

#else

   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

#endif

}

SystemInit函数开始先进行浮点运算单元设置,然后是复位PLLCFGR,CFGR寄存器,同时通过设置 CR 寄存器的 HSI 时钟使能位来打开 HSI 时钟。默认情况下如果 CFGR 寄存器复位,那么是选择HSI作为系统时钟,这点大家可以查看RCC->CFGR 寄存器的位描述最低2位可以得知,当低两位配置为 00的时候(复位之后),会选择 HSI振荡器为系统时钟。也就是说,调用 SystemInit 函数之后,首先是选择 HSI 作为系统时钟。

 

 

在设置完相关寄存器后,接下来SystemInit函数内部会调用 SetSysClock函数。这个函数比较长,我们就把函数一些关键代码行截取出来给大家讲解一下。这里我们省略一些宏定义标识符值的判断而直接把针对STM32F407 比较重要的内容贴出来:

static void SetSysClock(void)

{

   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  

   RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  

  

   do

   {

     HSEStatus = RCC->CR & RCC_CR_HSERDY;

     StartUpCounter++;

   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

 

   if ((RCC->CR & RCC_CR_HSERDY) != RESET)

   {

     HSEStatus = (uint32_t)0x01;

   }

   else

   {

     HSEStatus = (uint32_t)0x00;

   }

 

   if (HSEStatus == (uint32_t)0x01)

   {

    

     RCC->APB1ENR |= RCC_APB1ENR_PWREN;

     PWR->CR |= PWR_CR_VOS;

 

    

     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

       

    

RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

     

    

     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    

     RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;

     

    

     RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

 

    

     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

 

    

     RCC->CR |= RCC_CR_PLLON;

 

    

     while((RCC->CR & RCC_CR_PLLRDY) == 0)

     {

     }

     

    

     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN  

|FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

 

  

    

     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

     RCC->CFGR |= RCC_CFGR_SW_PLL;

 

    

     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);

     {

     }

   }

   else

   {

   }

 

}

这段代码的大致流程是这样的:先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主PLL时钟,然后设置主PLL作为系统时钟 SYSCLK时钟源。如果HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是HSI作为系统时钟。

在这里要特别提出来,在设置主PLL时钟的时候,会要设置一系列的分频系数和倍频系数参数。大家可以从SetSysClock函数的这行代码看出:

RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地方配置。对于我们开发板,我们的设置参数值如下:

#define PLL_M       8

#define PLL_Q      7

#define PLL_N      336

#define PLL_P      2

所以我们的主PLL时钟为:

PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz

在开发过程中,我们可以通过调整这些值来设置我们的系统时钟。

  这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符HSE_VALUE 的值为我们的外部时钟:

#if !defined  (HSE_VALUE)  

  #define HSE_VALUE    ((uint32_t)8000000)

   

#endif

这里默认固件库配置的是25000000,我们外部时钟为8MHz,所以我们根据我们硬件情况修改为8000000即可。

讲到这里,大家对 SystemInit 函数的流程会有个比较清晰的理解。那么 SystemInit 函数是怎么被系统调用的呢?SystemInit是整个设置系统时钟的入口函数。这个函数对于我们使用ST提供的 STM32F4 固件库的话,会在系统启动之后先执行main函数,然后再接着执行SystemInit函数实现系统相关时钟的设置。这个过程设置是在启动文件 startup_stm32f40_41xxx.s中间设置的,我们接下来看看启动文件中这段启动代码:

; Reset handler

Reset_Handler    PROC

                  EXPORT  Reset_Handler             [WEAK]

         IMPORT  SystemInit

         IMPORT  __main

 

                  LDR     R0, =SystemInit

                  BLX     R0

                  LDR     R0, =__main

                  BX      R0

                  ENDP

这段代码的作用是在系统复位之后引导进入main函数,同时在进入main函数之前,首先

要调用 SystemInit系统初始化函数完成系统时钟等相关配置。

最后我们总结一下SystemInit()函数中设置的系统时钟大小:

SYSCLK(系统时钟)                     =168MHz

  AHB总线时钟(HCLK=SYSCLK)            =168MHz

  APB1总线时钟(PCLK1=SYSCLK/4)        =42MHz

  APB2总线时钟(PCLK2=SYSCLK/2)        =84MHz

  PLL主时钟                          =168MHz


关键字:STM32F4  时钟  初始化配置 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机制作超级流水灯