结合最近我做的项目,对STM32时钟配置有一些理解,记录下来,以便自己查看和理解。
* @brief Setup the microcontroller system
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemCoreClock variable.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
void SystemInit (void)
{
RCC->CR |= (uint32_t)0x00000001;//开启内部高速8M的RC震荡器
RCC->CFGR &= (uint32_t)0xF8FF0000;//
//SWS:系统时钟切换状态 00:HSI作为系统时钟即SYSCLK=HSI=8M
//HPRE: AHB预分频因子,即AHB Prescaler 值为0xxx:SYSCLK不分频。即HCLK=SYSCLK
// PPRE1:低速APB预分频因子(APB1 Prescaler) 0xx:HCLK不分频。即PCLK1=HCLK
//PPRE2:高速APB预分频因子(APB2 Prescaler) 0xx:HCLK不分频。即PCLK2=HCLK
//ADCPRE:ADC预分频 00:PCLK2 2分频后作为ADC时钟,即ADCCLK=PCLK2/2
//MCO:有无时钟输出控制位。0XX:MCO 端没有时钟输出
RCC->CR &= (uint32_t)0xFEF6FFFF;
//时钟控制寄存器RCC_RC=0x*E*6****; 就是说寄存器的第25位和第20位,第17位为0,其余保持不变。
//也就是PLL关闭;时钟监测器关闭;HSE振荡器关闭;
RCC->CR &= (uint32_t)0xFFFBFFFF;
//就是使HSEBYP=0;外部4-25MHz振荡器没有旁路;
RCC->CFGR &= (uint32_t)0xFF80FFFF;
//RCC_CFGR的第23、22、21、 20、 19、 18、 17位都为0。
//PLLXTPER:HSE分频器作为PLL输入。此值为0,HSE不分频,那么PLLCLK=HSE
//PLLMUL:PLL倍频系数
RCC->CIR = 0x009F0000;
SetSysClock();
}
static void SetSysClockTo36(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
//注释为:SYSLCK,HCLK,PCLK2和PCLK1 的配置
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//外部高速时钟允许
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));//HSEStatus不为0时,外部高速时钟稳定了
if ((RCC->CR & RCC_CR_HSERDY) != RESET)//当外部高速时钟稳定时
{
HSEStatus = (uint32_t)0x01;//HSEStatus为1
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)//当HSEStatus为1时,即外部高速时钟稳定时
{
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
//前面配置得到 PCLK1=PCLK2=HCLK=SYSCLK,那么,SYSCLK是多少呢? 下边配置SYSCLK值
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9);
//RCC_CFGR_PLLXTPRE_HSE_Div2:HSE 2分频以后作为PLL时钟,即PLLCLK输入=HSE/2
//RCC_CFGR_PLLMULL9:PLL 9倍频输出,即PLLCLK输出,也就是PLLCLK,它等于9倍的PLLCLK输入,即PLLCLK = (HSE / 2) * 9 = 36 MHz
//到这里,可以知道PLLCLK=36M
RCC->CR |= RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
//前面要想得到的SYSCLK在这里就知道了。因为PLL输出作为系统时钟,即
//SYSCLK=PLLCLK=36M
//程序中需要用的其他时钟也可以确定了。
//因为APB1 Prescaler=1(没有分频),所以TIMxCLK=PLCK1=36M
//因为APB2 Prescaler=1(没有分频),所以TIM1CLK=PLCK2=36M
//在SystemInit 中ADCPRE:ADC预分频 00:PCLK2 2分频后作为ADC时钟,即ADCCLK=PCLK2/2,所以ADCCLK=18M
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{
}
}