STM32时钟树案例详解
时钟树
直接使用HSI作为时钟源
使用配置相应的结构体,最后调用HAL_RCC_OscConfig(), 和HAL_RCC_ClockConfig()初始化时钟。
/**
* @brief System Clock Configuration
* @retval None
* 方式一:直接配置相应的结构体
* 使用HSI作为系统时钟源(16MHz).
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; //配置选择哪个系统时钟源
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; //配置各条线路的分频
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); //配置调压器的输出电压级别,级别数值越小工作频率越高
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; //选择HSI(High Speed Inside)作为时钟来源
RCC_OscInitStruct.HSIState = RCC_HSI_ON; //开启HSI
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; //HSI校准调整值,选择默认(可不写)
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; //不使用PLL
/* 等待时钟源切换成功 */
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
printf("HAL_RCC_OscConfig(&RCC_OscInitStruct) is Error!\n"); //输出错误提示
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | /* HCLK */
RCC_CLOCKTYPE_SYSCLK | /* SYSCLK */
RCC_CLOCKTYPE_PCLK1 | /* PCLK1 */
RCC_CLOCKTYPE_PCLK2; /* PCLK2 */
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; //选择系统时钟源为HSI
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; //APB1分频系数为1
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; //APB2分频系数为1
/* 等待切换成功 */
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
printf("HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) is Error!\n"); //输出错误提示
Error_Handler();
}
}
使用PLL作为时钟源,使用HSI作为PLL的时钟源
以下关于时钟的计算参考:RM0090_Page226_7.3.2:RCC PLL configuration register
- f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
- f(PLL general clock output) = f(VCO clock) / PLLP
- f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
/**
* @brief System Clock Configuration
* @retval None
* 使用PLL作为系统时钟源(168MHz),由HSI提供时钟给PLL.
* HSIPLL_SystemClock_Config(16, 336, 2, 7)
*/
void HSIPLL_SystemClock_Config(uint32_t m, uint32_t n, uint32_t p, uint32_t q)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; //声明时钟源结构体
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; //声明各个时钟结构体
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); //配置调压器输出电压级别
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; //选择HSI作为时钟源(16MHz)
RCC_OscInitStruct.HSIState = RCC_HSI_ON; //开启HSI
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; //开启PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; //选择HSI作为PLL时钟源
RCC_OscInitStruct.PLL.PLLM = m; //配置M分频-----2~63
RCC_OscInitStruct.PLL.PLLN = n; //配置N倍频-----50~432
RCC_OscInitStruct.PLL.PLLP = p; //配置p分频-----2,4,6,8----->SYSCLK
RCC_OscInitStruct.PLL.PLLQ = q; //配置q分频-----4~15-------->Peripheral clock
/** EX: SYSCLK=PLLCLK=HSI/m*n/p;
*/
/* 等待时钟源配置成功 */
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
//printf("HAL_RCC_OscConfig(&RCC_OscInitStruct) is Error!\n"); //输出错误提示
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
/* 等待切换成功,Find Table10(Page:80, RM0090) */
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
//printf("HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) is Error!\n"); //输出错误提示
Error_Handler();
}
}
使用PLL作为时钟源,使用HSE作为PLL的时钟源
/**
* @brief System Clock Configuration
* @retval None
* 使用PLL作为系统时钟源(168MHz),由HSE提供时钟给PLL.
* HSEPLL_SystemClock_Config(8, 336, 2, 7)
*/
void HSEPLL_SystemClock_Config(uint32_t m, uint32_t n, uint32_t p, uint32_t q)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; //声明时钟源结构体
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; //声明各个时钟结构体
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); //配置调压器输出电压级别
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; //选择HSE作为时钟源(16MHz)
RCC_OscInitStruct.HSEState = RCC_HSE_ON; //开启HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; //开启PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; //选择HSE作为PLL时钟源
RCC_OscInitStruct.PLL.PLLM = m; //配置M分频-----2~63
RCC_OscInitStruct.PLL.PLLN = n; //配置N倍频-----50~432
RCC_OscInitStruct.PLL.PLLP = p; //配置p分频-----2,4,6,8----->SYSCLK
RCC_OscInitStruct.PLL.PLLQ = q; //配置q分频-----4~15-------->Peripheral clock
/** EX: SYSCLK=PLLCLK=HSE/m*n/p;
*/
/* 等待时钟源配置成功 */
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
printf("HAL_RCC_OscConfig(&RCC_OscInitStruct) is Error!\n"); //输出错误提示
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
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;
/* 等待切换成功,Find Table10(Page:80, RM0090) */
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
printf("HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) is Error!\n"); //输出错误提示
Error_Handler();
}
}
可参考链接:
- STM32时钟系统讲解(此为STM32L4) https://zhuanlan.zhihu.com/p/91225332