先上代码
__IO uint32_t StartUpCounter = 0, HSIStatus = 0;
RCC->CR |=((uint32_t)RCC_CR_HSION);
do
{
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
StartUpCounter++;
}while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
if(RCC->CR & RCC_CR_HSIRDY)
{
HSIStatus = 0x01;
}
else
{
HSIStatus = 0x00;
}
if(HSIStatus == 0x01)
{
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
/* PLL configuration = HSI * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
接着来说明下,
很多人拿到官方的例程代码里面的时钟配置是基于使用外部晶振的,但是为了节省成本,所以很多人都选择使用内部RC,
下面是内部RC的配置流程,
首先配置
RCC->CR |=((uint32_t)RCC_CR_HSION);
开启内部时钟,
在开启内部时钟之后,那么要等待内部时钟就绪,
do
{
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
StartUpCounter++;
}while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
if(RCC->CR & RCC_CR_HSIRDY)
{
HSIStatus = 0x01;
}
else
{
HSIStatus = 0x00;
}
并设置好状态,
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
这一部分的代码是和外部晶振的代码配置一样的,
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
关键代码是这一句,
而配置外部时钟的时候
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
语句是这样的,很多人都以为,
只要修改为内部时钟即可,但是很多的代码都是在PLL开启的时候限入死循环,
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
死在这里,
死在这里的原因是什么呢,
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
的解释如下,,,RCC_CFGR_PLLXTPRE_PREDIV1
这一句说的是,PLLCLK INPUT的来源外部晶振,所以,这里不对,
那么要使用内部晶振的配置
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
是这样的,这样的配置是,PLL的来源是来自内部晶振,而且这个来源的时钟不是通过2分频的,所以直接是通过8M来倍频的,
所以6X8是等于48M的,