是的,可以在内部生成40MHz时钟并将PLL时钟设置为40MHz,使用外部24MHz的时钟源。以下是实现步骤和关键配置:
使用以下寄存器配置(寄存器名称需根据具体芯片手册调整):
// 1. 启用外部24MHz晶振作为参考源
EXT_CLK_CR |= (1 << EXT_CLK_EN); // 启用外部时钟
while (!(EXT_CLK_SR & EXT_CLK_RDY)); // 等待时钟稳定
// 2. 配置PLL分频器(将24MHz分频到适合VCO的输入频率)
PLL_DIV_REG = (REF_DIV_3 << REF_DIV_POS); // 参考分频器 = 3 → 24MHz / 3 = 8MHz
// 3. 配置PLL倍频器(生成目标VCO频率)
PLL_MUL_REG = (FB_MUL_20 << FB_MUL_POS); // 倍频器 = 20 → 8MHz * 20 = 160MHz
// 4. 配置PLL后分频(降频到40MHz)
PLL_OUT_DIV_REG = (OUT_DIV_4 << OUT_DIV_POS); // 后分频 = 4 → 160MHz / 4 = 40MHz
// 5. 启用PLL
PLL_CR |= (1 << PLL_ENABLE); // 启动PLL
while (!(PLL_SR & PLL_LOCK)); // 等待PLL锁定
// 6. 将系统时钟切换到PLL输出
SYS_CLK_SEL = SYS_CLK_PLL_SOURCE; // 选择PLL作为主时钟| 参数 | 值 | 说明 |
|---|---|---|
| 外部时钟频率 | 24MHz | MHzECO引脚输入频率 |
| 参考分频(R) | 3 | 输入分频:24MHz / 3 = 8MHz |
| 反馈倍频(F) | 20 | VCO频率:8MHz × 20 = 160MHz (需在芯片VCO范围内) |
| 后分频(O) | 4 | 输出分频:160MHz / 4 = 40MHz |
| 最终输出频率 | 40MHz | PLL目标频率 |
VCO范围检查:
确保160MHz在芯片PLL的VCO工作范围内(例如,STM32的PLL VCO范围通常为100-500MHz,需查阅数据手册)。
寄存器名称:
上述代码中的寄存器名称(如PLL_DIV_REG, PLL_MUL_REG)需替换为具体芯片的寄存器名(例如STM32的RCC_PLLCFGR)。
时钟安全:
切换时钟后,需验证系统时钟频率:
uint32_t sysclk = SystemCoreClock; // 应返回40MHz时钟树冲突:
确保PLL输出未与其他外设时钟冲突(如USB需要48MHz时,需单独分频)。
// STM32F4xx示例(使用HSE=24MHz生成40MHz系统时钟)
RCC_OscInitTypeDef osc = {
.OscillatorType = RCC_OSCILLATORTYPE_HSE,
.HSEState = RCC_HSE_ON,
.PLL = {
.PLLState = RCC_PLL_ON,
.PLLSource = RCC_PLLSOURCE_HSE,
.PLLM = 3, // 输入分频:24MHz / 3 = 8MHz
.PLLN = 20, // VCO倍频:8MHz * 20 = 160MHz
.PLLP = 4, // 系统时钟分频:160MHz / 4 = 40MHz
.PLLQ = 8 // 其他分频(如USB)
}
};
HAL_RCC_OscConfig(&osc);
// 设置系统时钟源为PLL
RCC_ClkInitTypeDef clk = {
.ClockType = RCC_CLOCKTYPE_SYSCLK,
.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK
};
HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_1);
注意:实际参数需根据芯片型号调整,始终以数据手册中的时钟树和寄存器描述为准。
此方案在保证VCO频率合法的前提下,通过分频/倍频组合将24MHz转换为精确的40MHz系统时钟。
举报
更多回帖