STM32F1xx,时钟底层库讲解,(原创)

/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//开启HSE外部晶振振荡器,使之工作

/* Wait till HSE is ready and if Time out is reached exit */
do//等待外部高速时钟就绪标志置1
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));//判断标志位和计数看是否超时,超时则跳出

if ((RCC->CR & RCC_CR_HSERDY) != RESET)//诊断HSE是否启动成功
{
HSEStatus = (uint32_t)0x01;//成功
}
else
{
HSEStatus = (uint32_t)0x00;//失败
}

if (HSEStatus == (uint32_t)0x01)//如果成功了
{
/* Enable Prefetch Buffer *///设置预取缓冲器
FLASH->ACR |= FLASH_ACR_PRFTBE;//使能预取缓冲器

/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);//~0x03先对等待周期控制位进行清除
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;//设置等待周期为2,这是对于72M主频来说


/* HCLK = SYSCLK *///AHB的时钟预分频
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//除以1,不分频

/* PCLK2 = HCLK *///这是APB2的时钟
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//除以1,不分频

/* PCLK1 = HCLK *///!错误//这是APB1的时钟
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//除以2,2分频,手册要求不能超过36MHZ

#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);//对PREDIV2、PREDIV1、PLL2MUL预分频复位,PREDIV1SRC输入时钟源复位,默认为HSE
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |//PREDIV2进行5预分频,再经PLL2MUL进行8倍频
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);//PREDIV1SRC输入时钟源定为PLL2,并经PREDIV1进行了5分频

/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;//使能PLL2
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)//等待PLL2锁相环锁定频率
{
}


/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL

);//先复位
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | //对选择进来的时钟源进行1分频,并选择其作为PLL输入时钟源
RCC_CFGR_PLLMULL9); //PLLMUL进行9倍频
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz *///对于普通设备无需进行上面的配置
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_PLLMULL9);//只要对8M晶振进行1分频并选定为时钟源,再9倍频就可以达到72M
#endif /* STM32F10X_CL */

/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;//使能PLL

/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)//等待PLL锁相环锁定72M频率
{
}

/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));//复位SW控制位
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;//选择PLL作为系统时钟:可选则的时钟源有HSE、HSI、PLL

/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)//当如果修改了上一句时钟源的输入则必须修改此句,否则将会陷入死循环。
{
}
}
else//如果HSE振荡器起振失败
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#endif

相关文档
最新文档