通过STM32F107和STM32F746对比,学习STM32F746-discory开发板。打开2个芯片的示例工程后,能看到大致相同:
两个工程下启动文件,堆栈初始化和复位处理一致,复位处理分别调用system_stm32f7xx.c文件、system_stm32f10x.c文件下SystemInit函数,对时钟初始化;这篇帖子主要分下下STM32F107和STM32F746时钟树,先从STM32F107开始。
0
|
|
|
|
(STM32F101 102 103 105 107advanced ARM_-based 32-bit MCUsCD00171190.pdf参考手册8.2Clocks,第7章针对STM32F101 102 103系列)
|
|
|
|
|
Bits 7:4 PREDIV2[3:0]: PREDIV2 division factor Set and cleared by software to select PREDIV2 division factor. These bits can be written only when both PLL2 and PLL3 are disabled. 0100: PREDIV2 input clock divided by 5 Bits 3:0 PREDIV1[3:0]: PREDIV1 division factor Set and cleared by software to select PREDIV1 division factor. These bits can be written only when PLL is disabled. Note: Bit(0) is the same as bit(17) in the RCC_CFGR register, so modifying bit(17) in the RCC_CFGR register changes Bit(0) accordingly. 0111: PREDIV1 input clock divided by 8注释:PREDIV1输入时钟8分频 - 2)Clock configuration register (RCC_CFGR),配置PLL输入时钟源,HCLK、PCLK1、 PCLK2时钟
|
|
|
|
|
Bits 21:18 PLLMUL[3:0]: PLL multiplication factor
These bits are written by software to define the PLL multiplication factor. They can be written only
when PLL is disabled.
0111: PLL input clock x 9
Caution: The PLL output frequency must not exceed 72 MHz.
Bit 17 PLLXTPRE: LSB of division factor PREDIV1
Set and cleared by software to select the least significant bit of the PREDIV1 division factor.
It is the same bit as bit(0) in the RCC_CFGR2 register, so modifying bit(0) in the RCC_CFGR2 register
changes this bit accordingly.
If bits[3:1] in register RCC_CFGR2 are not set, this bit controls if PREDIV1 divides its input clock by
|
|
|
|
|
Bits 14:14 ADCPRE[1:0]: ADC prescaler
Set and cleared by software to select the frequency of the clock to the ADCs.
00: PCLK2 divided by 2
01: PCLK2 divided by 4
10: PCLK2 divided by 6
11: PCLK2 divided by 8
Bits 13:11 PPRE2[2:0]: APB high-speed prescaler (APB2)
Set and cleared by software to control the division factor of the APB High speed clock (PCLK2).
0xx: HCLK not divided
|
|
|
|
|
//设置HCLK=72MHz、PCLK2=72MHz、 PCLK1=36MHz:
/* HCLK = SYSCLK HPRE: AHB prescaler,AHB clock 0xxx: SYSCLK not divided*/
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK APB high-speed prescaler (APB2),PCLK2*/
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK/2 PPRE1: APB low-speed prescaler (APB1),PCLK1 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
//配置STM32F10X_CL互联型系统时钟:
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
//注释:相应位清零
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
//注释:PLL2输入HSE时钟5分频,8倍频;PREDIV1输入8分频
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
//注释:对PLL输入源及分频、倍频位清零
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
//注释:PLL时钟源选择PREDIV1,9倍频
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
|
|
|
|
|
- 3.使用“STM32CubeMX”软件,查看STM32F107VC时钟树:
|
|
|
|
|
放大后如下,25MHz HSE输入时钟,prediv2经5分频,PLL2MUL经8倍频,PLL2CLK为40MHz,Prediv1时钟源选择PLL2
|
|
|
|
|
(STM32F75xxx 和 STM32F74xxx 中文参考手册.pdf 5.2 时钟)
|
|
|
|
|
关于PLL 介绍如下:
该器件具有三个 PLL:
l主 PLL (PLL) 由 HSE或 HSI 振荡器提供时钟信号,并具有两个不同的输出时钟:
–第一个输出用于生成高速系统时钟(最高达 216 MHz )
–第二个输出用于为 USB OTG FS 、SDMMC 和 RNG生成 48 MHz 时钟。
lPLLI2S 用于生成精确时钟,从而在 I2S 、SAI和 SPDIFRX接口实现高品质音频性能。
lPLLSAI 用于为 SAI 接口生成时钟,生成 LCD-TFT时钟以及可供 USB OTG FS、SDMMC
和 RNG选择的 48 MHz (PLLSAI48CLK)时钟。
由于在PLL使能后主PLL配置参数便不可更改,所以建议先对PLL进行配置,然后再使能
(选择 HSI 或 HSE振荡器作为 PLL时钟源,并配置分频系数 M、N 、P和 Q)
|
|
|
|
|
- 1.RCC PLL 配置寄存器 (RCC_PLLCFGR)
位27:24 PLLQ[3:0]:主PLL (PLL)分频系数,适用于 USB OTG FS、SDIO 和随机数发生器时钟(Main PLL (PLL) division factor for USB OTG FS, SDIO and random number generator clocks)
|
|
|
|
|
由软件置 1 或清零,用于控制 USB OTG FS时钟、随机数发生器时钟和 SDMMC时钟的频
率。仅在 PLL 已禁止时才能写入这些位。
注意:为使 USB OTG FS能够正常工作,需要 48 MHz的时钟。对于 SDMMC 和随即数生
成器,频率需要低于或等于 48 MHz 才可正常工作。
USB OTG FS 时钟频率 = VCO频率 / PLLQ ,其中,2≤ PLLQ≤15
1001:PLLQ = 9
位 22 PLLSRC :主 PLL (PLL)和音频 PLL (PLLI2S) 输入时钟源 (Main PLL(PLL) and audio PLL (PLLI2S)
entry clock source)
由软件置 1 和清零,用于选择 PLL和 PLLI2S时钟源。此位只有在 PLL和 PLLI2S已禁止时
才可写入。
0:选择 HSI 时钟作为 PLL和 PLLI2S时钟输入
1:选择 HSE振荡器时钟作为 PLL和 PLLI2S时钟输入
|
|
|
|
|
位 17:16 PLLP[1:0]:适用于主系统时钟的主 PLL (PLL)分频系数 (Main PLL (PLL) division factor for main
system clock)
由软件置 1 和清零,用于控制常规 PLL输出时钟的频率。这些位只能在 PLL已禁止时写入。
注意:软件必须正确设置这些位,使其在此域中不超过 180 MHz。
PLL 输出时钟频率 = VCO频率 / PLLP,其中,PLLP = 2、4、6或 8
00:PLLP = 2
位 14:6 PLLN[8:0] :适用于 VCO的主 PLL (PLL) 倍频系数 (Main PLL (PLL) division factor for main
system clock)
由软件置 1 和清零,用于控制 VCO的倍频系数。这些位只能在 PLL已禁止时写入。写入这
些位时只允许使用半字和字访问。
注意:软件必须正确设置这些位,确保 VCO输出频率介于 192 和 432 MHz之间。以下是
一个 PLL输入的 PLLN 位域禁用值 FPLL_IN= 1 MHz的示例:
VCO 输出频率 = VCO输入频率× PLLN ,其中,192≤PLLN≤432
110110000 :PLLN = 432
|
|
|
|
|
位 5:0 PLLM[5:0] :适用于主 PLL(PLL 、PLLI2S 和 PLLSAI )输入时钟的分频系数 (Division factor
for the main PLLs (PLL, PLLI2S and PLLSAI) input clock)
由软件置 1 和清零,用于在 VCO之前对 PLL和 PLLI2S输入时钟进行分频。这些位只有在
PLL 和 PLLI2S已禁止时才可写入。
注意:软件必须正确设置这些位,确保 VCO输入频率介于 1 和 2 MHz 之间。建议选择 2 MHz
的频率,以便限制 PLL抖动。
VCO 输入频率 = PLL 输入时钟频率 / PLLM ,其中,2≤ PLLM ≤ 63
001001:PLLM = 9
由HSE=25MHz,M=25,N=432,P=2,Q=9,计算f(vco) = 432MHz,
f(PLL常规时钟输出)=216MHz,f(USB OTG FS 、SDMMC 、RNG 时钟输出)=48MHz
|
|
|
|
|
2.时钟配置源码:
main.c文件中,SystemClock_Config函数:
void SystemClock_Config(void)
{
//注释:使用系统库函数,初始化结构体
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
//注释:PLL时钟源选择HSE,M分频因子25,N倍频因子432
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
|
|
|
|
|
- 3.使用“STM32CubeMX”软件,查看STM32F746NG时钟树:
|
|
|
|
|
放大后如下:
|
|
|
|
|