STM32-04-STM32时钟树

STM32时钟树

  • 什么是时钟?

    时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波。(时钟是单片机的脉搏,搞懂时钟走向及关系,对单片机使用至关重要)。

  • 时钟树
    STM32-04-STM32时钟树_第1张图片

  • 时钟源

    • 2个外部时钟源
      • 高速外部振荡器(HSE):外接石英/陶瓷谐振器,频率为4MHz~16MHz。
      • 低速外部振荡器(LSE):外接32.768kHz石英晶体,主要作用于RTC的时钟源。
    • 2个内部时钟源
      • 高速内部振荡器(HSI):由内部RC振荡器产生,频率为8MHz。
      • 低速内部振荡器(LSI):由内部RC振荡器产生,频率为40kHz,可作为独立看门狗的时钟源。
  • 锁相环

    锁相环是自动控制系统中常用的一个反馈电路,在STM32主控中,锁相环的作用主要有两个方面:

    输入时钟净化:利用锁相环电路的反馈机制实现;

    倍频:用于使芯片在更高且频率稳定的时钟下工作。

    经过分频器处理后的输出振荡时钟信号比直接输入的时钟信号更稳定。

  • 系统时钟SYSCLK

    STM32的系统时钟SYSCLK为整个芯片提供了时序信号。在STM32F1系列中,它可以为HSI、PLLCLK、HSE中的一个,通过CFGR的位SW[1:0]设置。

  • 系统时钟配置步骤

    1. 配置HSE_VALUE stm32xxxx_hal_conf.h

      #if !defined (HSE_VALUE)
      	#if defined(USE_STM3210C_EVAL)
      		#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
      	#else 
      		#define HSE_VALUE 8000000U  /*!< Value of the External oscillator in Hz */
      	#endif 
      #endif /* HSE_VALUE */
      
    2. 调用SystemInit函数 system_stm32xxxx.c

      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)
      {
      	#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || 	defined(STM32F103xE) || defined(STM32F103xG)
       		#ifdef DATA_IN_ExtSRAM
       			SystemInit_ExtMemCtl();
       		#endif /* 配置扩展 SRAM */
      	#endif 
       	/* 配置中断向量表 */
      	#if defined(USER_VECT_TAB_ADDRESS)
       		SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table 			Relocation in Internal SRAM. */
      	#endif /* USER_VECT_TAB_ADDRESS */
      }
      

      主要用于外部存储器配置和中断向量表地址配置

    3. 选择时钟源,配置PLL system_stm32xxxx.c

      void sys_stm32_clock_init(uint32_t plln)
      {
          HAL_StatusTypeDef ret = HAL_ERROR;
          RCC_OscInitTypeDef rcc_osc_init = {0};
          RCC_ClkInitTypeDef rcc_clk_init = {0};
      
          rcc_osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;       /* 选择要配置HSE */
          rcc_osc_init.HSEState = RCC_HSE_ON;                         /* 打开HSE */
          rcc_osc_init.HSEPredivValue = RCC_HSE_PREDIV_DIV1;          /* HSE预分频系数 */
          rcc_osc_init.PLL.PLLState = RCC_PLL_ON;                     /* 打开PLL */
          rcc_osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE;             /* PLL时钟源选择HSE */
          rcc_osc_init.PLL.PLLMUL = plln;                             /* PLL倍频系数 */
          ret = HAL_RCC_OscConfig(&rcc_osc_init);                     /* 初始化 */
      
          if (ret != HAL_OK)
          {
              while (1);                                              /* 时钟初始化失败,之后的程序将可能无法正常执行,可以在这里加入自己的处理 */
          }
      
          /* 选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2*/
          rcc_clk_init.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
          rcc_clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;        /* 设置系统时钟来自PLL */
          rcc_clk_init.AHBCLKDivider = RCC_SYSCLK_DIV1;               /* AHB分频系数为1 */
          rcc_clk_init.APB1CLKDivider = RCC_HCLK_DIV2;                /* APB1分频系数为2 */
          rcc_clk_init.APB2CLKDivider = RCC_HCLK_DIV1;                /* APB2分频系数为1 */
          ret = HAL_RCC_ClockConfig(&rcc_clk_init, FLASH_LATENCY_2);  /* 同时设置FLASH延时周期为2WS,也就是3个CPU周期。 */
      
          if (ret != HAL_OK)
          {
              while (1);                                              /* 时钟初始化失败,之后的程序将可能无法正常执行,可以在这里加入自己的处理 */
          }
      }
      
      HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
      
          
      typedef struct 
      { 
      	uint32_t  OscillatorType; 		/* 选择需要配置的振荡器 */ 
      	uint32_t  HSEState; 			/* HSE 状态 */ 
      	uint32_t  HSEPredivValue; 		/* HSE 预分频值 */ 
      	uint32_t  LSEState; 			/* LSE 状态 */ 
      	uint32_t  HSIState; 			/* HSI状态 */ 
      	uint32_t  HSICalibrationValue; 	/* HSI 校准值 */ 
      	uint32_t  LSIState; 			/* LSI 状态 */ 
      	RCC_PLLInitTypeDef  PLL; 		/* PLL 结构体 */ 
      }RCC_OscInitTypeDef;
      
      
      typedef struct 
      { 
      	uint32_t  PLLState; 		/* PLL 状态 */ 
      	uint32_t  PLLSource; 	/* PLL 时钟源 */ 
      	uint32_t  PLLMUL; 		/* PLL 倍频系数 */ 
      }RCC_PLLInitTypeDef;
      
    4. 选择系统时钟源,配置总线分频器 HAL_RCC_ClockConfig()

      HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
      
          
      typedef struct 
      { 
      	uint32_t  ClockType; 		/* 要配置的时钟(SYSCLK/HCLK/PCLK1/PCLK2) */ 
      	uint32_t  SYSCLKSource; 		/* 系统时钟源 */ 
      	uint32_t  AHBCLKDivider; 		/* AHB  时钟预分频系数 */ 
      	uint32_t  APB1CLKDivider; 	/* APB1 时钟预分频系数 */ 
      	uint32_t  APB2CLKDivider; 	/* APB2 时钟预分频系数 */ 
      }RCC_ClkInitTypeDef;
      
      
      uint32_t FLatency 
      
      #define  FLASH_LATENCY_0   0x00000000U 				/* FLASH 0个等待周期 */ 
      #define  FLASH_LATENCY_1   FLASH_ACR_LATENCY_0 		/* FLASH 1个等待周期 */ 
      #define  FLASH_LATENCY_2   FLASH_ACR_LATENCY_1 		/* FLASH 2个等待周期 */
      
    5. 配置拓展外设时钟

声明:资料来源(战舰STM32F103ZET6开发板资源包)

  1. Cortex-M3权威指南(中文).pdf
  2. STM32F10xxx参考手册_V10(中文版).pdf
  3. STM32F103 战舰开发指南V1.3.pdf
  4. STM32F103ZET6(中文版).pdf
  5. 战舰V4 硬件参考手册_V1.0.pdf

你可能感兴趣的:(嵌入式,stm32,嵌入式硬件,单片机)