欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

使用 HSE/HSI 配置 STM32 时钟 - 软件设计

最编程 2024-05-04 17:10:55
...
编程要点:
  1. 开启HSE/HSI,并等待HSE/HSI稳定。
  2. 设置AHB,APB2,APB1的分频因子。
  3. 设置PLL的时钟来源和 PLL的倍频因子。
  4. 开启PLL,等待PLL稳定。
  5. 把PLLCK切换为系统时钟SYSCLK。
  6. 读取时钟切换状态位,确保时钟被选为系统时钟。
① 使用HSE配置系统时钟
void HSE_SetSysClock(uint32_t pllmul)
{
	__IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
	
	//把RCC外设初始化成复位状态
	RCC_DeInit();
	
	//使能HSE,开启外部晶振,
	RCC_HSEConfig(RCC_HSE_ON);
	
	//等待SHE启动稳定
	HSEStartUpStatus = RCC_WaitForHSEStartUp();
	
	//当HSE稳定之后继续往下执行
	if(HSEStartUpStatus == SUCCESS)
	{
		//使能Flash预存取缓存区
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		
		//设置SYSCLK周期与Flash访问时间的比例,这里统一设置成2
		//0: 0<SYSCLK<24M   1:  24M<SYSCLK<48M    2:   48M<SYSCLK<72M
		FLASH_SetLatency(FLASH_Latency_2);
		
		//AHB预分频因子设置为1,HCLK = SYSCLK
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		
		//APB2预分频因子设置为1,PCLK2 = HCLK
		RCC_PCLK2Config(RCC_HCLK_Div1); 
		
		//APB1预分频因子设置为2,PCLK1 = HCLK/2
		RCC_PCLK1Config(RCC_HCLK_Div2);
		
		RCC_PLLConfig(RCC_PLLSource_HSI_Div2,pllmul);
		
		//开启PLL
		RCC_PLLCmd(ENABLE);
		
		//等待PLL稳定
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
			{
				
			}
		
		//当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		
		//读取时钟切换状态位,确保PLLCLK被选为系统时钟
		while (RCC_GetSYSCLKSource()!=0x08)
			{
		
			}
	}
		else
			{
				while(1)
					{
					
					}
			}
}

这个函数使用库函数编写,有个形参pllmul,用来设置PLL的倍频因子。
函数调用举例:HSE_SetSysClock(RCC_PLLMul_9); 设置时钟为:8MHz * 9 = 72MHz
HSE_SetSysClock(RCC_PLLMul_16); 设置时钟为:8MHz * 16 = 128MHz

② 使用HSI配置系统时钟
void HSI_SetSysClock(uint32_t pllmul)
{
	__IO uint32_t HSIStartUpStatus = 0;
	
	//把RCC外设初始化成复位状态
	RCC_DeInit();
	
	//使能HSI
	RCC_HSICmd(ENABLE);
	
	//等待SHI启动稳定
	HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
	
	//当HSI稳定之后继续往下执行
	if(HSIStartUpStatus == RCC_CR_HSIRDY)
	{
		//使能Flash预存取缓存区
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		
		//设置SYSCLK周期与Flash访问时间的比例,这里统一设置成2
		//0: 0<SYSCLK<24M   1:  24M<SYSCLK<48M    2:   48M<SYSCLK<72M
		FLASH_SetLatency(FLASH_Latency_2);
		
		//AHB预分频因子设置为1,HCLK = SYSCLK
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		
		//APB2预分频因子设置为1,PCLK2 = HCLK
		RCC_PCLK2Config(RCC_HCLK_Div1);
		
		//APB1预分频因子设置为2,PCLK1 = HCLK/2
		RCC_PCLK1Config(RCC_HCLK_Div2);
		
		RCC_PLLConfig(RCC_PLLSource_HSI_Div2,pllmul);
		
		//开启PLL
		RCC_PLLCmd(ENABLE);
		
		//等待PLL稳定
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
			{
				
			}
		
		//当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		
		//读取时钟切换状态位,确保PLLCLK被选为系统时钟
		while (RCC_GetSYSCLKSource()!=0x08)
			{
		
			}
	}
		else
			{
				while(1)
					{
					
					}
			}
}

HSI设置系统时钟函数与SHE设置系统时钟函数原理上一样,但HSI必须2分频之后才能作为PLL的时钟来源。所以使用HSI时,最大系统时钟SYSCL只能是HSI/216=416=64MHz.函数调用举例:HSI_SetSysClock(RCC_PLLMul_9);设置系统时钟为:4MHz * 9=36MHz。

③ 软件延时
void Delay(__IO uint32_t nCount)
{
	for(;nCount !=0; nCount--);
}
④ MCO输出

在STM32F103系列中,PA8可以复用为MCO引脚,对外提供时钟输出。

void MCO_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//选择GPIO8引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	
	//设置为复用推挽输出
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	
	//设置IO的反转速率为50MHz
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//初始化GPIOA8
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}
//MCO引脚输出可以是HSE,HSI,PLLCL/2,SYSCLK
//RCC_MCOConfig(RCC_MCO_HSE);
//RCC_MCOConfig(RCC_MCO_HSI);
//RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
RCC_MCOConfig(RCC_MCO_SYSCLK);
⑤ Main函数
int main(void)
{
	//程序来到main函数之前,启动文件statup_stm32f10x_hd.s已经调用
	//SystemInit()函数把系统时钟初始化成72MHz
	//SystemInit()在system_stm32f10x.c中定义
	//重新设置系统时钟,这时候可以选择是使用HSE还是HSI
	//使用HSE时,SYSCLK = 8MHz * RCC_PLLMul_x,x为2~16,最高是128MHZ
	HSE_SetSysClock(RCC_PLLMul_9);
	//使用HSI时,SYSCLK = 4MHz * RCC_PLLMul_x,x为2~16,最高是64MHZ
	//HSI_SetSysClock(RCC_PLLMul_16);
	//MCO引脚初始化
	MCO_GPIO_Config();
	RCC_MCOConfig(RCC_MCO_SYSCLK);
	//LED端口初始化
	LED_GPIO_Config();
	while(1)
	{
		LED1(ON);
		Delay(0x0FFFFF);
		LED1(OFF);
		Delay(0x0FFFFF);
	}
}