N32H762IIL时钟树

一、时钟树

一、目标

  • 外部晶振 HSE = 25 MHz
  • 最终系统主频 sys_clk = 600 MHz
  • 需要通过 PLL 升频,选择合适的 PLL 参数
  • 确保各模块时钟合理分配(CPU、总线、外设等)

📐 二、时钟源与 PLL 架构解析(基于图2)

✅ 1. 时钟源输入

频率 类型
HSE (OSC_IN) 25 MHz 外部高速晶振
MSI 16 MHz 内部RC
HSI 64 MHz 内部高速RC
LSE 32.768 kHz 外部低速晶振
LSI 32 kHz 内部低速RC

我们选用 HSE = 25 MHz 作为 PLL 的输入源。


✅ 2. PLL 结构(图2右半部分)

芯片支持多个 PLL:

  • PLL1 → 输出 pll1_a, pll1_b, pll1_c(用于 CPU 和总线)
  • PLL2 , PLL3 → 可能用于图像、音频等
  • SHRPLL → 用于高速接口(如 PHY)

我们重点关注 PLL1 ,因为它驱动了 M7 CPUAXI bus clock

PLL1 输入选择(PLLSRC)
复制代码
PLLSRC: 选择 HSE (25 MHz)
PLL1 内部结构:
  • VCO 输入频率范围:440 MHz ~ 800 MHz
  • VCO 输出频率 = (HSE * NF) / NR
  • 输出频率 = VCO / ND

其中:

  • *NF:倍频系数(Numerator of Multiplication)
  • /NR:分频系数(Pre-divider)
  • /ND:后分频(Post-divider)

⚙️ 三、计算:如何用 25 MHz 得到 600 MHz?

目标:sys_clk = 600 MHz

在图1中可以看到:

  • sys_clk 来自 MUX,可以选择 pll1_a_clkpll2_a_clk
  • sys_clk 经过 Divider 后成为 sys_div_clk(即 600 MHz)
  • 最终给 M7 CPU 的时钟是 M7 CPU clock,它来自 sys_div_clk,通常不额外分频

所以我们需要:

pll1_a_clk = 600 MHz

pll1_a_clk 是由 PLL1 的 s_pll1_a_clk 经过 CLK_DIV 分频得到的。

但注意:

  • 图2 中 s_pll1_a_clkVCO 输出 经过 PLL1ADIV 分频后的结果
  • 所以我们要先让 VCO 输出足够高,再分频到 600 MHz

设计 PLL1 参数

步骤1:确定 VCO 输出频率

我们希望 s_pll1_a_clk = 600 MHz

假设 PLL1ADIV = 1(不分频),则 VCO 必须输出 600 MHz

VCO 范围:440 MHz ~ 800 MHz → ✅ 600 MHz 在范围内

所以:

  • VCO_freq = 600 MHz
步骤2:计算 PLL1 倍频因子

输入 = HSE = 25 MHz

VCO = (HSE × NF) / NR = 600 MHz

复制代码
(25 × NF) / NR = 600
→ NF / NR = 600 / 25 = 24

所以可以取:

  • NF = 24
  • NR = 1

✅ 满足条件

注意:某些芯片要求 NF ≥ 8,且 NR 为整数。24/1 是合法值。

步骤3:设置 PLL1ADIV

为了得到 s_pll1_a_clk = 600 MHz,我们不需要分频:

  • PLL1ADIV = 1(即 CLK_DIV = 1)

✅ PLL1 配置总结

表格

参数
PLL1SRC HSE (25 MHz)
NF 24
NR 1
ND (for s_pll1_a_clk) 1
PLL1ADIV 1
PLL1EN Enable

→ 输出 s_pll1_a_clk = 600 MHz


🔄 四、系统时钟路径(图1)

1. 主系统时钟选择

在图1顶部:

  • sys_clk 选择器(MUX)连接到:
    • pll1a_clk → ✅ 我们选这个
    • pll2a_clk, pll3a_clk, shrpll_clk, hsi_clk, msi_clk, lse_clk

所以我们配置:

sys_clk = pll1a_clk = 600 MHz


2. 系统分频(sys_div_clk)

图1中:

  • sys_clk 进入一个 Divider ,输出 sys_div_clk
  • 默认可能不除(divider=1),所以 sys_div_clk = 600 MHz

→ 用于驱动:

  • M7 CPU clock
  • AXI bus clock

✅ 所以 M7 CPU 运行在 600 MHz


3. 总线时钟配置

图1底部显示:

  • AHBx, APBx 等总线时钟都来源于 sys_div_clk 或其分频

例如:

  • AHB9 Bus clock = 300 MHz(由 sys_div_clk / 2 得来)
  • APB1 Bus clock = 150 MHz(sys_div_clk / 4

这些可以通过 ICG(Clock Gating)控制


4. 其他重要模块时钟

表格

模块 时钟来源 频率
M4 CPU M4 CPU clock = 300 MHz(来自 sys_div_clk / 2 300 MHz
AXI SRAM AXI bus clock = 600 MHz 600 MHz
DCMU sys_div_clk 600 MHz
EXT1 sys_div_clk 600 MHz
I/O Pads IO clocks 可配置,一般 ≤ 100 MHz

🔧 五、完整时钟树配置表(基于 25MHz HSE → 600MHz)

表格

模块 时钟源 频率 配置说明
HSE 外部晶振 25 MHz 使用 25 MHz 晶振
PLL1 Input HSE 25 MHz PLL1SRC = HSE
PLL1 VCO (25 × 24) / 1 = 600 MHz 600 MHz NF=24, NR=1
s_pll1_a_clk VCO / 1 600 MHz PLL1ADIV = 1
sys_clk MUX → pll1a_clk 600 MHz 选择 PLL1A 输出
sys_div_clk sys_clk / 1 600 MHz 不分频
M7 CPU Clock sys_div_clk 600 MHz 主处理器运行频率
AXI Bus Clock sys_div_clk 600 MHz 高速总线
M4 CPU Clock sys_div_clk / 2 300 MHz 二级 CPU
AHBx Bus Clock sys_div_clk / 2 300 MHz 外设总线
APBx Bus Clock sys_div_clk / 4 150 MHz 低速外设
I/O Pad Clock IO clocks ≤100 MHz 通常由独立分频器生
cpp 复制代码
ErrorStatus ConfigureSystemClock_600MHz(void)
{
   
RCC_DeInit();  // 复位时钟系统

/* 1. 使能并等待HSE时钟稳定 */
RCC_ConfigHse(RCC_HSE_ENABLE);  // 使能 HSE

if(RCC_WaitHseStable() == SUCCESS)  // 等待HSE时钟起振稳定
{
    /* 2. 配置系统时钟分频 */
    RCC_ConfigSysclkDivider(RCC_SYSCLK_DIV1);           // 系统时钟 = 600 MHz
    RCC_ConfigSysbusDivider(RCC_BUSCLK_DIV2);           // AHB = 300 MHz
    
    /* 3. 配置内核和总线时钟源 */
    RCC_ConfigM7Clk(RCC_M7HYPERCLK_SRC_PLL1A);
    RCC_ConfigAXIClk(RCC_AXIHYPERCLK_SRC_PLL1A);
    
    /* 4. 配置总线分频 */
    RCC_ConfigAXIclkDivider(RCC_AXICLK_DIV2);           // AXI 时钟 = 300 MHz
    RCC_ConfigAXIHyperDivider(RCC_AXICLK_HYP_DIV2);     // AXI HyperRAM 时钟
    __RCC_DELAY_US(1);  // 等待分频器稳定
    
    /* 5. 配置APB总线分频 */
    RCC_ConfigAPBclkDivider(RCC_APB1CLK_DIV2, RCC_APB2CLK_DIV2, 
                           RCC_APB5CLK_DIV2, RCC_APB6CLK_DIV2);
    
   
        
      
        RCC_ConfigPll1(RCC_PLL_SRC_HSE, 25000000, 600000000, ENABLE);
        
        /* 9. 等待PLL1锁定 */
         __RCC_DELAY_US(10);  
        
        /* 10. 配置PLL1分频器 */
        RCC_ConfigPLL1ADivider(RCC_PLLA_DIV1);  // PLL1A = 600MHz
        RCC_ConfigPLL1BDivider(RCC_PLLB_DIV1);  // PLL1B = 600MHz
        RCC_ConfigPLL1CDivider(RCC_PLLC_DIV1);  // PLL1C = 600MHz
        
        /* 11. 等待分频器稳定 */
        __RCC_DELAY_US(2);
        
        /* 12. 切换系统时钟源到PLL1A */
        RCC_ConfigSysclk(RCC_SYSCLK_SRC_PLL1A);
        
        /* 13. 等待时钟切换完成 */
        uint32_t timeout = 1000;  // 超时计数器
        while(RCC_GetSysclkSrc() != RCC_SYSCLK_STS_PLL1A)
        {
            timeout--;
            if(timeout == 0)
            {
                // 时钟切换失败处理
                // Error_Handler();
                break;
            }
        }
        
        /* 14. 更新SystemCoreClock全局变量 */
        SystemCoreClock = 600000000;  // 更新系统时钟频率
        SystemD2Clock = 300000000;    // 更新D2域时钟频率
        
       
		return SUCCESS;
} // HSE稳定成功
else
{
    // HSE启动失败处理
    return ERROR;
}
}
cpp 复制代码
#define __RCC_DELAY_US(usec)     do{                                       \
                                    uint32_t delay_end;                   \
                                    CPU_DELAY_INTI();                     \
                                    /* Delay*/                            \
                                    delay_end = DWT_CYCCNT + (usec * (600000000/1000000)); \
                                    while(DWT_CYCCNT < delay_end){};      \
                                    CPU_DELAY_DISABLE();                  \
                                  }while(0) 

void MCU_Init(void)
{
	  if(ConfigureSystemClock_600MHz()==SUCCESS)
	  {
		  USART1_Config(115200);
	      usart1_printf("USE HSE!\r\n");
	  }
	  else
	  {
		   USART1_Config(115200);
		  usart1_printf("USE HSI!\r\n");
		  RCC_SetSysClkToMode0();
	   }
	      TIM1_Config();
	      TIM3_Config();
          GetClkFreqTime =0;
}
相关推荐
良许Linux2 小时前
汽车电子技术和汽车网络
网络·单片机·嵌入式硬件·汽车·嵌入式·制造
forAllforMe2 小时前
STM32 中断分组解析 说明,以及优先级
stm32·单片机·嵌入式硬件
不脱发的程序猿2 小时前
嵌入式Linux:阻塞式I/O与非阻塞式I/O
linux·服务器·单片机·嵌入式硬件·嵌入式
炸膛坦客2 小时前
单片机/C语言八股:(三)C 语言编译器的优化功能,包括 keil(仅作了解)
c语言·单片机·嵌入式硬件
csg11073 小时前
PIC单片机高阶实战(一):PIC32MX振荡器与定时器
单片机·嵌入式硬件·物联网
逐步前行3 小时前
STM32_GPIO_标准库操作
stm32·单片机·嵌入式硬件
LCG元3 小时前
USB设备开发:STM32F105实现USB HID设备,虚拟串口通信实战
stm32·单片机·嵌入式硬件
香水5只用六神3 小时前
【TIM】基本定时器定时实验(2)
c语言·开发语言·stm32·单片机·嵌入式硬件·mcu·学习
阿拉斯攀登3 小时前
【瑞芯微 RK 系列 + 安卓驱动全栈教程】博客系列
嵌入式硬件·安卓·瑞芯微·rk3576·嵌入式安卓·安卓驱动