datasheet

STM32F4系统时钟设置之二

2019-06-13来源: eefocus关键字:STM32F4  系统时钟  设置

STM32F407系统时钟配置

时钟树

1


方法一,采用官方库提供的配置(这里外部晶振25MHz,系统配置为168MHz)

STM32F4启动与STM32F10X不同,时钟已经默认配置好

启动代码,文件:startup_stm32f4xx.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函数之前,系统调用了SystemInit函数.


SystemInit函数分析:SystemInit函数位于system_stm32f4xx.c文件中.此文件提供几个宏定义可以设置各个时钟:

/************************* PLL Parameters *************************************/  

/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */  

#define PLL_M      25  

#define PLL_N      336  

 

/* SYSCLK = PLL_VCO / PLL_P */  

#define PLL_P      2  

 

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */  

#define PLL_Q      7  

 

/******************************************************************************/



而晶振频率则是在文件stm32f4xx.h中进行设置:


外部晶振:


#if !defined  (HSE_VALUE)   

  #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */  

#endif /* HSE_VALUE */



内部晶振:

#if !defined  (HSI_VALUE)     

  #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/  

#endif /* HSI_VALUE */ 



综上,可以得出默认配置中: 

锁相环压腔振荡器时钟PLL_VCO = 25 / 25 * 336 = 336MHz 

系统时钟SYSCLK = 336 / 2 = 168MHz 

USB,SD卡时钟 = 336 / 7 = 48MHz


SystemInit函数代码:

/** 

  * @brief  Setup the microcontroller system 

  *         Initialize the Embedded Flash Interface, the PLL and update the  

  *         SystemFrequency variable. 

  * @param  None 

  * @retval None 

  */  

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 RCC clock configuration to the default reset state ------------*/  

  /* Set HSION bit */  

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

 

  /* Reset CFGR register */  

  RCC->CFGR = 0x00000000;  

 

  /* Reset HSEON, CSSON and PLLON bits */  

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

 

  /* Reset PLLCFGR register */  

  RCC->PLLCFGR = 0x24003010;  

 

  /* Reset HSEBYP bit */  

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

 

  /* Disable all interrupts */  

  RCC->CIR = 0x00000000;  

 

#ifdef DATA_IN_ExtSRAM  

  SystemInit_ExtMemCtl();   

#endif /* DATA_IN_ExtSRAM */  

 

  /* Configure the System clock source, PLL Multiplier and Divider factors,  

     AHB/APBx prescalers and Flash settings ----------------------------------*/  

  SetSysClock();  

 

  /* Configure the Vector Table location add offset address ------------------*/  

#ifdef VECT_TAB_SRAM  

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */  

#else  

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */  

#endif  

}



SetSysClock函数分析,在SetSysClock函数中,配置了系统时钟,PLL倍频以及分频系数:

/** 

  * @brief  Configures the System clock source, PLL Multiplier and Divider factors,  

  *         AHB/APBx prescalers and Flash settings 

  * @Note   This function should be called only once the RCC clock configuration   

  *         is reset to the default reset state (done in SystemInit() function).    

  * @param  None 

  * @retval None 

  */  

static void SetSysClock(void)  

{  

/******************************************************************************/  

/*            PLL (clocked by HSE) used as System clock source                */  

/******************************************************************************/  

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;  

 

  /* Enable HSE */  

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

 

  /* Wait till HSE is ready and if Time out is reached exit */  

  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)  

  {  

    /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */  

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;  

    PWR->CR |= PWR_CR_VOS;  

 

    /* HCLK = SYSCLK / 1*/  

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;  

 

    /* PCLK2 = HCLK / 2*/  

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;  

 

    /* PCLK1 = HCLK / 4*/  

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;  

 

    /* Configure the main PLL */  

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);  

 

    /* Enable the main PLL */  

    RCC->CR |= RCC_CR_PLLON;  

 

    /* Wait till the main PLL is ready */  

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

    {  

    }  

 

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */  

    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;  

 

    /* Select the main PLL as system clock source */  

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

    RCC->CFGR |= RCC_CFGR_SW_PLL;  

 

    /* Wait till the main PLL is used as system clock source */  

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

    {  

    }  

  }  

  else  

  {

  /* If HSE fails to startup, the application will have wrong clock configuration. User can add here some code to deal with this error */  

  }  

 

}



如果外部时钟启动失败,系统会使用内部时钟 

默认配置: 

HCLK = SYSCLK / 1 = 168MHz 

PCLK2 = HCLK / 2 = 84MHz 

PCLK1 = HCLK / 4 = 42MHz


方法二,根据需要重新进行配置(这里外部晶振25MHz,系统配置为168MHz)

自己根据自己外部晶振大小和需要进行配置

 

void RCC_Config(void)

{

    RCC_DeInit();    //RCC寄存器初始化

    RCC_HSEConfig(RCC_HSE_ON);    //使用外部时钟

    if(RCC_WaitForHseStartUp() == SUCCESS)     //等待外部时钟启动

    {

        RCC_PLLCmd(DISABLE);    //配置PLL前应先关闭主PLL

        RCC_SYSCLKConfig(RCC_SYSCLKSOURCE_PLLCLK);    //选择PLL时钟为系统时钟

        RCC_HCLKConfig(RCC_SYSCLK_Div1);    //HCLK(AHB)时钟为系统时钟1分频

        RCC_PCLK1Config(RCC_HCLK_Div4);    //PCLK(APB1)时钟为HCLK时钟8分频

        RCC_PCLK2Config(RCC_HCLK_Div2);    //PCLK(APB2)时钟为HCLK时钟2分频

        RCC_PLLConfig(RCC_PLLSource_HSE,25,336,2,7);    //PLL时钟配置,外部晶振为25MHz,系统配置为168MHz

        RCC_PLLCmd(ENABLE);    //PLL时钟开启

while(RCC_GetFlagStatus(RCC_FLAG_PLLRD

[1] [2]

关键字:STM32F4  系统时钟  设置

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic464497.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32软件复位的实现方法
下一篇:STM32F407时钟设置

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32F030R8-Nucleo使用PA2、PA3 UART2不能使用的问题

1. 开发环境开发平台:官方开发板STM32F030R8-Nucleo开发软件:Keil uVision5.24开发库:STM32Cube_FW_F0_V1.9.02. 实验现象根据官方例程,将UART1的配置更改为UART2,然后使用杜邦线接到PA2、PA3引脚,可串口就是无法收发数据。之后查看原理图发现,官方的Demo板,默认就没有将PA2、PA3扩展到外部引脚上,而是将这个USART2串口连接到了ST-Link的串口上,这样,ST-Link既可以下载程序,也可以当做开发板的USART2使用。截取部分具体电路图如下:其中SB14、SB13、SB63和SB62都是零欧姆电阻,问题就在这里了,SB14、SB13焊接了,但是SB63
发表于 2019-06-14
STM32F030R8-Nucleo使用PA2、PA3 UART2不能使用的问题

基于Ymodem协议的STM32F407的串口IAP

发送数据。成功接收的不会被确认。有错误的块被确认(NAK),并重发。Ymodem类似于Xmodem-1K,不同之处是提供批处理模式(batch mode)。在批处理模式下,可以使用一个命令发送一些文件。Ymodem使用循环冗余码校验作为错误校验方式。——摘自百度百科基于Ymodem协议的IAP引导程序硬件平台原子探索者STM32F407开发板通信接口串口实现流程按住复位键时按下KEY1键,在松开复位键之前按住KEY1不放,松开复位键,红色LED灯常亮,这时便进入固件升级程序,不断向上位机发送字符’C’请求上位机发送应用程序固件。这时打开上位机查询请求,上位机接收到请求后,通过串口发送第一个数据包,这个数据包主要包含了传输的文件的文件名和文
发表于 2019-06-14
基于Ymodem协议的STM32F407的串口IAP

STM32F10xxx支持三种复位

STM32F10xxx支持三种复位形式,分别为系统复位、上电复位和备份区域复位。一、系统复位除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器(见图4)以外,系统复位将复位所有寄存器至它们的复位状态。当发生以下任一事件时,产生一个系统复位:1. NRST引脚上的低电平(外部复位) 2.  窗口看门狗计数终止(WWDG复位) 3.  独立看门狗计数终止(IWDG复位) 4.  软件复位(SW复位) 5.  低功耗管理复位可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源。软件复位通过将Cortex™-M3中断应用
发表于 2019-06-14
STM32F10xxx支持三种复位

一则STM32f103莫名反复复位的经验记录

最近在调试STM32F103RBT6时,发现只要一打开AD就会反复复位,将断点设置到启动代码处,发现复位是非常有规律的,总是执行过断点后就又回到断点了。找原理,查硬件,一切均没有问题。最后怀疑到代码上来,因为AD采样是另外一个产品中正常使用移植过来的,分为三大部分:对AD涉及到的外设和存储等的初始化,对AD的采集与存储(主要是中断),对AD的数据进行计算分析。将三大模块全部注释后再逐一开放,发现是对AD的初始化会导致复位。对AD的初始化代码再全部注释后逐一开放,发现是启动定时器TIM4的代码会导致复位。后来将与定时器有关的代码全部审查了一遍,也没有发现问题,同样的相似代码在TIM1上工作的很好。查网上的相似问题,也没有改善
发表于 2019-06-14

STM32F4的CCM内存之一

我们知道STM32F4当中有个CCM内存,如图所示,这个内存是挂在D总线上直接和内核相连,因此除了内核之外谁都不能访问,那么我们怎么将其利用起来呢? 首先,我们可以使用Keil的设置选项,将IRAM2打勾,让编译器选择什么时候使用这个内存。显然,我们还可以将这两个地址修改一下,将IRAM1改为0x10000000,这样,编译器就会优先分配CCM内存。 我们来看看结果,在MAP文件中,表明确实使用了这段内存,但是因为我们使用的内存较少, 还没有用到CCM。 这种自动分配的方式有什么问题呢?这段内存是内核专有的,除了内核任何其它总线都不能访问,这就意味着,一旦编译器将数据分配到CCM中,而同时使用了DMA
发表于 2019-06-14
STM32F4的CCM内存之一

STM32F4的CCM之二

前言有客户用STM32F427芯片,程序将CSTACK放在CCM RAM中,结果测试过一段时间的板子都出现了不能正常运行的情况。这个现象一度让我们怀疑是否是CCM RAM在测试过程中遭到了破坏,导致我们在解决问题的道路上浪费了不少时间。事实证明STM32的CCM RAM并没有那么脆弱,而解决问题时尽力从多个角度进行验证,不放过所有可能出问题的环节之心态更为重要。在具体讨论问题的原因之前,不妨先介绍一下STM32F4/STM32F3系列芯片上的CCM RAM。CCM RAM介绍ST的STM32F303, STM32F358, STM32F328, STM32F334系列和STM32F4的Advanced line系列芯片里都有CCM
发表于 2019-06-13
STM32F4的CCM之二

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved