欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

【STM32学习笔记】时钟的配置

程序员文章站 2022-06-15 22:18:58
时钟树简单总结一下:​PLLCLK的来源有三个,HSE、HSE/2、HSI/2,一般选 HSE = 8M​SYSCLK(系统时钟)的来源有三个,PLLCLK(锁相环)、HSE、HEI,一般选 PLLCLK * 9 = 72M​AHB总线上的时钟 HCLK = SYSCLK = 72M​APB1总线上的时钟 PCLK1 = HCLK/2 = 36M​APB2总线上的时钟 PCLK2 = HCLK = 72M官方固件库的时钟配置(通过寄存器)static void SetS...

时钟树

【STM32学习笔记】时钟的配置

简单总结一下:

​ PLLCLK的来源有三个,HSE、HSE/2、HSI/2,一般选 HSE = 8M

​ SYSCLK(系统时钟)的来源有三个,PLLCLK(锁相环)、HSE、HEI,一般选 PLLCLK * 9 = 72M

​ AHB总线上的时钟 HCLK = SYSCLK = 72M

​ APB1总线上的时钟 PCLK1 = HCLK/2 = 36M

​ APB2总线上的时钟 PCLK2 = HCLK = 72M

官方固件库的时钟配置(通过寄存器)

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* 使能 HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* 等待HSE就绪并做超时处理 */
  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;
  }  

  // 如果HSE启动成功,程序则继续往下执行
  if (HSEStatus == (uint32_t)0x01)
  {
    // 使能预取指
    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 = 72M
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    // PCLK2 = HCLK = 72M 
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    // PCLK1 = HCLK/2 = 36M
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
    
    //  锁相环配置: 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);

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

    // 等待PLL稳定 
    while((RCC->CR & RCC_CR_PLLRDY) == 0);  
    // 选择PLLCLK作为系统时钟
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    // 等待PLLCLK切换为系统时钟 
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08);
      
  }
  else
  { /* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */
  }
}

自己写的时钟配置(通过固件库中已封装的函数)

可改变倍频,实现不同频率锁相环,从而改变系统时钟的频率

#include "bsp_rccclkconfig.h"

void HSE_SetSysClk(uint32_t RCC_PLLMul_x){
	
	ErrorStatus HSEStatus; /* ErrorStatus RCC_WaitForHSEStartUp(void); */
	
	//寄存器复位
	RCC_DeInit();
	
	//使能 HSE
	RCC_HSEConfig(RCC_HSE_ON);
	//等待HSE稳定
	HSEStatus=RCC_WaitForHSEStartUp();
	
	if(HSEStatus==SUCCESS){
		
		// 使能预取指
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		// Flash 2 wait state 
		FLASH_SetLatency(FLASH_Latency_2);
		
		// HCLK = SYSCLK = 72M
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
    // PCLK1 = HCLK = 36M
		RCC_PCLK1Config(RCC_HCLK_Div2);
    // PCLK2 = HCLK = 72M 
		RCC_PCLK2Config(RCC_HCLK_Div1);
		
		//  锁相环(PLL)配置: PLLCLK = HSE * x = ?? MHz 
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
		// 使能PLL
		RCC_PLLCmd(ENABLE);
		// 等待PLL稳定
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
		
		// 选择系统时钟
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		// 等待PLLCLK切换为系统时钟 
		while(RCC_GetSYSCLKSource() != 0x08);
		
	}
	
	else{
		/* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */
	}
	
}

void HSI_SetSysClk(uint32_t RCC_PLLMul_x){
	
	__IO uint32_t HSIStatus; /* ErrorStatus RCC_WaitForHSEStartUp(void); */
	
	//寄存器复位
	RCC_DeInit();
	
	//使能 HSI
	 RCC_HSICmd(ENABLE);
	//等待HSI稳定
	HSIStatus = RCC->CR & RCC_CR_HSIRDY;
	
	if(HSIStatus==SUCCESS){
		
		// 使能预取指
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		// Flash 2 wait state 
		FLASH_SetLatency(FLASH_Latency_2);
		
		// HCLK = SYSCLK = 72M
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		// PCLK1 = HCLK = 36M
		RCC_PCLK1Config(RCC_HCLK_Div2);
    // PCLK2 = HCLK = 72M 
		RCC_PCLK2Config(RCC_HCLK_Div1);
    
		//  锁相环(PLL)配置: PLLCLK = HSI * x = ?? MHz 
		RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);
		// 使能PLL
		RCC_PLLCmd(ENABLE);
		// 等待PLL稳定
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
		
		// 选择系统时钟
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		// 等待PLLCLK切换为系统时钟 
		while(RCC_GetSYSCLKSource() != 0x08);
		
	}
	
	else{
		/* 如果HSI 启动失败,用户可以在这里添加处理错误的代码 */
	}
	
}


//MCO 输出初始化
void MCO_GPIO_Config(void){
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}

/** 通过 MCO 输出不同源的时钟频率,可连接示波器观察频率
  *下列函数为官方固件库中已封装函数,在main中直接调用即可
  *如:输出系统时钟的频率:RCC_MCOConfig(RCC_MCO_SYSCLK);
  */

/**
  * @brief  Selects the clock source to output on MCO pin.
  * @param  RCC_MCO: specifies the clock source to output.       
  *     @arg RCC_MCO_NoClock: No clock selected
  *     @arg RCC_MCO_SYSCLK: System clock selected
  *     @arg RCC_MCO_HSI: HSI oscillator clock selected
  *     @arg RCC_MCO_HSE: HSE oscillator clock selected
  *     @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected
  */
void RCC_MCOConfig(uint8_t RCC_MCO)
{
  /* Check the parameters */
  assert_param(IS_RCC_MCO(RCC_MCO));

  /* Perform Byte access to MCO bits to select the MCO source */
  *(__IO uint8_t *) CFGR_BYTE4_ADDRESS = RCC_MCO;
}

本文地址:https://blog.csdn.net/Brave_Runer/article/details/107920262

相关标签: STM32 单片机