【STM32 CubeMX】HAL库的本质读写寄存器

文章目录

  • 前言
  • 一、HAL库的本质
    • 1.1 HAL库的本质是操作寄存器
    • 1.2 自己实现HAL_GPIO_WritePin
      • 寄存器
      • 通过寄存器的操作点灯
      • 代码概况
      • Port bit set/reset register寄存器
  • 总结


前言

在嵌入式系统开发中,HAL(Hardware Abstraction Layer)库是一个重要的概念,它提供了一个抽象层,使开发者可以更容易地编写可移植的代码,而不必担心底层硬件的细节。STM32CubeMX是一款由STMicroelectronics提供的工具,用于生成STM32微控制器的初始化代码,其中包括了HAL库的使用。

HAL库的本质与HAL库源码分析
HAL库的本质是一个由供应商提供的软件库,旨在提供一系列抽象接口,用于访问底层硬件资源,如GPIO、USART、I2C等。这些接口隐藏了底层硬件的细节,使得开发者能够以统一的方式进行开发,而不必担心不同型号或者不同系列的微控制器的差异。

HAL库的源码分析可以揭示其内部的工作原理和实现细节。通过分析源码,我们可以了解到每个函数的具体功能、调用关系以及与底层硬件交互的细节。HAL库通常包括了对不同硬件模块的驱动程序,这些驱动程序是与特定型号的微控制器兼容的。


一、HAL库的本质

1.1 HAL库的本质是操作寄存器

其实点灯就是操作下面的output data register
在这里插入图片描述

比如我们之前点灯写的HAL_GPIO_WritePin()他的源码如下:

void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_PIN_ACTION(PinState));

  if (PinState != GPIO_PIN_RESET)
  {
    GPIOx->BSRR = GPIO_Pin;
  }
  else
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;
  }
}

他去设置某个寄存器等于某个值,这叫是HAL库的本质

1.2 自己实现HAL_GPIO_WritePin

寄存器

CPU可以发出地址,然后访问比如Flash、RAM、GPIOC
我们可以通过访问某一个地址区间去访问Flash
访问其他地址访问GPIOC等等等等

我们可以访问ram,写入val,读出仍是val
我们可以访问flash,使用读出指令,不能直接写

在GPIOC里面有很多的寄存器,但我们不能像操作ram和flash一样,这些寄存器的功能各有不同
比如说以我这个F103ZE为例子:
在这里插入图片描述
比如Port configuration配置寄存器,一个低位,一个高位
比如输入寄存器:Port input data,通过读他,可以得到引脚的状态/数据
比如输出寄存器:Port output data,我们可以通过写这个寄存器,让这个引脚输出高低电平
还有一些其他的

通过寄存器的操作点灯

我们可以在芯片手册中找到GPIOC的基地址,在看GPIOC的输出寄存器偏移地址可以得出,要访问输出寄存器就要访问0x400110C这个地址的寄存器

在这里插入图片描述
比如说,举个例子:我们可以通过一个C语言的指针指向这个要操作的寄存器
然后把里面的值给改变了是不是就操作了寄存器的值
他的每一个寄存器的大小都是2bytes

首先我们使用指针指向寄存器的位子

unsigned int *p;
p	= (unsigned int*)0x40010C0C;

接下来我们需要操作第十三个寄存器,即可点亮我们的灯
比如我们可以这样设置他为1:

unsigned int val = *p;
val = val | (1<<5);
*p = val;

我们可以这样设置他为0:

val = *p;
val = val & ~(1<<5);
*p = val;

这样我们就通过寄存器输出高低电平了

要注意的是,比如你要操作GPIOC里面的13,你就要移13,像下面这样,其他的也是一样
要操作哪个引脚就偏移他的引脚名称,我这里的灯是PB5,所以就把他的地址里面的值偏移5即可
在这里插入图片描述

代码概况

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	
	unsigned int *p;
	p	= (unsigned int*)0x40010C0C;

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		unsigned int val = *p;
		val = val | (1<<5);
		*p = val;
		
		HAL_Delay(500);
		
		val = *p;
		val = val & ~(1<<5);
		*p = val;
		
		HAL_Delay(500);
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Port bit set/reset register寄存器

像我们上面,我们需要把寄存器的内容拿出来,然后通过控制某一位的0/1来操作高低电平,这样稍微有点麻烦,那么我们可以使用下面这个寄存器Port bit set/reset register,他只需要写入1到某一位就可以输出高电平/低电平
在这里插入图片描述
他是一个32位的寄存器

比如BRy
在这里插入图片描述
他写入1就把指定的GPIO reset
0就是没有任何作用

比如BSy
在这里插入图片描述
他写入1就是指定GPIO set
0就是没有任何作用

那么我们就可以把代码变成这样:

unsigned int *p;
	p	= (unsigned int*)(0x40010C00 + 0x10);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		unsigned int val = *p;
		*p = (1 << 21);
		
		HAL_Delay(500);
		
		*p = (1 << 5);
		
		HAL_Delay(500);
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

通过写21位,把他变成reset状态
通过写5位,把他变成set状态,这样就实现了闪烁灯


总结

HAL库作为嵌入式系统开发中的重要工具,提供了一种方便、快捷的方式来访问STM32微控制器的硬件资源。通过使用HAL库,开发者可以更加专注于应用程序的开发,而不必花费大量时间去编写底层的驱动程序。通过深入分析HAL库的源码,我们可以更好地理解其内部实现细节,从而更好地利用这一工具来开发高效、可靠的嵌入式应用程序。

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

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

相关文章

Kotlin和Java 单例模式

Java 和Kotlin的单例模式其实很像&#xff0c;只是Kotlin一部分单例可以用对象类和委托lazy来实现 Java /*** 懒汉式&#xff0c;线程不安全*/ class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (insta…

肯尼斯·里科《C和指针》第13章 高级指针话题(2)函数指针

我们不会每天都使用函数指针。但是&#xff0c;它们的确有用武之地&#xff0c;最常见的两个用途是转换表(jump table)和作为参数传递给另一个函数。本节将探索这两方面的一些技巧。但是&#xff0c;首先容我指出一个常见的错误&#xff0c;这是非常重要的。 简单声明一个函数指…

静态时序分析:SDC约束命令set_clock_uncertainty

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 set_clock_uncertainty是用来指定设计中时钟周期的不确定性&#xff0c;不确定性指的是对那些会对时钟周期造成的负面影响。这些不确定性可能来源于时钟抖动(clo…

【JavaEE】_JavaScript(Web API)

目录 1. DOM 1.1 DOM基本概念 1.2 DOM树 2. 选中页面元素 2.1 querySelector 2.2 querySelectorAll 3. 事件 3.1 基本概念 3.2 事件的三要素 3.3 示例 4.操作元素 4.1 获取/修改元素内容 4.2 获取/修改元素属性 4.3 获取/修改表单元素属性 4.3.1 value&#xf…

HotCoin Global: 澳洲双牌照持有平台,坚守全球合规之路

前言&#xff1a; 加密交易平台的合规性不仅是相关法规遵守的问题&#xff0c;更是市场透明度和用户公平性的关键。为促使加密市场的交易活动有规范、有秩序地进行&#xff0c;确保加密投资者的资产与交易安全&#xff0c;部分国家明确对加密资产的交易和经营活动进行监督及管…

SNMP 简单网络管理协议、网络管理

目录 1 网络管理 1.1 网络管理的五大功能 1.2 网络管理的一般模型 1.3 网络管理模型中的主要构件 1.4 被管对象 (Managed Object) 1.5 代理 (agent) 1.6 网络管理协议 1.6.1 简单网络管理协议 SNMP 1.6.2 SNMP 的指导思想 1.6.3 SNMP 的管理站和委托代理 1.6.4 SNMP…

博客系统-SpringBoot版本

相比于之前使用Servlet来完成的博客系统&#xff0c;SpringBoot版本的博客系统功能更完善&#xff0c;使用到的技术更接近企业级&#xff0c;快来看看吧~ 目录 1.项目介绍 2.数据库准备 3.实体化类 4.返回格式 5.登录和注册功能 6.登出&#xff08;注销&#xff09;功能…

【Python】Python代码的单元测试

Python代码的单元测试 单元测试的概念 定义&#xff1a;是指对软件中的最小可测试单元进行检查和验证。 作用&#xff1a;可以确保程序模块是否否和我们规范的输出&#xff0c;保证该模块经过修改后仍然是满足我们的需求。 单元测试的策略 如果要创建单元测试&#xff0c;…

C语言-----用二维数组解决菱形的打印问题

1.打印菱形&#xff0c;多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜线和正斜线的长度。 #include <stdio.h>int main() {int n0;while(scanf("%d",&n)! EOF){int i0;int j0;f…

初识webpack(二)解析resolve、插件plugins、dev-server

目录 (一)webpack的解析(resolve) 1.resovle.alias 2.resolve.extensions 3.resolve.mainFiles (二) plugin插件 1.CleanWebpackPlugin 2.HtmlWebpackPlugin 3.DefinePlugin (三)webpack-dev-server 1.开启本地服务器 2.HMR模块热替换 3.devServer的更多配置项 (…

.NET高级面试指南专题七【SocketWebSocket】

Socket&#xff08;套接字&#xff09;是一种在计算机网络中实现通信的一种机制&#xff0c;它提供了一种标准的接口&#xff0c;使不同计算机上的程序能够通过网络进行数据交换。Socket允许在网络中的不同设备之间建立连接&#xff0c;进行双向的数据传输。 Socket通常用于实现…

Map和Set(哈希表)

目录 map&#xff1a; map说明&#xff1a; Map.Entry的说明&#xff1a;,v> Map 的常用方法: 演示&#xff1a; 注意&#xff1a; TreeMap和HashMap的区别 Set&#xff1a; 常见方法说明&#xff1a; 注意&#xff1a; TreeSet和HashSet的区别 哈希表: 冲突&a…

FileZilla Server 1.8.1内网搭建

配置环境服务器服务器下载服务器配置服务器配置 Server - ConfigureServer Listeners - Port 协议设置 Protocols settingsFTP and FTP over TLS(FTPS) Rights management(权利管理)Users(用户) 客户端建立连接 配置环境 服务器处于局域网内: 客户端 < -访问- > 公网 &l…

车载软件架构 —— Adaptive AUTOSAR软件架构

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师&#xff08;Wechat&#xff1a;gongkenan2013&#xff09;。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 本就是小人物&#xff0c;输了就是输了&#…

寒假思维训练day21

今天更新一道不错的状态压缩DP题&#xff0c;顺带总结一下状态压缩DP。 摘要&#xff1a; Part1 浅谈状态压缩DP的理解 Part2 浅谈对状态机DP的理解 Part3 关于状态压缩DP的1道例题 Part1 状态压缩DP 1、状态压缩DP&#xff1a; 事物的状态可能包含多个特征&#xff0c;…

linuxqq关闭主面板后无法再次打开的问题

文章目录 前言解决方案强调一点 前言 听说QQ出了linux版&#xff0c;所以来试试。结果试试就逝世。这次记录一个关闭后没办法打开的解决办法。 解决方案 刚安装好后如果点了关闭&#xff0c;系统托盘里也没有&#xff0c;点击图标又是重新登录。当然&#xff0c;我们最简单、…

浅谈Linux环境

冯诺依曼体系结构&#xff1a; 绝大多数的计算机都遵守冯诺依曼体系结构 在冯诺依曼体系结构下各个硬件相互配合处理数据并反馈结果给用户 其中控制器和运算器统称为中央处理器&#xff08;CPU&#xff09;&#xff0c;是计算机硬件中最核心的部分&#xff0c;像人类的大脑操控…

钓鱼邮件的发送工具GUI

一.简介 本程序利用Python语言编写&#xff0c;使用Tkinter实现图形化界面&#xff0c;可使用Pyinstaller进行exe打包&#xff0c;程序主界面截图如下&#xff1a; 二.功能 1.支持腾讯企业邮、网易企业邮、阿里企业邮、自建邮服SMTP授权账号&#xff08;其他邮服&#xff0c…

【HTML】交友软件上照片的遮罩是如何做的

笑谈 我不知道大家有没有在夜深人静的时候感受到孤苦难耐&#xff0c;&#x1f436;。于是就去下了一些交友软件来排遣寂寞。可惜的是&#xff0c;有些交友软件真不够意思&#xff0c;连一些漂亮小姐姐的图片都要进行遮罩&#xff0c;完全不考虑兄弟们的感受,&#x1f620;。所…

微信小程序(四十一)wechat-http的使用

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.模块下载 2.模块的使用 在终端输入npm install wechat-http 没有安装成功vue的先看之前的一篇 微信小程序&#xff08;二十&#xff09;Vant组件库的配置- 如果按以上的成功配置出现如下报错先输入以下语句 …