历史上的今天
返回首页

历史上的今天

今天是:2025年01月04日(星期六)

2021年01月04日 | STM32F4如何设置系统时钟

2021-01-04 来源:eefocus

STM32F4的系统时钟非常重要,涉及到整个系统的运行结果,无论是什么操作,都需要时钟信号,不同型号的微控制器的默认系统时钟配置是不同的,这里,给出两种配置STM32F407系统时钟的方法。


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


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

启动代码,文件:startup_stm32f4xx.s

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 *************************************/

#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)

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

#define PLL_M      8

#else /* STM32F411xE */

#if defined (USE_HSE_BYPASS)

#define PLL_M      8    

#else /* STM32F411xE */   

#define PLL_M      16

#endif /* USE_HSE_BYPASS */

#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */  

 

 

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

#define PLL_Q      7

 

 

#if defined (STM32F40_41xxx)

#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */

#define PLL_P      2  //2            //2---168M   4---84M

#endif /* STM32F40_41xxx */

 

 

#if defined (STM32F427_437xx) || defined (STM32F429_439xx)

#define PLL_N      360

/* SYSCLK = PLL_VCO / PLL_P */

#define PLL_P      2

#endif /* STM32F427_437x || STM32F429_439xx */

 

 

#if defined (STM32F401xx)

#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */

#define PLL_P      4

#endif /* STM32F401xx */

 

 

#if defined (STM32F411xE)

#define PLL_N      400

/* SYSCLK = PLL_VCO / PLL_P */

#define PLL_P      4   

#endif /* STM32F411xx */

 

 

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

我使用的是STM32F407,筛选可用信息如下:


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

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

#define PLL_M      8

#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)8000000) /*!< 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 */   


综上,如果使用外部晶振8MHz,则可以得出默认配置中: 


锁相环压腔振荡器时钟PLL_VCO =(HSE_VALUE/PLL_M)* PLL_N=8/ 8* 336 = 336MHz 


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


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


SystemInit函数代码:

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;

 

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

  SystemInit_ExtMemCtl(); 

#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

         

  /* 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倍频以及分频系数:

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 start-up, the application will have wrong clock 

         configuration. User can add here some code to deal with this error */  

  }  

  

}

点击打开链接

    /* 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 start-up, the application will have wrong clock 

推荐阅读

史海拾趣

Chino-Excel公司的发展小趣事

随着公司规模的扩大,Chino-Excel公司开始实施全球化战略布局。公司先后在多个国家和地区设立研发中心和生产基地,以充分利用当地资源和市场优势。同时,公司加强与全球合作伙伴的紧密合作,共同开发新产品和技术,进一步巩固了在全球市场的地位。

成都振芯/国腾(CORPRO)公司的发展小趣事

2010年,CORPRO在深交所创业板成功上市,成为当时国内“卫星导航第一股”。这一里程碑事件不仅提升了CORPRO的品牌知名度和市场影响力,也为公司后续的发展提供了更为广阔的资金来源和市场空间。上市后,CORPRO继续加大研发投入,推动技术创新和产品升级。

GainSpan ( Telit)公司的发展小趣事

随着业务的不断扩展和技术实力的提升,风华电子厂于1993年实施股份制改革,并更名为广东风华高新科技股份有限公司。1996年,公司在深圳证券交易所成功上市(证券简称风华高科,证券代码000636),成为电子元器件行业的重要一员。上市不仅为公司筹集了更多资金,也进一步提升了公司的知名度和市场竞争力。

ETERNA公司的发展小趣事

ETERNA公司起源于1856年,由格斯塔夫·罗斯切尔德和约翰·乌尔里希在瑞士的圣伊米尔创立。自成立之初,ETERNA便以精湛的制表工艺和不懈的创新精神闻名于世。公司不断推出具有划时代意义的腕表产品,其中最具代表性的是其“五点星座”设计,这一设计成为了品牌的象征,并引领了制表业的新潮流。ETERNA通过不断的技术创新和设计突破,逐渐在电子行业中崭露头角。

CINTERION公司的发展小趣事

CINTERION的前身可追溯到西门子于1995年创建的无线模块业务。在成立之初,该公司便专注于工业用机器对机器(M2M)无线通信模块的研发与生产。随着技术的不断进步,CINTERION逐渐在行业内崭露头角,其产品在智能电网、汽车、公用事业等领域得到了广泛应用。1996年,CINTERION成功推出了全球第一款蜂窝模组,这一创新为公司在无线通信模组市场打下了坚实的基础。

东晶(ECEC)公司的发展小趣事

随着产品质量的不断提升和市场份额的逐步扩大,东晶电子开始将目光投向国际市场。公司积极参与国际展会,与全球知名电子企业建立合作关系,产品出口到欧洲、北美、东南亚等多个国家和地区。同时,东晶电子还与国际知名厂商进行技术交流和合作研发,不断提升自身技术水平,以适应全球市场的竞争需求。

问答坊 | AI 解惑

红外学习型万能解码遥控开关及调光调速器

有需要请联系我  免费的  截止时间2009.6.28(上班了,就没时间了) [ 本帖最后由 sjl105105 于 2009-6-26 12:31 编辑 ]…

查看全部问答>

在绘制原理图时如何设置标题

在protel99绘制原理图中,要求设置标题。为什么在disign菜单option中设置标题,为什么显示不出来呢…

查看全部问答>

要下载一个设备的SDK,大家帮我看看应该下哪个

CE上开发MC3000的程序,我去MC3000下他的SDK,没有搞清楚应该下载下面的哪个. 1:Platform SDK for MC3000 v1.1 with Windows CE 5.0 Core 2:Platform SDK for MC3000 v1.1 with Windows CE 5.0 Professional 不知道这两个有什么区别. 另外还有一 ...…

查看全部问答>

74HC244内部的三态门是如何实现缓冲和驱动的?

我在用proteus做LPC2132的串口通信仿真时,外接一个虚拟终端和示波器,用示波器来查看数据发送的波形 当把示波器和虚拟终端接在一起然后连到Txd0 Rxd0上时,虚拟终端上面不能显示LPC2132发过来的数据,但是示波器可以看到LPC2132串口数据发送的波 ...…

查看全部问答>

LabVIEW关于定时的研究

1.如果想实现定周期While循环时,需要用Wait(ms).vi而不是Wait Until Next ms Multiple.vi2.Wait(ms).vi在与代码并行时可以保证整个运行时间为设定值,这个功能一般都会以为是Wait Until Next ms Multiple.vi的特性3.Wait Until Next ms Multipl ...…

查看全部问答>

FPGA设计中的异步信号处理

        近来一直在学习在fpga如何进行异步信号的处理,有一些心得,开个贴,把自己的一些体会贴出来,跟大家分享,也期待可以得到高手的指点。       目录如下:  &n ...…

查看全部问答>

IAR中如何在执行main()之间关闭看门狗

IAR中如何在执行main()之间关闭看门狗?论坛上有人问,但是说的不具体。不知道怎么弄。会的告诉一下,谢谢! …

查看全部问答>

基础的LED灯和数码管同时点亮的问题

如题,我在练习的时候遇到了一个可能比较基本的问题:不通过定时器,只写一个delay函数来实现LED灯的闪烁和数码管的点亮。 我自己用这种方式写的(8个LED闪烁,点亮2个数码管),无法实现上述功能。LED能闪烁,但是两位数码管中的第一位不能稳定显 ...…

查看全部问答>

1602取字模软件及其设置

看到论坛里面有用1602显示汉字的,很好奇,也整弄了下 找了个区模的软件,能很好的取模,共享给大家 第一步:先新建一个 x*y  的模; 第二步:自己一个点点自己点; 第三步:使字模左右翻转下; 第四部:设置(看图片) 第五部: ...…

查看全部问答>