STM32时钟系统简介

目录

STM32时钟系统

时钟系统框图

时钟系统总结

PLLCLK,SYSCLK,HCKL,PCLK1,PCLK2 之间的关系

五大时钟源

简要概述系统时钟源

APB1&ABP2总线对应的设备

与时钟相关的寄存器

STM32官方库函数讲解

时钟初始化SystemInit()函数

系统文件中跨文件全局变量的宏定义声明


STM32时钟系统

时钟系统框图

 

时钟系统总结

PLLCLK,SYSCLK,HCKL,PCLK1,PCLK2 之间的关系

1、HSI:高速内部时钟信号 stm32单片机内带的时钟 (8M频率)精度较差

2、HSE:高速外部时钟信号精度高来源(1)HSE外部晶体/陶瓷谐振器(晶振) (2)HSE用户外部时钟

3、LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时钟使用

五大时钟源

LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时钟使用

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL:

①、HSI是高速内部时钟,RC振荡器,频率为8MHz。

②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。

③、LSI是低速内部时钟,RC振荡器,频率为40kHz。

④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。

⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

简要概述系统时钟源

 

注:USB模块虽然需要一个单独的48MHz时钟信号,但它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的,这个图中输出端口不太全,该图旨在说明核心系统时钟源的功能。

APB1&ABP2总线对应的设备

连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4;

连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口。

与时钟相关的寄存器

我们要知道无论是STM32官方提供的库函数还是其提供的寄存器操作方法,本质上来说都是对相应的寄存器进行操作。

RCC 寄存器结构,RCC_TypeDeff,在文件“stm32f10x_map.h”中定义如下:

typedef struct{vu32 CR;                  //HSI,HSE,CSS,PLL等的使能vu32 CFGR;              //PLL等的时钟源选择以及分频系数设定vu32 CIR;                // 清除/使能 时钟就绪中断vu32 APB2RSTR;      //APB2线上外设复位寄存器vu32 APB1RSTR;      //APB1线上外设复位寄存器vu32 AHBENR;         //DMA,SDIO等时钟使能vu32 APB2ENR;       //APB2线上外设时钟使能vu32 APB1ENR;      //APB1线上外设时钟使能vu32 BDCR;           //备份域控制寄存器vu32 CSR;          } RCC_TypeDef;

这里RCC是Reset and clock control的缩写,意为“复位与时钟控制”

STM32官方库函数讲解

时钟初始化SystemInit()函数

我们知道在操作STM32开发板之前,必须先初始化全部的时钟,是他们均恢复到默认状态,然后我们再在函数文件中使能相应的时钟。那问题来了,我们一般编写函数文件时没用过SystemInit()函数呀?SystemInit()函数是怎么调用的?

SystemInit()函数在哪里定义的?

 

SystemInit()函数在那里被调用的?

由于SystemInit()函数调用是STM32的核心代码,因此放到启动文件中,如果要查找可以在CORE->startup_stm32f10x_xx.s中找到。

 

更加个性化的系统初始化函数调用

; Reset handler  
Reset_Handler   PROC  EXPORT  Reset_Handler             [WEAK]  IMPORT  __main  IMPORT  SystemInit // 如果你编写了自己的时钟初始化函数可以将SystemInit换为你自己的初始化函数  LDR     R0, =SystemInit  BLX     R0                 LDR     R0, =__main  BX      R0  ENDP  

 

 

SystemInit()函数如何工作?

// 系统初始化函数SystemInit()  
void SystemInit (void)  
{  /* 将RCC时钟配置重置为默认重置状态(用于调试) */  /* 设置 HSION 位为1 , 即默认状态下系统时钟源为HSI*/  RCC->CR |= (uint32_t)0x00000001;  /* 设置 HSEON, CSSON and PLLON 位为0 */  RCC->CR &= (uint32_t)0xFEF6FFFF;  /* 设置 HSEBYP 位为0 */  RCC->CR &= (uint32_t)0xFFFBFFFF;  /* 设置 PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE 位为0 */  RCC->CFGR &= (uint32_t)0xFF80FFFF;  /* 配置系统时钟频率,HCLK, PCLK2和PCLK1分频器 */  /* 配置Flash延迟周期并启用预取缓冲区 */  SetSysClock(); // 用于配置系统时钟频率,HCLK, PCLK2和PCLK1预压器  #ifdef VECT_TAB_SRAM  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */  
#else  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */  
#endif   
}  
// 系统时钟速度配置函数SetSysClock()  
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  /* 如果以上定义都没有启用,则HSI将用作系统时钟源(使用默认值) */   
}  

 

此外,我们还可以自定义初始速度:

 

只要我们把注释掉的预定义命令恢复,就可以配置不同速度。

可以读出系统时钟速度的变量SystemCoreClock:

/******************************************************************************* 
*  Clock Definitions 
*******************************************************************************/  
#ifdef SYSCLK_FREQ_HSE  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */  
#elif defined SYSCLK_FREQ_24MHz  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */  
#elif defined SYSCLK_FREQ_36MHz  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */  
#elif defined SYSCLK_FREQ_48MHz  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */  
#elif defined SYSCLK_FREQ_56MHz  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */  
#elif defined SYSCLK_FREQ_72MHz  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */  
#else /*!< HSI Selected as System Clock source */  uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */  
#endif  

 

系统文件中跨文件全局变量的宏定义声明

 

图中“STM32F10X_HD,USE_STDPERIPH_DRIVER “为所有文件均能识别的宏定义标志,其中我们很常见的是” STM32F10X_HD “,它代表的是大容量芯片。

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部