本身F4时钟树就是够枯燥的了,配置时钟树的库函数初始化就更枯燥了,我看了4遍网课了已经,看一遍睡着一遍,故我将视频中内容一一分析,总结如下:
时钟系统初始化函数只有在库函数版本中才有 。
- 执行程序之前必先驱动时钟
从以下代码中可以看出在运行主函数之前要先初始化时钟系统函数
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit //先输出
IMPORT __main //后输出
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
- 初始化系统时钟函数
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set置位 HSION bit */
RCC->CR |= (uint32_t)0x00000001;
//将CR寄存器第一位(位0,如下第一图所示)设置为1,打开HSI振荡器。
/* Reset复位¸´Î» CFGR register */
RCC->CFGR = 0x00000000;//全复位了
/* Reset HSEON, * *ON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
//将16进制值用二进制来表示1111 1110 1111 0110 1111 1111 1111 1111 ,
//可以看出第16,19,24位置0(如下第二三四图)。
//HSE 振荡器关闭,时钟安全系统关闭,主PLL关闭
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
//0010 0100 0000 0000 0011 0000 0001 0000
//位5:0设置PLLM=32分频(2~63),位14:6主PLL倍频系数PLLN=192(范围是192~432),位17:16 PLLP=2,
//位21:18保留,必须保持复位值,位22选择HSE作为PLL输入,位23位保留,位27:24 PLLQ=4,位31:28,
//保持复位值。
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
//同理1011是将第3位置零也就是第18位置零,外部时钟旁路HSE振荡器
/* Disable all interrupts */
RCC->CIR = 0x00000000;
- 以下图片均为CR时钟控制寄存器的位控制图。
时钟安全系统(CSS)作用: 当主PLL选择HSE作为时钟来源时(如下图),假如OSC_IN挂掉了导致没有时钟输入,那么时钟安全系统就会识别到PLLCLK状态不行,主动将SYSCLK的时钟来源选择切换为HSI状态,保证外设系统执行 。
- SetSysClock()函数
static void SetSysClock(void)
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//使能第16位HSE
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
//等待第17位返回1(就绪),正式开启。若长时间不返回一 系统也会自行中断向下走。CR等待函数
if (HSEStatus == (uint32_t)0x01)
{
/* Select regulator voltage output Scale 1 mode */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;//
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //不分频 使得HCLK等于SYSCLK
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // 设置APB2二分频
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;//设置APB1四分频
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
//使能PLLCFGR各个参数(N、P、M、Q)值进行算数
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON; //使能主PLL
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)//等待主PLL就绪
{
}
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL; //系统时钟时钟源的切换!! 选择PLLCLK作为其时钟源
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
到这里 我们配置了 HCLK、PCLK2、PCLK1、选择HSE作为PLL时钟源,配置了PLLCLK(PLLCFGR)并等待就绪,又把系统时钟设置为PLLCLK(CFGR)并等待就绪。
- 总结
结合时钟树总结配置全过程
①打开HSE时钟等待其使能
②配置好HCLK、APB1、APB2外设时钟跟系统时钟关系。
③将HSE设置为主PLL的时钟源
④配置好M、N、P值,使能PLLCLK并等待其就绪
⑤将系统时钟选择PLLCLK作为其时钟源,最后达到配置系统时钟作用