历史上的今天
返回首页

历史上的今天

今天是:2024年09月29日(星期日)

正在发生

2018年09月29日 | STM32F4时钟初始化配置

2018-09-29 来源:eefocus

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


推荐阅读

史海拾趣

Crystek公司的发展小趣事

尽管Crystek公司在发展过程中取得了显著的成就,但也面临着一些挑战和困难。例如,随着行业竞争的加剧和市场需求的不断变化,公司需要不断调整战略方向和产品结构以适应市场的变化。同时,公司还需要加强人才培养和团队建设,提升员工的技能水平和创新能力。然而,Crystek公司始终保持着积极进取的态度和勇于面对挑战的精神,相信在未来的发展中,公司将继续保持领先地位并创造更加辉煌的业绩。

这五个故事展示了Crystek公司在电子行业中的发展历程和取得的成就。从创业起步到技术创新、市场拓展、部门专业化以及应对挑战和未来发展,Crystek公司始终保持着积极进取的精神和不断创新的态度,为电子行业的发展做出了重要贡献。

Chengdu Sino Microelectronics Technology Co Ltd公司的发展小趣事

随着国内市场的逐渐饱和,成都华微科技开始将目光投向国际市场。公司凭借过硬的产品质量和完善的服务体系,逐渐在国际市场上崭露头角。通过与国外客户的深入合作,华微科技不仅提升了自身的国际影响力,也为中国集成电路设计行业在国际市场上赢得了更多的话语权。

天二科技(EVER OHMS)公司的发展小趣事

2004年,天二科技迈出了全球化布局的重要一步,在全球范围内建立了销售和技术支持网络。同年,公司在中国大陆成立了分公司,进一步加深了与中国市场的联系。通过全球化布局,天二科技不仅成功拓展了海外市场,还积累了丰富的国际经验,为公司未来的发展提供了有力支持。

Hokuriku公司的发展小趣事

进入80年代,随着电子技术的不断进步和应用领域的拓宽,Hokuriku Electric意识到单一产品线的局限性。于是,公司开始实施多元化产品战略,相继推出了传感器、贴片保险丝、机械零件、电路基板等一系列新产品。这些产品不仅丰富了公司的产品线,还进一步巩固了其在电子行业中的地位。通过多元化布局,Hokuriku Electric成功抵御了市场波动带来的风险,实现了持续稳定的增长。

對餘科技(DIOFIT)公司的发展小趣事

随着科技的不断发展,DIOFIT公司始终将技术创新作为发展的核心驱动力。他们不断投入研发资金,引进先进技术和人才,致力于研发具有自主知识产权的电子产品。在物联网、人工智能等前沿领域,DIOFIT公司取得了一系列突破性的成果,推出了一系列具有竞争力的产品,成为行业内的技术创新引领者。

Ceratech Corporation公司的发展小趣事

在电子行业中,压敏技术是一项重要的技术。Ceratech Corporation公司针对这一领域进行了深入研究和探索。公司研发团队经过多次试验和改进,成功研发出具有自主知识产权的压敏产品。这些产品不仅具有高灵敏度和高稳定性,而且能够适应各种复杂环境。通过压敏技术的研发与应用,Ceratech Corporation进一步提升了其在电子行业的技术实力和市场竞争力。

问答坊 | AI 解惑

如何测电源纹波

最近我想用示波器测一下电源的输出纹波,听说测纹波也是有一定技巧的,哪位大虾可否告知下?…

查看全部问答>

ARM9开发IDE

现在各个公司,开发arm9 的时候都使用什么开发工具啊?linux下的 ADS吗?版本多少的?…

查看全部问答>

求助、Keil新手编译问题。

程序: #include #include main() { SCON = 0x52; TMOD = 0x20; TCON = 0x69 TH1 = 0xf3; printf(\"text to output some words\\n\"); } 报错:TEXT2.C(10): 错误 C141: syntax error near \'TH1\'       目标没 ...…

查看全部问答>

网络最佳兼职

假如你想创业但资金不多或想找个兼职请看这 与您现有的工作相容互补而不冲突             不需要受学历的限制        不需要特殊的专业技能        不需要受 ...…

查看全部问答>

FPGA 视频高手求兼职

本人从事视频ASIC的开发6年,精通H。264/电视信号/VGA编解码,此外,对去隔行,帧率变换(24FPS---〉50或60FPS),SCALER,OSD,JPG/BMP Encoder等也有深刻认识和实际工作经验。现承接视频方面的FPGA或IC设计兼职,还请社会各界朋友多多关照:) ...…

查看全部问答>

PIC的配置位问题

刚开始学PIC单片机 从PIC16F630和PIC18F2480入手  程序编译正确 但是下载到板子上  运行不了 不知道是不是配置位的问题 不知道如何配置 还有I/O口的设置 也不知道该如何正确设置…

查看全部问答>

急!485通信,PC机不能正常接收!

请教大家, 本人用单片机做的控制器通过485与PC机通信,波特率从600-19200,接收全波特率都能正常工作(能按要求指令执行命令,),但超过1200的波特率,PC机接收的就全是乱码了(用的串口调试助手2.1版,使用十六进制数据进行通信),单片机使用S ...…

查看全部问答>

开发板用着用着就漏电了

开发板用着用着就漏电了…

查看全部问答>

PIC32 单片机SPI功能如何关闭

各位大侠,我用的单片机型号是:PIC32MX360F512L,用的引脚是RF8和RF7,对应的是SPI功能的SDO1和SDI1,请问如何关闭spi功能?…

查看全部问答>

看门狗复位的应用技巧

说起看门狗这个名字还是蛮有趣的,它的作用就是在主人走神的时候咬他一口,把他咬醒。实际点来说,就是当MCU运行过程中,在某处进入了死循环,或者受到干扰造成PC指针指向了无程序区,都会导致程序没反应,按键失效,屏幕内容不变等问题。这时如果 ...…

查看全部问答>