STM32时钟初始化研究

时钟是一个MCU的脉搏,研究清楚脉搏才能更清楚的把握整个MCU的运行。本文主要研究STM32F10x系列,利用官方库文件进行初始化设置。开发环境为MDK4.6,库文件V3.5版本,STM32参考手册。

利用MDK自带仿真器,仿真发现。芯片启动首先打开system_stmf10x.c文件,调用void SystemInit(void)函数。下面贴上代码和中文注释

void SystemInit (void)
{
	/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
	/* Set HSION bit */
	RCC->CR |= (uint32_t)0x00000001;	//内部高速时钟使能
	
	
	/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
	//SW:HSI(内部高速8M RC震荡器)作为时钟源
	//AHB(SYSCLK)不分频
	//APB1,APB2不分频
	// PCLK2 2分频后作为ADC时钟
	// HSI时钟2分频后作为PLL输入时钟
	//MCO没有时钟输出
	RCC->CFGR &= (uint32_t)0xF8FF0000;

	
	/* Reset HSEON, CSSON and PLLON bits */
	//HSE振荡器关闭, 时钟安全系统监测器关闭PLL关闭
	RCC->CR &= (uint32_t)0xFEF6FFFF;


	/* Reset HSEBYP bit */
	//清零来旁路外部晶体振荡器。只有在外部4-25MHz振荡器关闭的情况下,才能写入该位。
	RCC->CR &= (uint32_t)0xFFFBFFFF;

	
	/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
	//HSI时钟2分频后作为PLL输入时钟
	//HSE不分频器作为PLL输入
	//0000:PLL 2倍频输出
	//0:PLL时钟1.5倍分频作为USB时钟
	RCC->CFGR &= (uint32_t)0xFF80FFFF;

	
	/* Disable all interrupts and clear pending bits  */
	RCC->CIR = 0x009F0000;

	
	/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
	/* Configure the Flash Latency cycles and enable prefetch buffer */
	SetSysClock();

	
	SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}

主要是用于重置RCC寄存器,既重置STM32的时钟树。

初始化重置时钟后的时钟树图:

STM32时钟初始化研究_第1张图片

上文中还有个函数叫SetSysClock用于设置MCU系统时钟,贴入代码:

static void SetSysClock(void)
{

	#ifdef SYSCLK_FREQ_HSE
	  SetSysClockToHSE();
	#elif defined SYSCLK_FREQ_24MHz
	  SetSysClockTo24();
	#elif defined SYSCLK_FREQ_36MHz
	  SetSysClockTo36();
	#elif defined SYSCLK_FREQ_48MHz
	  SetSysClockTo48();
	#elif defined SYSCLK_FREQ_56MHz
	  SetSysClockTo56();  
	#elif defined SYSCLK_FREQ_72MHz
	  SetSysClockTo72();
	#endif
	/* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */
}

static void SetSysClockTo72(void)
{
	__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

	/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    


	/* Enable HSE */    
	/*define C_CR_HSEON                        (int32_t)0x00010000)   */
	/*!< External High Speed clock enable */
	//开启HSE振荡器
	RCC->CR |= ((uint32_t)RCC_CR_HSEON);

	
	/* Wait till HSE is ready and if Time out is reached exit */
	//等待HSE起振
	//#define HSEStartUp_TimeOut   HSE_STARTUP_TIMEOUT
	//#define HSE_STARTUP_TIMEOUT   ((uint16_t)0x0500)
	/*!< Time out for HSE start up */
	do
	{
		HSEStatus = RCC->CR & RCC_CR_HSERDY;
		StartUpCounter++;  
	} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

	if ((RCC->CR & RCC_CR_HSERDY) != RESET)
	{
		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);
		FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;  

		/* HCLK = SYSCLK */
		//#define  RCC_CFGR_HPRE_DIV1      ((uint32_t)0x00000000)        /*!< SYSCLK not divided */
		//HCLK  :AHB总线时钟,由系统时钟SYSCLK 分频得到,不分频
		RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;


		/* PCLK2 = HCLK */
		// #define  RCC_CFGR_PPRE2_DIV1    ((uint32_t)0x00000000)        /*!< HCLK not divided */
		//APB2由AHB分频而来,不分频。
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

		
		/* PCLK1 = HCLK */
		//#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)        /*!< HCLK divided by 2 */
		//APB1由AHB分频而来,2分频。
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

		/*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
		//设置PLLCLK时钟源为HSE,且PLL9倍频
		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);

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


		/* Wait till PLL is ready */
		//等待PLL稳定运行
		while((RCC->CR & RCC_CR_PLLRDY) == 0)
		{
		}
		
		/* Select PLL as system clock source */
		//设置PLL作为系统时钟源
		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 */
		//等待PLL用于系统时钟源
		while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
		{
		}
		else
		{ /* If HSE fails to start-up, the application will have wrong clock  configuration. User can add here some code to deal with this error */
		}

}
初始化重置时钟后的时钟树图:

STM32时钟初始化研究_第2张图片

你可能感兴趣的:(STM32时钟初始化研究)