STM32 笔记:时钟配置

记录 STM32F4 的时钟树配置、PLL 计算过程与 DWT 微秒计时用法。

周一 1月 05 2026
348 字 · 3 分钟

一、时钟配置

void SystemClock_Config(void)
{
/* RCC振荡器配置结构体 */
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* RCC总线时钟配置结构体 */
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
//使能 PWR电源控制模块时钟。
__HAL_RCC_PWR_CLK_ENABLE();
//168M
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;//外部高速晶振
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;//关闭内部高速RC振荡
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;//PLL源
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;//系统时钟来自 PLL
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//168M
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;//42M
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;//84M
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}

已知 PLL 参数:PLLM = 8,PLLN = 336,PLLP = 2,PLLQ = 7,外部晶振 HSE = 8 MHz

  1. PLL 输入频率
FPLL_IN=FHSEPLLMF_{PLL\_IN} = \frac{F_{HSE}}{PLLM} FPLL_IN=8MHz8=1MHzF_{PLL\_IN} = \frac{8\,MHz}{8} = 1\,MHz
  1. VCO 频率
FVCO=FPLL_IN×PLLNF_{VCO} = F_{PLL\_IN} \times PLLN FVCO=1MHz×336=336MHzF_{VCO} = 1\,MHz \times 336 = 336\,MHz
  1. 系统时钟 SYSCLK
SYSCLK=FVCOPLLPSYSCLK = \frac{F_{VCO}}{PLLP} SYSCLK=336MHz2=168MHzSYSCLK = \frac{336\,MHz}{2} = 168\,MHz
  1. USB / SDIO / RNG 时钟
FUSB=FVCOPLLQF_{USB} = \frac{F_{VCO}}{PLLQ} FUSB=336MHz7=48MHzF_{USB} = \frac{336\,MHz}{7} = 48\,MHz
时钟主要使用对象
SYSCLK系统主时钟源(CPU、总线时钟的源头)
HCLKAHB 总线:CPU、DMA、SRAM、GPIO
PCLK1APB1 低速外设:USART2/3、UART4/5、I2C、CAN、TIM2~7
PCLK2APB2 高速外设:USART1/6、SPI1、ADC、TIM1/8

二、DWT配置

DWT(Data Watchpoint and Trace)硬件计数器来实现微秒级计时,精度高一些。

//计时1us
void cycleCounterInit(void)
{
usTicks=SystemCoreClock / 1000000U; //168M/1000000
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;//打开 DWT
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;//启动周期计数器
}
/*使用DWT->CYCCNT*/
uint32_t start = DWT->CYCCNT;
/* 要测试的代码 */
foo();
uint32_t end = DWT->CYCCNT;

Thanks for reading!

STM32 笔记:时钟配置

周一 1月 05 2026
348 字 · 3 分钟

STM32 专栏

第 1 篇 / 共 5 篇

已经是本专栏第一篇

下一篇

STM32 笔记:串口相关