STM32——STM32F103时钟解析(正点原子资料+HAL库代码分析)

文章目录

    • 前言
    • 时钟树详解
    • 系统时钟配置
    • 系统时钟使能配置

前言

上次写系统时钟解析的时候说出一篇103的时钟解析,我就整理HAL库开发的正点的资料,给小白梳理,我也是小白,不做权威使用。

时钟树详解

在这里插入图片描述
在 STM32 中,有五个时钟源,为 HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HIS,HSE 以及 PLL 是高速时钟,LSI 和 LSE是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源,其他的是内部时钟源。下面我们看看 STM32 的5 个时钟源,我们讲解顺序是按图中红圈标示的顺序:

①、HSI 是高速内部时钟,RC 振荡器,频率为 8MHz。
②、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。
③、LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同时 LSI 还可以作为 RTC 的时钟源。
④、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
⑤、PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为 2~16 倍,但是其输出频率最大不得超过 72MHz。

上面我们简要概括了 STM32 的时钟源,那么这 5 个时钟源是怎么给各个外设以及系统提供时钟的呢?这里我们将一一讲解。我们还是从图的下方讲解起吧,因为下方比较简单。图中我们用 A~E 标示我们要讲解的地方。

A. MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,可以选择为 PLL 输出的 2 分频、HSI、HSE、或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源。
B. 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及HSE 的 128 分频。
C. 从图中可以看出 C 处 USB 的时钟是来自 PLL 时钟源。STM32 中有一个全速功能的 USB 模块,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。
D.处就是 STM32 的系统时钟 SYSCLK,它是供 STM32 中绝大部分部件工作的时钟源。系统时钟可选择为 PLL 输出、HSI 或者 HSE。系统时钟最大频率为 72MHz,当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。
E. 这里的 E 处是指其他所有外设了。从时钟图上可以看出,其他所有外设的时钟最终来源都是 SYSCLK。SYSCLK 通过 AHB 分频器分频后送给各模块使用。这些模块包括:
①、AHB 总线、内核、内存和 DMA 使用的 HCLK 时钟。
②、通过 8 分频后送给 Cortex 的系统定时器时钟,也就是 systick 了。
③、直接送给 Cortex 的空闲运行时钟 FCLK。
④、送给 APB1 分频器。APB1 分频器输出一路供 APB1 外设使用(PCLK1,最大频率 36MHz),另一路送给定时器(Timer)2、3、4 倍频器使用。
⑤、送给 APB2 分频器。APB2 分频器分频输出一路供 APB2 外设使用(PCLK2,最大频率 72MHz),另一路送给定时器(Timer)1 倍频器使用。

其中需要理解的是 APB1 和 APB2 的区别,APB1 上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,APB2 上面连接的是高速外设包 括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。居宁老师的《稀里糊涂玩 STM32》资料里面教大家的记忆方法是 2>1, APB2 下面所挂的外设的时钟要比 APB1 的高。

在以上的时钟输出中,有很多是带使能控制的,例如 AHB 总线时钟、内核时钟、各种 APB1 外设、APB2 外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。

系统时钟配置

在系统启动之后,程序会先执行 HAL 库定义的 SystemInit 函数,进行系统一些初始化配置。 SystemInit 程序中主要做了以下三个方面的工作:
1) 复位 RCC 时钟配置为默认复位值(默认开始了 HIS)
2) 外部存储器配置
3) 中断向量表地址配置

HAL 库的 SystemInit 函数并没有像标准库的 SystemInit 函数一样进行时钟的初始化配置。HAL 库的 SystemInit 函数除了打开 HSI 之外,没有任何时钟相关配置,所以使用 HAL 库我们必须编 写自己的时钟配置函数。首先我们打开工程模板看看我们在工程 SYSTEM 分组下面定义的 sys.c中包含,也可以使用Cubemx自动生成配置代码,具体可以参考STM32Cubemx的总结手册。

//时钟系统配置函数 
//PLL:选择的倍频数,RCC_PLL_MUL2~RCC_PLL_MUL16 
//返回值:0,成功;1,失败 
void Stm32_Clock_Init(u32 PLL) 
{ 
HAL_StatusTypeDef ret = HAL_OK; 
RCC_OscInitTypeDef RCC_OscInitStructure; 
RCC_ClkInitTypeDef RCC_ClkInitStructure; 
RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE; //时钟源为 HSE 
RCC_OscInitStructure.HSEState=RCC_HSE_ON; //打开 HSE 
RCC_OscInitStructure.HSEPredivValue=RCC_HSE_PREDIV_DIV1; //HSE 预分频 
RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON;
//打开 PLL 
RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE; 
//PLL 时钟源选择 HSE 
RCC_OscInitStructure.PLL.PLLMUL=PLL; 
//主 PLL 倍频因子 
ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化 
if(ret!=HAL_OK) while(1); 
//选中 PLL 作为系统时钟源并且配置 HCLK,PCLK1 和 PCLK2 
RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK| 
RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1| 
RCC_CLOCKTYPE_PCLK2); 
//设置系统时钟时钟源为 PLL 
RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1; 
//AHB 分频系数为 1 
RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV2; 
//APB1 分频系数为 2 
RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV1; 
//APB2 分频系数为 1 
ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2); 
//同时设置 FLASH 延时周期为 2WS,也就是 3 个 CPU 周期。 
if(ret!=HAL_OK) while(1); 
}

在sys.c文件中,有一个Stm32_Clock_Init()函数,这个函数里面是时钟的配置。除了配置 PLL 相关参数确定 SYSCLK 值之外,还配置了 AHB,APB1 和 APB2 的分频系数,也就是确定了HCLK,PCLK1 和 PCLK2 的时钟值。

typedef struct 
{ 
uint32_t OscillatorType; //需要选择配置的振荡器类型 
uint32_t HSEState; //HSE 状态 
uint32_t HSEPredivValue; // Prediv1 值 
uint32_t LSEState; //LSE 状态 
uint32_t HSIState; //HIS 状态
uint32_t HSICalibrationValue; //HIS 校准值 
uint32_t LSIState; 
//LSI 状态 
RCC_PLLInitTypeDef PLL; //PLL 配置 
}RCC_OscInitTypeDef; 

typedef struct 
{ 
uint32_t PLLState; //PLL 状态 
uint32_t PLLSource; //PLL 时钟源 
uint32_t PLLMUL; //PLL VCO 输入时钟的乘法因子 
}RCC_PLLInitTypeDef;

在这个函数中初始化一个结构体,关于RCC_OscInitTypeDef外部晶振的结构体,里面包含选择配置振荡器的类型。在这个结构体中有关于PLL的配置的成员变量,RCC_PLLInitTypeDef 结构体,里面又包含了PLL状态、 PLL时钟源、PLL输入时钟的乘法因子,这三个成员变量主要是设置PLL的分频倍频参数。

RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE; //时钟源为 HSE 
RCC_OscInitStructure.HSEState=RCC_HSE_ON; //打开 HSE 
RCC_OscInitStructure.HSEPredivValue=RCC_HSE_PREDIV_DIV1; //HSE 预分频 
RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON;
//打开 PLL 
RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE; 
//PLL 时钟源选择 HSE 
RCC_OscInitStructure.PLL.PLLMUL=PLL; 
//主 PLL 倍频因子 
ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化 

在时钟配置函数中开启了 HSE 时钟源,同时选择 PLL 时钟源为 HSE,然后把Stm32_Clock_Init 的唯一的入口参数直接设置作为 PLL 的倍频因子。设置好 PLL 时钟源参数之后,也就是确定了 PLL 的时钟频率,接下来我们就需要设置系统时钟,以及 AHB,APB1 和 APB2 相关参数。

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, 
uint32_t FLatency); 

该函数有两个入口参数,第一个入口参数 RCC_ClkInitStruct 是结构体RCC_ClkInitTypeDef 指针类型,用来设置 SYSCLK 时钟源以及 AHB,APB1 和 APB2 的分频系数。第二个入口参数 FLatency 用来设置 FLASH 延迟。

//选中 PLL 作为系统时钟源并且配置 HCLK,PCLK1 和 PCLK2 
RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK| 
RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1| 
RCC_CLOCKTYPE_PCLK2);
//设置系统时钟时钟源为 PLL 
RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1; //AHB 分频系数为 1 
RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV2; //APB1 分频系数为 2 
RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV1; //APB2 分频系数为 1 
ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2); 
//同时设置 FLASH 延时周期为 2WS,也就是 3 个 CPU 周期。 

第一个参数 ClockType 配置说明我们要配置的是 SYSCLK,HCLK,PCLK1 和 PCLK2 四个时钟。
第二个参数 SYSCLKSource 配置选择系统时钟源为 PLL。
第三个参数 AHBCLKDivider 配置 AHB 分频系数为 1。
第四个参数 APB1CLKDivider 配置 APB1 分频系数为 2。
第五个参数 APB2CLKDivider 配置 APB2 分频系数为 1。
根据我们在主函数中调用 Stm32_Clock_Init(RCC_PLL_MUL9)时候设置的入口参数值,我 们可以计算出,PLL 时钟为 PLLCLK=HSE9 =8MHz9=72MHz,同时我们选择系统时钟源为 PLL , 所 以 系 统 时 钟 SYSCLK=72MHz 。 AHB 分频系数为 1 ,故其频率为 HCLK=SYSCLK/1=72MHz。APB1 分频系数为 2,故其频率为 PCLK1=HCLK/2=36MHz。APB2 分频系数为 1,故其频率为 PCLK2=HCLK/1=72/1=72MHz。最后我们总结一下通过调用函数 Stm32_Clock_Init(RCC_PLL_MUL9)之后的关键时钟频率值:
SYSCLK(系统时钟) =72MHz
PLL 主时钟 =72MHz
AHB 总线时钟(HCLK=SYSCLK/1) =72MHz
APB1 总线时钟(PCLK1=HCLK/2) =36MHz
APB2 总线时钟(PCLK2=HCLK/1) =72MHz

系统时钟使能配置

在 STM32F1 的 HAL 库中,外设时钟使能操作都是在 RCC 相关固件库文件头文件 stm32f1xx_hal_rcc.h 定义的。大家打开stm32f1xx_hal_rcc.h 头文件可以看到文件中除了少数几 个函数声明之外大部分都是宏定义标识符。外设时钟使能在 HAL 库中都是通过宏定义标识符来实现的。我们的宏是__HAL_RCC_GPIOA_CLK_ENABLE(),宏定义里面有SET_BIT()函数,SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN); 意思很清楚哈,里面是寄存器配置APB2ENR,后面是配置的位,是一个宏

#define RCC_APB2ENR_IOPAEN ((uint32_t)0x00000001) 

作用是设置寄存器 RCC->APB2ENR 寄存器的位 2 为 1。我们可以从 STM32F1 的中文参考手册中搜索 APB2ENR 寄存器定义,位 2 的作用是用来使用 GPIOA 时钟。而配置描述如下:
IOPAEN:IO 端口 A 时钟使能
由软件置 1 和清零
0:禁止 IO 端口 A 时钟
1:使能 IO 端口 A 时钟
那么我们对各个时钟的使能就可以用以下方式表述:

__HAL_RCC_GPIOA_CLK_ENABLE();//使能 GPIOA 时钟 
__HAL_RCC_DMA1_CLK_ENABLE();//使能 DMA1 时钟 
__HAL_RCC_USART2_CLK_ENABLE();//使能串口 2 时钟 
__HAL_RCC_TIM1_CLK_ENABLE();//使能 TIM1 时钟

我们使用外设的时候需要使能外设时钟,如果我们不需要使用某个外设,同样我们可以禁止某个外设时钟。禁止外设时钟使用方法和使能外设时钟非常类似,同样是头文件中定义的宏定义标识符。我们同样以 GPIOA 为例,宏定义标识符为:

#define __HAL_RCC_GPIOA_CLK_DISABLE() \ 
(RCC->APB2ENR &= ~(RCC_APB2ENR_IOPAEN)) 

禁止外设时钟的设置为:

__HAL_RCC_DMA1_CLK_DISABLE();//禁止 DMA1 时钟 
__HAL_RCC_USART2_CLK_DISABLE();//禁止串口 2 时钟 
__HAL_RCC_TIM1_CLK_DISABLE();//禁止 TIM1 时钟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/153524.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零代码实现问卷网与巨量引擎的对接

通过数环通,您可以使用不到几分钟的时间即可实现问卷网与巨量引擎的对接与集成,从而高效实现工作流程自动化,降本增效! 1.产品介绍 巨量引擎是字节跳动旗下的营销服务品牌,它整合了字节跳动旗下的产品及海量内容&…

RTLS 颠覆制造业的 方式之——跟踪

进行中工作跟踪 在制品 (WIP) 跟踪主要关注生产中的项目如何从一个步骤移动到另一步骤。因此,运动是此类流程管理的共同点,使得实时位置的洞察力几乎在每个时刻都很有用。 1. 传递时间和运动数据 制造几乎总是涉及许多同时移动的事物。无论是在同一条…

如果免费使用GPT4

各位兄弟,这个漏洞也是最近挖到的,觉得这个可以为大家谋福利,所以我这给你们写一下。 看我如下操作 先登录GPT4 登录进来后,我们可以看见这里是GPT3 然后看如下操作 然后再问一下是模型几 各位就是这么简单,点过关注…

一个朴实无华的Java计算引擎(很实用)

计算引擎: 公司用的一个计算引擎(适合计算量比较大比较多的行业,比如金融行业、科学研究和工程、互联网和社交媒体、电子商务、医疗和生命科学、制造业、能源行业、交通和物流)。 计算引擎地址:xbc-cm: 公式管理、公式计算、公式计算结果管…

分享一个图像轮播效果

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 话不多说,先看效果: 根据图片的播放,页面背景会被替换为当前图片。 老规矩,源码自己拿…

划片机:半导体工艺精细化高效化的新里程碑

随着科技的飞速发展,半导体已经成为现代电子设备的基石,而半导体晶圆的划片机作为半导体制造的核心设备之一,其发展程度直接关系到半导体的质量和产量。近年来,博捷芯精密划片机以其在半导体划片机领域的卓越表现,引领…

几个测试接口的好工具,效率加倍~

作为一名后端程序员,一定要对自己写的接口负责,保证接口的正确和稳定性。因此,接口测试也是后端开发中的关键环节。 但我相信,很多朋友是懒得测试接口的,觉得这很麻烦。一般自己写的接口自己都不调用,而是…

抖音测试付费短视频:从短剧领域拓展到知识、娱乐全品类

11月16日,抖音开始测试短视频内容付费,即用户在观看创作者的内容时,部分内容需要付费解锁才能全部观看,涉及范围不仅包括此前已经进行付费试水的短剧领域,还拓展至知识、娱乐等几乎全品类内容,用户可按单条…

Linux进程之进程的状态简述

文章目录 1.百度搜索2.对进程状态的认识2.0创建状态2.1就绪状态2.2运行状态2.3阻塞状态2.4挂起状态 3.认识LinuxOS下的进程3.0进程状态的简述3.1了解R/S状态3.2D深度睡眠状态3.3信号/调试暂停状态3.4僵尸状态 1.百度搜索 2.对进程状态的认识 一个进程所具有的状态为操作系统的…

stm32f10系列--管脚被设置为输入模式时,对其进行输出操作将影响其输入功能

有时程序载入硬件,没有按代码执行,可能由于此。 1.欲完成功能: 结构:PA0管脚可以输出高低电平,控制LED灯的亮灭;PA1管脚作为输入,连接一头已经接地的switch开关。 逻辑:当开关闭合…

网络运维Day18

文章目录 环境准备导入数据确认表导入成功练习用表解析表格结构设计 查询语句进阶什么是MySQL函数常用功能函数数学计算流程控制函数查询结果处理 连接查询(联表查询)表关系什么是连接查询连接查询分类笛卡尔积内连接(INNER)外连接 子查询什么是子查询子查询出现的位置子查询练…

IEEE Standard for SystemVerilog—Chapter14. Clocking blocks

14.1 General This clause describes the following: — Clocking block declarations(时钟块声明) — Input and output skews(输入和输出偏斜) — Clocking block signal events(时钟块信号事件) — Cycle delays(周期延迟) — Synchronous events(同步事件) — Synchronous…

pytorch 安装 2023年

pytorch网址:https://pytorch.org/get-started/locally/ conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidia我在自己电脑上用这个pip命令完全安装不了,只能用conda安装。复制上面提供的命令,在cmd中直接运…

在Linux安装Nginx Proxy Manager并结合内网穿透工具实现远程访问管理界面

文章目录 前言1. docker 一键安装2. 本地访问3. Linux 安装cpolar4. 配置公网访问地址5. 公网远程访问6. 固定公网地址 前言 Nginx Proxy Manager 是一个开源的反向代理工具,不需要了解太多 Nginx 或 Letsencrypt 的相关知识,即可快速将你的服务暴露到外…

北京筑龙:招商局“强管控”成就采购合规与效益统一

1872至2023,历时151年,跨越三个世纪。招商局集团,从洋务运动中国第一场“商战”挽回航运利权,到开辟中国首条近海商业航线和远洋商业航线;从独资开发中国第一个对外开放工业区,到开办中国第一家银行……敢为…

@Version乐观锁配置mybatis-plus使用(version)

1:首先在实体类的属性注解上使用Version import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.Versio…

EtherNET转Profibus网关使用欧姆龙PLC的配置方法

兴达易控EtherNET转Profibus网关(XD-EPPB20)是一款具有 Profibus 从站功能的通讯网关。EtherNET转Profibus网关主要功能是将 EtherNET/IP 设备接入到 PROFIBUS 网络中。 本网关连接到 Profibus 总线中做为从站使用,连接到 EtherNET/IP 总线中…

2023年亚太杯数学建模思路 - 复盘:光照强度计算的优化模型

文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米,宽为12米&…

微星迫击炮b660m使用intel arc a750/770显卡功耗优化方法

bios 优化: 1,开机后持续点击“delete”键直到进入微星bios。 2,点击右上角选择我们熟悉的中文。 3,点击Settings--->高级---> pcie/Pci子系统设置 4,Native PCIE Enable : Enabled Native Aspm:允许

nginx服务器配置http/2

nginx服务器配置http/2 文章目录 nginx服务器配置http/21.安装nginx2.ssl证书2.1 创建ssl证书 3.配置nginx3.1 配置http/2 4.保存配置文件5.重启nginx6.测试 1.安装nginx 如果你没有安装nginx,可以参考这里:nginx教程 2.ssl证书 如果你没有ssl证书&…
最新文章