系统时钟是芯片工作的心脏和动力源,先从时钟进行分析。后续的ADC,TIM均是基于时钟来进行的。
在 STM32F746 中,有 5 个最重要的时钟源,为 HSI、 HSE、 LSI、 LSE、 PLL。
LSI 是低速内部时钟, RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使用。
LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。 这个主要是 RTC 的时钟源。
HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~26MHz。
HSI 是高速内部时钟, RC 振荡器, 频率为 16MHz。 可以直接作为系统时钟或者用作 PLL输入。
NUCLEO-F746ZG开发板使用的是低速时钟和高速外部时钟源,其中低速为 32.768kHz,高速时钟使用外部时钟源。
选择 HSE 为 PLL 时钟源,同时 SYSCLK 时钟源为 PLL,那么 SYSCLK 时钟为 216MHz。
系统时钟初始化代码如下:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Configure LSE Drive Capability
//配置 LSE 驱动能力
*/
HAL_PWR_EnableBkUpAccess();//上电复位后,备份域是受保护的,防止意外的写操作
//启用对 RTC 和备份寄存器的访问
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();//使能PWR时钟
//下面这个设置用来设置调压器输出电压级别,以便在器件未以最大频率工作,使性能与功耗实现平衡
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别1
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;//时钟源为HSE
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;//用户外部时钟输入
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;//打开PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;//PLL时钟源选择HSE
RCC_OscInitStruct.PLL.PLLM = 4;//主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
RCC_OscInitStruct.PLL.PLLN = 216;//主PLL倍频系数(PLL倍频),取值范围:64~432.
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;//系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
RCC_OscInitStruct.PLL.PLLQ = 2;//USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)//初始化时钟
{
Error_Handler();
}
/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != HAL_OK)//开启Over-Driver功能
{
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;//选中PLL作为系统时钟源并且配置HCLK,SYSCLK,PCLK1和PCLK2
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;//设置系统时钟时钟源为PLL
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//AHB分频系数为1
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;//APB1分频系数为4
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;//APB2分频系数为2
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)//同时设置FLASH延时周期为7WS,也就是8个CPU周期。
{
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;//配置扩展时钟,USART3
PeriphClkInitStruct.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;//USART3时钟选择为系统时钟
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)//初始化
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();//使能CSS
}
HAL 库配置 STM32F746 时钟系统的一般步骤:
(1)使能 PWR 时钟
__HAL_RCC_PWR_CLK_ENABLE();//使能PWR时钟
之所以要使能 PWR 时钟,是因为后面的步骤中“设置调节器输出电压级别”以及“开启 Over-Driver 功能”都是电源控制相关配置,所以必须开启 PWR 时钟 。
(2)设置调压器输出电压级别
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别1
这个设置用来设置调压器输出电压级别,以便在器件未以最大频率工作,使性能与功耗实现平衡。
调压器输出电压级别 VOS,它是由 PWR->CR 的位 15:14 来确定的:
系统时钟为216M,则需要设置电压级别1,且开启 Over-Driver 功能。
(3)初始化RCC振荡器
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;//时钟源为HSE
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;//用户外部时钟输入
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;//打开PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;//PLL时钟源选择HSE
RCC_OscInitStruct.PLL.PLLM = 4;//主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
RCC_OscInitStruct.PLL.PLLN = 216;//主PLL倍频系数(PLL倍频),取值范围:64~432.
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;//系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
RCC_OscInitStruct.PLL.PLLQ = 2;//USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)//初始化时钟
{
Error_Handler();
}
(4)选择开启 Over-Driver 功能
if (HAL_PWREx_EnableOverDrive() != HAL_OK)//开启Over-Driver功能
{
Error_Handler();
}
(5)初始化CPU,AHB和APB总线时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;//选中PLL作为系统时钟源并且配置HCLK,SYSCLK,PCLK1和PCLK2
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;//设置系统时钟时钟源为PLL
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//AHB分频系数为1
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;//APB1分频系数为4
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;//APB2分频系数为2
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)//同时设置FLASH延时周期为7WS,也就是8个CPU周期。
{
Error_Handler();
}
(6)外设时钟配置-USART3
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;//配置扩展时钟,USART3
PeriphClkInitStruct.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;//USART3时钟选择为系统时钟
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)//初始化
{
Error_Handler();
}
(7)开启CSS功能
HAL_RCC_EnableCSS();//使能CSS
时钟配置完成后,可以说查看各个总线的时钟频率。