上一篇介绍了 系统时钟的来源、时钟树 以及 PLL1 分路的配置步骤。我们注意到,PLL2、PLL3是固定倍频,无法修改,但是他们下分的 PFDx 分路是可以修改的。只不过我们在初始化的时候,依然按照官方给定的频率进行初始化。
目录
一、了解相关寄存器
二、PLL2_PFDx 初始化
三、PLL3_PFDx 初始化
一、了解相关寄存器
现在只知道要设置 PLL2_PFDx 和 PLL3_PFDx 的频率,但是不知道要通过哪个寄存器设置。我们可以在第 18 章的 Functional Description 下找到 PFD 时钟分路配置对应的寄存器。
当 PLL 从断电变为上电加载时或者因为被修改处于重新锁定状态时,要求 CCM_ANALOG_PFD_480n 或者 CCM_ANALOG_PFD_528n 寄存器的 PFDx_CLKGATE 位在PLL锁定后,有一个从 1 变为 0 的过程。
这是下面的第一句话,从这句话我们可以得到的信息有:
- 修改PLL2_PFDx:需要操作 CCM_ANALOG_PFD_528n 寄存器
- 修改PLL3_PFDx:需要操作 CCM_ANALOG_PFD_480n 寄存器
- 共通点:都需要操作 PFDx_CLKGATE 位,设为 0
二、PLL2_PFDx 初始化
PLL2_PFDx 由 CCM_ANALOG_PFD_528 寄存器控制。我们会发现,PFD0~3,每一个PFDx都有一组字段,以PFD0为例:
- PFD0_FRAC:PLL2_PFD0 的分频数,计算公式如下,其中PFD0_FRAC的取值范围为 12~35。假设我们按照官方给定的 PLL2_PFD0 的值设为 352,那么 PFD0_FRAC 应该等于 27,即 PFD0_FRAC 字段应该设为 0x1b
PLL2_PFD0 = 528 × 18 / PFD0_FRAC
- PFD0_STABLE:该字段为只读,仅用于判断 PLL2_PFD0 是否稳定
- PFD0_CLKGATE:
- 设为 1,分频器禁用,即关闭 PLL2_PFD0 输出 ;
- 设为 0,分频器启用,即使能 PLL2_PFD0 输出
PLL2一共有四路,所以我们要依次计算每一路的分频数。
寄存器: CCM_ANALOG_PFD_528
基地址: 0x20C8100
初始化操作:
unsigned int reg = 0;
reg |= (27 << 0); // PFD0 分频数(27)
reg &= ~(1 << 7); // 分频使能
reg |= (16 << 8); // PFD1 分频数(16)
reg &= ~(1 << 15); // 分频使能
reg |= (23 << 16); // PFD2 分频数(23)
reg &= ~(1 << 23); // 分频使能
reg |= (47 << 24); // PFD3 分频数(47)
reg &= ~(1 << 31); // 分频使能
CCM_ANALOG_PFD_528 = reg;
三、PLL3_PFDx 初始化
PLL3_PFDx 的初始化过程和PLL2_PFDx 是一样的,PLL3_PFDx 由 CCM_ANALOG_PFD_480 寄存器控制。不同之处在于分频数的计算公式。
- PFD0_FRAC:PLL3_PFD0 的分频数
PLL2_PFD0 = 480 × 18 / PFD0_FRAC
- PFD0_STABLE:该字段为只读,仅用于判断 PLL3_PFD0 是否稳定
- PFD0_CLKGATE:
- 设为 1,分频器禁用,即关闭 PLL2_PFD0 输出 ;
- 设为 0,分频器启用,即使能 PLL2_PFD0 输出
寄存器: CCM_ANALOG_PFD_480
基地址: 0x20C80F0
初始化操作:
unsigned int reg = 0;
reg |= (12 << 0); // PFD0 分频数(12)
reg &= ~(1 << 7); // 分频使能
reg |= (16 << 8); // PFD1 分频数(16)
reg &= ~(1 << 15); // 分频使能
reg |= (17 << 16); // PFD2 分频数(17)
reg &= ~(1 << 23); // 分频使能
reg |= (18 << 24); // PFD3 分频数(18)
reg &= ~(1 << 31); // 分频使能
CCM_ANALOG_PFD_480 = reg;