【发布时间】:2021-08-28 11:17:32
【问题描述】:
我一直在尝试在 STM32H7B3 板上设置 PLL 时钟频率,我可以通过在下面的代码中设置 DIVN 乘法器 (RCC_PLL1DIVR_N1) 来实现。上次我能够成功执行此操作是将乘数设置为 1。当我尝试下载乘数设置为 0x18F (= 399) 的代码时,我收到了上述错误消息。我现在意识到,由于 sys_ck 规范,我应该尝试的最大值可能是 DIVN = 280,但尽管如此,错误发生在下载代码时,而不是运行它。我尝试使用重置按钮,但无济于事。我现在无法连接到开发板,我不知道还能尝试什么。
RCC -> CFGR &= 0; // Reset register
int32_t cfgr = RCC -> CFGR;
int32_t sws_pll1 = RCC_CFGR_SWS_PLL1;
int32_t status = cfgr & sws_pll1;
while (!status) {
cfgr = RCC -> CFGR;
sws_pll1 = RCC_CFGR_SWS_PLL1;
status = cfgr & sws_pll1;
} // System clock switch status: Wait until PLL1 is system clock; TODO: hangs*/
// RCC source control register
RCC->CR |= RCC_CR_HSION; // HSI clock enable
while (!(RCC->CR & RCC_CR_HSIRDY)); // Wait until HSI clock is ready
/* -------- PLL Config -------- */
// RCC PLLs clock source selection register
RCC -> PLLCKSELR |= RCC_PLLCKSELR_PLLSRC_HSI; // Select HSI as PLL clock source (hsi_ck)
// Note: Must have PLL1ON = 0 for modifying prescaler
RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1; // Reset prescaler for PLL1 to disabled
RCC -> PLLCKSELR |= RCC_PLLCKSELR_DIVM1_5; // Set prescaler for PLL1 to divsion by 32
// RCC PLL1 fractional divider register
RCC -> PLL1FRACR = 0; // Set FRACN to 0
// RCC PLLs configuration register
RCC -> PLLCFGR |= RCC_PLLCFGR_PLL1FRACEN; // PLL1 franctional latch enable
RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLL1VCOSEL; // Select PLL1 output frequency range: wide VCO range from 128 to 560 MHz
RCC -> PLLCFGR |= RCC_PLLCFGR_PLL1RGE_3; // Select PLL1 input reference frequency range: between 8 and 16 MHz
// Note: Must have PLL1ON = 0 and PLL1RDY = 0 for enabling divider output
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVP1EN; // PLL1 DIVP divider output enable
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVQ1EN; // PLL1 DIVQ divider output enable
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVR1EN; // PLL1 DIVR divider output enable
// RCC PLL1 dividers configuration register
// Note: Must have PLL1ON = 0 and PLL1RDY = 0 for writing bits
RCC -> PLL1DIVR &= 0; // Reset register
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_N1_Pos) & RCC_PLL1DIVR_N1; // DIVN = 0x18F = 399
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_P1_Pos) & RCC_PLL1DIVR_P1; // DIVP = 1
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_Q1_Pos) & RCC_PLL1DIVR_Q1; // DIVQ = 1
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_R1_Pos) & RCC_PLL1DIVR_R1; // DIVR = 1
// RCC source control register
RCC -> CR |= RCC_CR_PLL1ON; // PLL1 enable
//while((RCC -> CR & RCC_CR_PLL1RDY) == 0); // Wait until PLL1 clock is ready; TODO: hangs
更新:我运行了 JLinkSTM32,但它打印了以下内容:
Connecting to J-Link via USB...O.K.
Using SWD as target interface.
Target interface speed: 1000 kHz.
VTarget = 3.299V
Reset target...O.K.
Reset option bytes to factory settings...
Option bytes reset to factory settings.
Resetting option bytes failed.
Press any key to exit.
【问题讨论】:
-
虽然我通常不喜欢它,但 STM32CubeMX 工具有一个时钟树工具,可以根据所需的系统时钟、I2S、USB、AHB 等时钟速率等约束条件为您确定 PLL 和分频器设置。如果您手动使用它,它将突出显示冲突。您不必使用其生成的代码,只需将设置复制到您自己的代码中即可。鉴于各种 STM32 部件上时钟树的差异和复杂性,我推荐它。一些较旧的部件为此提供了电子表格,但您必须设法让 Excel 运行宏才能使其正常工作。
-
这个乘数对我来说似乎很疯狂。上次我做 PLL 时,我使用了 mul 8 div 2 之类的东西。我同意 @Clifford 使用我的时钟树来降低值。
-
@Sorenp 我使用 DIVM 除以 32,使用 DIV(P/Q/R) 除以 2,因此 64 MHz HSI 时钟变为 1 MHz,然后乘以 DIVN 的值。它可能高于应有的水平,但低于 2 倍。
-
@Sorenp 我认为他指的是那里的 DIVNx 值,而不是乘数。 STM32 PLLS 和时钟树非常灵活和复杂,H7 是一个 280MHz 的部分,可以使用 4MHz 外部晶振或振荡器运行,并具有三个独立的 PLLS。
标签: c embedded stm32 clock segger-jlink