历史上的今天
返回首页

历史上的今天

今天是:2025年08月13日(星期三)

正在发生

2018年08月13日 | STM32F407的时钟配置(system_config.c浅见)

2018-08-13 来源:eefocus

入手STM32F4系列是从F4Discovery开始的,板子确实很对得起99元的价格~因为最近要做一个图像识别方面的项目,因此开始在f4上进行编程,之前也写过f103系类的单片机,但时钟方面都是使用别人已经写好的时钟配置函数,没有去仔细考虑,换用了f4之后,分析了一下系统的启动过程,发现system_config.c中的SystemInit函数已经把时钟配置好了,但还有一些地方需要做修改,否则可能会导致时钟启动过程出现错误,现在 写出来,也算是做的个备忘吧。


  startup_stm32f40_41xxx.s是怎么对SystemInit进行调用的呢?见103行:


/* Call the clock system intitialization function.*/

bl  SystemInit


  因此跳到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

}

   可见,该函数打开了HSE,PLL(当然还有一些其他功能,如浮点运算,这里不作讨论),并且在最后引用了setsysclock()


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

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

 

    /* HCLK = SYSCLK / 1*/

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

 

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

    /* PCLK2 = HCLK / 1*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

    

    /* PCLK1 = HCLK / 1*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */

 

#if defined (STM32F401xx)

    /* PCLK2 = HCLK / 2*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;

    

    /* PCLK1 = HCLK / 4*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

#endif /* STM32F401xx */

   

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

    {

    }

   

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

    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */

    PWR->CR |= PWR_CR_ODEN;

    while((PWR->CSR & PWR_CSR_ODRDY) == 0)

    {

    }

    PWR->CR |= PWR_CR_ODSWEN;

    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)

    {

    }      

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

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

#endif /* STM32F427_437x || STM32F429_439xx  */

 

#if defined (STM32F40_41xxx)     

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

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

#endif /* STM32F40_41xxx  */

 

#if defined (STM32F401xx)

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

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;

#endif /* STM32F401xx */

 

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

  }

 

}

  看出,该函数定义了PLL倍频系数,AHB,APB1,APB2时钟(也就是HCLK,PCLK1,PCLK2),根据不同的器件的定义,分别设置了不同的是,时钟频率,可以改变PLL_N,PLL_M,PLL_P,PLL_Q的值,和RCC_CFGR_PPRE2_DIVx,RCC_CFGR_PPRE1_DIVx就可以改变了,x代表分频系数。

  系统时钟具体可以参考以下公式:


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


SYSCLK = PLL_VCO / PLL_P;


  USB时钟,SDIO可以参考:


USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLL_Q;


  比如使用8M的外部晶振,那么PLL_M=8, PLL_N=336, PLL_P=2 就可以配置出168M的系统时钟了。如果PLL_Q=7, USB, SDIO时钟为48M。


另外,还需注意的一点时,PCLK1,也就是APB1时钟不能大于42M,PCLK2不能大于84M,USB,SDIO时钟不能大于48M。


  这样,就可以不用使用自己编写的时钟配置函数了~


推荐阅读

史海拾趣

兵字(BingZi)公司的发展小趣事

随着公司规模的不断扩大和产品线的日益丰富,兵字公司开始注重品牌建设和市场拓展。公司注册了“BingZi兵字”商标,并通过一系列的市场推广活动,提升了品牌的知名度和美誉度。同时,兵字公司还积极开拓国内外市场,与多家知名企业建立了长期稳定的合作关系,实现了业务的快速增长。

Capar Components Corp公司的发展小趣事

作为一家有社会责任感的企业,Capar Components Corp积极参与公益事业,回馈社会。公司定期组织员工参与社区服务活动,帮助困难群体解决实际问题。此外,公司还设立了奖学金和助学金,支持教育事业的发展。这些举措不仅彰显了公司的社会责任感,也为公司树立了良好的企业形象。


这些故事是基于一个虚构的电子行业公司背景编写的,您可以根据Capar Components Corp的实际情况进行调整和修改,以使其更符合该公司的历史和发展轨迹。请注意,由于我无法获取Capar Components Corp的具体信息,这些故事仅为示例性质,并非真实事件。

Electronic Concepts Inc公司的发展小趣事

随着公司规模的不断扩大,ECI越来越重视团队建设。公司高层认识到,一个团结、高效的团队是企业持续发展的关键。在人力资源部经理刘女士的策划下,ECI开展了一系列团队建设活动,如拓展训练、员工分享会等。这些活动不仅增强了员工的凝聚力,也提升了员工的工作效率和创新能力。

GHI Electronics公司的发展小趣事

随着业务的不断拓展,GHI Electronics开始实施全球化战略。公司积极寻求与全球合作伙伴的合作机会,共同开拓新市场。同时,GHI Electronics还在多个国家和地区设立了分支机构或研发中心,以便更好地服务当地客户并快速响应市场需求。这种全球化战略布局不仅增强了GHI Electronics的市场竞争力,也为其带来了更多的商业机会和发展空间。

Catalyst / ON Semiconductor公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,Catalyst / ON Semiconductor公司面临着前所未有的挑战。为了应对这些变革,公司进行了一系列的转型和调整。公司优化了组织架构和管理流程,提高了运营效率;同时,公司还加大了对新兴技术的投入和研发力度,以适应市场的不断变化。

Antenova公司的发展小趣事

Antenova公司在行业内率先推出了第二代GPS射频天线模块,这一创新产品为嵌入式GPS应用提供了高性能的解决方案。该产品的推出不仅树立了行业标杆,还为公司带来了可观的收入增长。同时,Antenova还不断推出其他领先产品,进一步巩固了公司在天线设计领域的领先地位。

问答坊 | AI 解惑

【晒电路】看看这个电路是什么作用?

这个电路发表时就是问是什么电路?…

查看全部问答>

(原创)网络摄像机外接红外对射报警实地测试

   网络摄像机可以外接报警器这个基本上很多人都知道,但怎么接?软件怎么调试?接好之后怎么用?接好之后的网络摄像机和报警器的联动效果到底怎么样?这些问题经常有人来问起,就是解答过后很多朋友也是有点模糊搞,所以今天专门拿了个 ...…

查看全部问答>

3位半表供电电源能不能与测试端 共用一个电源?

最近想了解一下3位半电压表头,曾看到有不能共用的说法,请教诸位: 1,是不是这类表头都有此类问题? 2,会出现什么问题和现象? 3,在仅有一个电源的情况下当如何解决? [ 本帖最后由 liweiliang 于 2010-5-8 22:28 编辑 ]…

查看全部问答>

看看这个电路无法工作的原因。

下载 (28.88 KB) 2010-7-15 21:25 图一 如图:目的在pmos跟nmos输出端得到两路幅度为48v的方波。 我的理解,在图中B、C两点可以得到反相的正负12v(幅度为24v)的控制mos的vgs的波形。 对于pmos,当 ...…

查看全部问答>

关于S3C2410的DMA 实验的问题

实验代码里有: for(i=srcAddr; i…

查看全部问答>

PLC项目寻求合作

一个小型的工控项目,方案待定 要求开发者在上海 请联系 13818699649 范 MSN: fycat@gmail.com…

查看全部问答>

推荐一本嵌入式系统设计的好书

前几天借到一本邱毅凌写的《现代嵌入式系统开发专案实务》,描述了一个beginner到项目经理的故事,易懂有趣,讲了很多一般软件工程书不好讲或者不敢讲的事,有志做项目领导者的朋友不妨读读。…

查看全部问答>

18B20测温

3路18B20测温,没有用单总线,测得3个值里选出1个最大值,显示在数码管上。 //18B20单线温度检测的应用样例程序 #include #include #include #define uchar unsigned char #define uint   unsigned int; /*********************** ...…

查看全部问答>

DSP开发,C语言,#define select_16bit_reg(reg) (* (unsigned int *)LCD_CMD_ADD)...

在用于DSP开发的C语言中, #define select_16bit_reg(reg)(* (unsigned int *)LCD_CMD_ADD) = (reg)    //selet **** control register R** #define write_16bit_data(dat)(* (unsigned int *)LCD_DAT_ADD) = (dat)     ...…

查看全部问答>

【新加坡】某大型半导体公司招聘 IC验证工程师,急!

       本人是从事猎头工作的,目前全国各地有大量通信类招聘职位,包含研发经理,项目经理,软件开发工程师,测试工程师,硬件工程师,FPGA,Soc,构架师,技术支持等,询问全国各地职位情况请发邮件至lrbwmy@sina.com,谢谢 ...…

查看全部问答>