历史上的今天
返回首页

历史上的今天

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

正在发生

2019年09月12日 | 秉火429笔记之八 RCC时钟

2019-09-12 来源:eefocus

1. RCC 作用概述

RCC :reset clock control 复位和时钟控制器。


设置系统时钟SYSCLK、设置AHB分频因子(决定HCLK等于多少)、设置APB2分频因子(决定PCLK2等于多少)、设置APB1分频因子(决定PCLK1等于多少)、设置各个外设的分频因子;控制AHB、APB2和APB1这三条总线时钟的开启、控制每个外设的时钟的开启。对于SYSCLK、HCLK、PCLK2、PCLK1这四个时钟的配置一般是:HCLK = SYSCLK=PLLCLK = 180M,PCLK1=HCLK/2 = 90M,PCLK1=HCLK/4 = 45M。如果需要使用USB,HCLK=168M为宜。


2. RCC框图剖析—时钟树


HSE 高速外部时钟信号

外部时钟信号,可由有源晶振或无源晶振提供,频率范围 4-26MHZ。若使用HSE作为时钟源,当HSE故障时,将会切换到HSI,直到HSE恢复正常,HSI=16MHZ.


锁相环PLL

PLL的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。PLL有两个,一个是主PLL,另外一个是专用的PLLI2S,他们均由HSE或者HSI提供时钟输入信号.


主PLL有两路的时钟输出,第一个输出时钟PLLCLK用于系统时钟,F429里面最高是180M,第二个输出用于USB OTG FS的时钟(48M)、RNG和SDIO时钟(<=48M)。专用的PLLI2S用于生成精确时钟,给I2S提供时钟。


HSE或者HSI经过PLL时钟输入分频因子M(2~63)分频后,成为VCO的时钟输入,VCO的时钟必须在1~2M之间,我们选择HSE=25M作为PLL的时钟输入,M设置为25,那么VCO输入时钟就等于1M.


VCO输入时钟经过VCO倍频因子N倍频之后,成为VCO时钟输出,VCO时钟必须在192~432M之间。我们配置N为360,则VCO的输出时钟等于360M。如果要把系统时钟超频,就得在VCO倍频系数N这里做手脚。PLLCLK_OUTMAX = VCOCLK_OUTMAX/P_MIN = 432/2=216M,即F429最高可超频到216M。


VCO输出时钟之后有三个分频因子:PLLCLK分频因子p,USB OTG FS/RNG/SDIO时钟分频因子Q,分频因子R(F446才有,F429没有)。p可以取值2、4、6、8,我们配置为2,则得到PLLCLK=180M。Q可以取值4~15,但是USB OTG FS必须使用48M,Q=VCO输出时钟360/48=7.5,出现了小数这明显是错误,权衡之策是是重新配置VCO的倍频因子N=336,VCOCLK=1M*336=336M,PLLCLK=VCOCLK/2=168M,USBCLK=336/7=48M,细心的读者应该发现了,在使用USB的时候,PLLCLK被降低到了168M,不能使用180M,这实乃ST的一个奇葩设计。因此,通常对时钟无高速需求的情况下,配置为168M为宜。


系统时钟SYSCLK

系统时钟来源可以是:HSI、PLLCLK、HSE,具体的由时钟配置寄存器RCC_CFGR的SW位配置.


AHB总线时钟HCLK

系统时钟SYSCLK经过AHB预分频器分频之后得到时钟叫APB总线时钟,即HCLK,分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器RCC_CFGR的HPRE位设置。


通常情况下,设置为1分频,即HCLK=SYSCLK。


APB2总线时钟HCLK2

APB2总线时钟PCLK2由HCLK经过高速APB2预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器RCC_CFGR的PPRE2位设置。。HCLK2属于高速的总线时钟,片上高速的外设就挂载到这条总线上.


通常情况下,设置为2分频,即PCLK2 = HCLK /2。


APB1总线时钟HCLK1

APB1总线时钟PCLK1由HCLK经过低速APB预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器RCC_CFGR的PPRE1位设置。HCLK1属于低速的总线时钟,最高为45M,片上低速的外设就挂载到这条总线上.


通常情况下,设置为4分频,即PCLK1 = HCLK/4。


RTC时钟

RTCCLK 时钟源可以是 HSE 1 MHz( HSE 由一个可编程的预分频器分频)、 LSE 或者 LSI时钟。选择方式是编程 RCC 备份域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只能通过复位备份域的方式修改。我们通常的做法是由LSE给RTC提供时钟,大小为32.768KHZ。LSE由外接的晶体谐振器产生,所配的谐振电容精度要求高,不然很容易不起震。


独立看门狗时钟

独立看门狗时钟由内部的低速时钟LSI提供,大小为32KHZ


I2S时钟

I2S时钟可由外部的时钟引脚I2S_CKIN输入,也可由专用的PLLI2SCLK提供,具体的由RCC 时钟配置寄存器 (RCC_CFGR)的I2SSCR位配置。我们在使用I2S外设驱动W8978的时候,使用的时钟是PLLI2SCLK,这样就可以省掉一个有源晶振。


ETH PHY以太网时钟

429要想实现以太网功能,除了有本身内置的MAC之外,还需要外接一个PHY芯片,常见的PHY芯片有DP83848和LAN8720,其中DP83848支持MII和RMII接口,LAN8720只支持RMII接口。秉火F429开发板用的是RMII接口,选择的PHY芯片是LAB8720。使用RMII接口的好处是使用的IO减少了一半,速度还是跟MII接口一样。当使用RMII接口时,PHY芯片只需输出一路时钟给MCU即可,如果是MII接口,PHY芯片则需要提供两路时钟给MCU。


USB PHY时钟

F429的USB没有集成PHY,要想实现USB高速传输的话,必须外置USB PHY芯片,常用的芯片是USB3300。当外接USB PHY芯片时,PHY芯片需要给MCU提供一个时钟。外扩USB3300会占用非常多的IO,跟SDRAM和RGB888的IO会复用的很厉害。


MCO时钟输出

MCO是microcontroller clock output的缩写,是微控制器时钟输出引脚,主要作用是可以对外提供时钟,相当于一个有源晶振。F429中有两个MCO,由PA8/PC9复用所得。MCO1所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的 MCO1PRE[2:0] 和 MCO1[1:0]位选择。MCO2所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的 MCO2PRE[2:0] 和 MCO2位选择。


3. 编程要点

开启HSE/HSI ,并等待 HSE/HSI 稳定

设置 AHB、APB2、APB1的预分频因子

设置PLL的时钟来源,设置VCO输入时钟 分频因子PLL_M,设置VCO输出时钟

倍频因子PLL_N,设置PLLCLK时钟分频因子PLL_P,设置OTG FS,SDIO,RNG

时钟分频因子 PLL_Q

开启PLL,并等待PLL稳定

把PLLCK切换为系统时钟SYSCLK

读取时钟切换状态位,确保PLLCLK被选为系统时钟

官方有快捷配置工具

4. 源码实例

#include "./rcc/bsp_clkconfig.h"

#include "stm32f4xx_rcc.h"

 

/*

 * 使用HSE时,设置系统时钟的步骤

 * 1、开启HSE ,并等待 HSE 稳定

 * 2、设置 AHB、APB2、APB1的预分频因子

 * 3、设置PLL的时钟来源

 *    设置VCO输入时钟 分频因子        m

 *    设置VCO输出时钟 倍频因子        n

 *    设置PLLCLK时钟分频因子          p

 *    设置OTG FS,SDIO,RNG时钟分频因子 q

 * 4、开启PLL,并等待PLL稳定

 * 5、把PLLCK切换为系统时钟SYSCLK

 * 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟

 */

 

/*

 * m: VCO输入时钟 分频因子,取值2~63

 * n: VCO输出时钟 倍频因子,取值192~432

 * p: PLLCLK时钟分频因子  ,取值2,4,6,8

 * q: OTG FS,SDIO,RNG时钟分频因子,取值4~15

 * 函数调用举例,使用HSE设置时钟

 * SYSCLK=HCLK=180M,PCLK2=HCLK/2=90M,PCLK1=HCLK/4=45M

 * HSE_SetSysClock(25, 360, 2, 7);

 * HSE作为时钟来源,经过PLL倍频作为系统时钟,这是通常的做法

 

 * 系统时钟超频到216M爽一下

 * HSE_SetSysClock(25, 432, 2, 9);

 */

void HSE_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q)

{

  __IO uint32_t HSEStartUpStatus = 0;

  

  // 使能HSE,开启外部晶振,秉火F429使用 HSE=25M

  RCC_HSEConfig(RCC_HSE_ON);

  // 等待HSE启动稳定

HSEStartUpStatus = RCC_WaitForHSEStartUp();

 

  if (HSEStartUpStatus == SUCCESS)

  {

    // 调压器电压输出级别配置为1,以便在器件为最大频率

// 工作时使性能和功耗实现平衡

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

// HCLK = SYSCLK / 1

RCC_HCLKConfig(RCC_SYSCLK_Div1);

// PCLK2 = HCLK / 2

RCC_PCLK2Config(RCC_HCLK_Div2);

// PCLK1 = HCLK / 4

RCC_PCLK1Config(RCC_HCLK_Div4);

    // 如果要超频就得在这里下手啦

// 设置PLL来源时钟,设置VCO分频因子m,设置VCO倍频因子n,

//  设置系统时钟分频因子p,设置OTG FS,SDIO,RNG分频因子q

RCC_PLLConfig(RCC_PLLSource_HSE, m, n, p, q);

// 使能PLL

RCC_PLLCmd(ENABLE);

  

  // 等待 PLL稳定

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {

    }   

 

/*-----------------------------------------------------*/

    //开启 OVER-RIDE模式,以能达到更高频率

    PWR->CR |= PWR_CR_ODEN;

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

    {

    }

    PWR->CR |= PWR_CR_ODSWEN;

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

    {

    }      

    // 配置FLASH预取指,指令缓存,数据缓存和等待状态

    FLASH->ACR = FLASH_ACR_PRFTEN 

            | FLASH_ACR_ICEN 

            | FLASH_ACR_DCEN 

            | FLASH_ACR_LATENCY_5WS;

/*-----------------------------------------------------*/

// 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

    // 读取时钟切换状态位,确保PLLCLK被选为系统时钟

    while (RCC_GetSYSCLKSource() != 0x08)

    {

    }

  }

  else

  { // HSE启动出错处理

 

    while (1)

    {

    }

  }

}

 

/*

 * 使用HSI时,设置系统时钟的步骤

 * 1、开启HSI ,并等待 HSI 稳定

 * 2、设置 AHB、APB2、APB1的预分频因子

 * 3、设置PLL的时钟来源

 *    设置VCO输入时钟 分频因子        m

 *    设置VCO输出时钟 倍频因子        n

 *    设置SYSCLK时钟分频因子          p

 *    设置OTG FS,SDIO,RNG时钟分频因子 q

 * 4、开启PLL,并等待PLL稳定

 * 5、把PLLCK切换为系统时钟SYSCLK

 * 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟

 */

 

/*

 * m: VCO输入时钟 分频因子,取值2~63

 * n: VCO输出时钟 倍频因子,取值192~432

 * p: PLLCLK时钟分频因子  ,取值2,4,6,8

 * q: OTG FS,SDIO,RNG时钟分频因子,取值4~15

 * 函数调用举例,使用HSI设置时钟

 * SYSCLK=HCLK=180M,PCLK2=HCLK/2=90M,PCLK1=HCLK/4=45M

 * HSI_SetSysClock(16, 360, 2, 7);

 * HSE作为时钟来源,经过PLL倍频作为系统时钟,这是通常的做法

 

 * 系统时钟超频到216M爽一下

 * HSI_SetSysClock(16, 432, 2, 9);

 */

 

void HSI_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q)

{

  __IO uint32_t HSIStartUpStatus = 0;

// 把RCC外设初始化成复位状态

  RCC_DeInit();

  

  //使能HSI, HSI=16M

RCC_HSICmd(ENABLE);

  // 等待 HSI 就绪

HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;

// 只有 HSI就绪之后则继续往下执行

  if (HSIStartUpStatus == RCC_CR_HSIRDY)

  {

    // 调压器电压输出级别配置为1,以便在器件为最大频率

// 工作时使性能和功耗实现平衡

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

// HCLK = SYSCLK / 1

RCC_HCLKConfig(RCC_SYSCLK_Div1);

// PCLK2 = HCLK / 2

RCC_PCLK2Config(RCC_HCLK_Div2);

// PCLK1 = HCLK / 4

RCC_PCLK1Config(RCC_HCLK_Div4);

    // 如果要超频就得在这里下手啦

// 设置PLL来源时钟,设置VCO分频因子m,设置VCO倍频因子n,

//  设置系统时钟分频因子p,设置OTG FS,SDIO,RNG分频因子q

RCC_PLLConfig(RCC_PLLSource_HSI, m, n, p, q);

// 使能PLL

RCC_PLLCmd(ENABLE);

  

  // 等待 PLL稳定

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {

    }   

 

/*-----------------------------------------------------*/

    //开启 OVER-RIDE模式,以能达到更高频率

    PWR->CR |= PWR_CR_ODEN;

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

    {

    }

    PWR->CR |= PWR_CR_ODSWEN;

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

    {

    }      

    // 配置FLASH预取指,指令缓存,数据缓存和等待状态

    FLASH->ACR = FLASH_ACR_PRFTEN 

            | FLASH_ACR_ICEN 

            |FLASH_ACR_DCEN 

            |FLASH_ACR_LATENCY_5WS;

/*-----------------------------------------------------*/

// 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

    // 读取时钟切换状态位,确保PLLCLK被选为系统时钟

    while (RCC_GetSYSCLKSource() != 0x08)

    {

    }

  }

  else

  { // HSI启动出错处理

    while (1)

    {

    }

  }

}

 

 

// MCO1 PA8 GPIO 初始化

void MCO1_GPIO_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  

  // MCO1 GPIO 配置

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  

  GPIO_Init(GPIOA, &GPIO_InitStructure); 

}

 

// MCO2 PC9 GPIO 初始化

void MCO2_GPIO_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  

  // MCO2 GPIO 配置

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}


推荐阅读

史海拾趣

AC Photonics Inc公司的发展小趣事

AC Photonics Inc公司自成立以来,一直致力于光电技术的研发与应用。在公司成立初期,研发团队在光子集成技术上取得了重大突破,成功开发出一种高效、稳定的光电转换器。这一技术的问世,不仅提升了数据传输的速度和稳定性,还大大降低了能耗,为公司的业务发展奠定了坚实的基础。随着这一技术的逐步推广和应用,AC Photonics Inc在电子行业中逐渐崭露头角。

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

天二科技始终将产品质量视为企业的生命线。为了不断提升产品品质,公司引进了先进的自动化设备和生产工艺,并建立了严格的质量控制体系。经过多年的努力,天二科技的产品质量得到了显著提升,并先后通过了ISO9001、TS16949等多项国际质量管理体系认证。这些认证的取得不仅证明了天二科技在产品品质方面的卓越表现,更为公司赢得了客户的信任和市场的认可。

Equator Technologies公司的发展小趣事

Equator Technologies公司成立于XX年代初,当时正值数字视频技术飞速发展的时代。公司凭借其在视频DSP(数字信号处理器)领域的独特见解和技术实力,迅速崭露头角。起初,Equator主要聚焦于提供高性能的视频处理解决方案,用于改善电视和其他显示设备的画质。通过不断的技术创新和产品迭代,Equator逐渐在市场中建立了良好的口碑。

Analog Microelectronics GmbH公司的发展小趣事

面对日益激烈的市场竞争和技术变革,Equator始终保持着持续创新的精神。公司不断投入研发资源,探索新的技术方向和应用场景。例如,在人工智能和机器学习领域,Equator正在积极开展相关研究和实践工作,探索将这些先进技术应用于视频处理领域的可能性。通过持续创新和努力,Equator正致力于引领电子行业未来的发展方向。

EMI Filter Company公司的发展小趣事

AVX公司作为电子元件行业的佼佼者,一直在寻求技术的突破和创新。在EMI滤波器领域,AVX不走寻常路,他们专注于研发高性能的陶瓷EMI滤波器。这种滤波器利用陶瓷材料的特性,能够在高温、高频等恶劣环境下保持稳定的性能。AVX的陶瓷EMI滤波器在市场上独树一帜,深受汽车、航空航天等行业的青睐。

常忆科技(CHINGIS)公司的发展小趣事

展望未来,常忆科技将继续坚持创新驱动的发展战略。公司将不断加大在研发和创新方面的投入,推动产品技术的持续升级和迭代。同时,常忆科技还将积极拓展新的应用领域和市场空间,以满足更多客户的需求。

为了实现可持续发展,常忆科技还将注重环境保护和社会责任。公司将致力于推广绿色环保的生产方式和产品应用,为社会的可持续发展做出贡献。在未来的发展中,常忆科技有望凭借其卓越的技术实力和创新精神,继续在电子行业中书写新的辉煌篇章。

问答坊 | AI 解惑

值得注意的单片机控制板的设计原则

值得注意的单片机控制板的设计原则 需要遵循的原则如下:   (1) 在元器件的布局方面,应该把相互有关的元件尽量放得靠近一些,例如,时钟发生器、晶振、CPU的时钟输入端都易产生噪声,在放置的时候应把它们靠近些。对于那些易产生噪声的器 ...…

查看全部问答>

代码阅读器第一个版本, 请大家试试

代码阅读器第一个版本,   请大家试试 http://code-search.kingofcoder.com/…

查看全部问答>

UBOOT , NBOOT EBOOT 三者有什么区别?

UBOOT , NBOOT  EBOOT  三者有什么区别…

查看全部问答>

烧78E58 ldrom用什么烧录器.

烧78E58 ldrom用什么烧录器.我们公司的烧录器是很老的一个superpro/Z,识别78E58话最大的也就到7FFF,而ldrom烧录的起始位为10000H,找不到这个空间,是不是我的设置不对,如果这个烧录器不能烧ldrom,请帮我介绍一个烧录器.…

查看全部问答>

我的应急灯的一些体会

一,为什么要用LED驱动IC及充电IC           这个是我在昨天看了坛友的发出弱光的那篇文章想到地,其实不用IC也可以的,只不过寿命一定不长,有一个或几个浪涌,LED就淹死了,锂电池也一样.   二, ...…

查看全部问答>

STM32串口设置要注意的问题

在调试STM32的串口程序时发现以下问题: 1、如果将数据位设置为8位,即USART_WordLength_8b,则设置为无校验和偶校验的时候,上位机PC可以正确接收到发送的数据,设置为奇校验的时候则接收到的数据是错误的。 2、将数据位设置为9位,即USART ...…

查看全部问答>

stm32F103RB对冲击电压很敏感,已损坏了几片

现象:输入电流或电压过大,比如5V,stm32F103RB就会损坏。然后我的电路板上的电压就会被拉低,原来3.3V就会变成1V多。 怎样来保护这个芯片呢?现在加了5.0的TVS,管脚端口也加了电阻限流。效果好像也不太好。…

查看全部问答>

中国当代医疗电子的发展如何???

我是一名医学信息工程专业的学生,学习医疗电子,想问问各位前辈这个行业怎么样,发张前景,工资???…

查看全部问答>

电源/负载电路组合的稳定性分析

为了分析2300系列电源/负载电路组合,整个电源建模为由一个理想误差校正放大器、一个理想放大器输出级和一个理想反馈感测放大器组成的反馈网络(见图1)。感测放大器直接测量负载电压,促使电源输出升高电压来克服测试线和夹具的损耗,以确保所需电 ...…

查看全部问答>