HAL库是什么,HAL库的定义

 1、HAL 库的定义

        HAL是 Hardware Abstraction Layer 的缩写,中文名:硬件抽象层。HAL 库是 ST 为 STM32 最新推出的抽象层嵌入式软件,可以更好的确保跨 STM32 产品的最大可移植性。该库提供了一整套一致的中间件组件,如 RTOS,USB,TCP/IP 和 图形 等。
  百度有一堆定义, HAL 库是基于一个非限制性的 BSD 许可协议(Berkeley Software Distribution)而发布的开源代码。 ST 制作的中间件堆栈(USB 主机和设备库,STemWin)带有允许轻松重用的许可模式, 只要是在 ST 公司的 MCU 芯片上使用,库中的中间件(USB 主机/设备库,STemWin)协议栈即被允许随便修改,并可以反复使用。
但是我简单通俗的来讲,就是HAL库可以使得用户将代码跨芯片使用,不同的MCU芯片(F1/F2...)都可以使用,体现了可移植性强!!

 

2、STM32CubeMX

说到 STM32 的 HAL 库,就不得不提 STM32CubeMX,其作为一个可视化的配置工具,对于开发者来说,确实大大节省了开发时间。STM32CubeMX 就是以 HAL 库为基础的,且目前仅支持 HAL 库及 LL 库! 

STM32CubeMX软件的特点:

  • 集成了ST的每一款型号的MCU/MPU的可配置的图形界面,能够自动提示IO冲突并且对于复用IO可自动分配;
  • 具有动态验证的时钟树;
  • 能够很方便的使用所集成的中间件;
  • 能够估算MCU/MPU在不同主频运行下的功耗;
  • 能够输出不同编译器的工程,比如能够直接生成MDK、EWARM、STM32CubeIDE、MakeFile等工程;

STM32CubeMX的使用也比较简单:先下载STM32CubeMx软件及对应不同系列MCU/MPU的Packs。

  • 确定要使用的MCU/MPU的型号;
  • 对所选的MCU/MPU的GPIO进行功能配置、配置时钟树及初始化相关参数;
  • 选择要用到的中间件进行配置;
  • 将配置好功能的MCU/MPU生成对应编译器的C语言工程文件;

stm32cubemx官网下载

3、HAL库与标准库(SPL)的区别

 文字性的东西我不宜过多赘述,这里直接上代码!

1、句柄

在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例)
我们首先要初始化他们的各个寄

存器。在标准库中,这些操作都是利用固件库结构体变量+固件库Init函数实现的:

	USART_InitTypeDef USART_InitStructure;

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

	USART_Init(USART3, &USART_InitStructure); //初始化串口1

可以看到,要初始化一个串口,需要对六个位置进行赋值,然后引用Init函数,并且USART_InitStructure并不是一个全局结构体变量,而是只在函数内部的局部变量,初始化完成之后,USART_InitStructure就失去了作用。

而在HAL库中,同样是USART初始化结构体变量,我们要定义为全局变量

UART_HandleTypeDef UART1_Handler;

右键查看结构体成员

typedef struct
{
	  USART_TypeDef                 *Instance;        /*!< UART registers base address        */
	  UART_InitTypeDef              Init;             /*!< UART communication parameters      */
	  uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
	  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
	  uint16_t                      TxXferCount;      /*!< UART Tx Transfer Counter           */
	  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
	  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
	  uint16_t                      RxXferCount;      /*!< UART Rx Transfer Counter           */  
	  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */ 
	  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
	  HAL_LockTypeDef               Lock;             /*!< Locking object                     */
	  __IO HAL_UART_StateTypeDef    State;            /*!< UART communication state           */
	  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */
}UART_HandleTypeDef;

我们发现,与标准库不同的是,该成员不仅包含了之前标准库就有的六个成员(波特率,数据格式等),还包含过采样、(发送或接收的)数据缓存、数据指针、串口 DMA 相关的变量、各种标志位等等要在整个项目流程中都要设置的各个成员。
该 UART1_Handler 就被称为串口的句柄
它被贯穿整个USART收发的流程,比如开启中断。

HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);

在这些函数中,只需要调用初始化时定义的句柄UART1_Handler就好。

也就是说我们是把各个成员全部封装好,移植的时候就可以直接调用了,那如果与用户需求不符怎么办,别急,后面要讲到的MSP与Callback回调函数:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

2、MSP函数

MCU Specific Package 单片机的具体方案
MSP是指和MCU相关的初始化,引用一下正点原子的解释,个人觉得说的很明白:

我们要初始化一个串口,首先要设置和 MCU 无关的东西,例如波特率,奇偶校验,停止
位等,这些参数设置和 MCU 没有任何关系,可以使用 STM32F1,也可以是STM32F2/F3/F4/F7上的串口。而一个串口设备它需要一个 MCU 来承载,例如用 STM32F4 来做承载,PA9 做为发送,PA10 做为接收,MSP 就是要初始化 STM32F4 的 PA9,PA10,配置这两个引脚。所以 HAL驱动方式的初始化流程就是:HAL_USART_Init()—>HAL_USART_MspInit() ,先初始化与 MCU无关的串口协议,再初始化与 MCU 相关的串口引脚。在 STM32 的 HAL 驱动中HAL_PPP_MspInit()作为回调,被 HAL_PPP_Init()函数所调用。当我们需要移植程序到 STM32F1平台的时候,我们只需要修改 HAL_PPP_MspInit 函数内容而不需要修改 HAL_PPP_Init 入口参数内容。

在HAL库中,几乎每初始化一个外设就需要设置该外设与单片机之间的联系,比如IO口,是否复用等等,可见,HAL库相对于标准库多了MSP函数之后,移植性非常强,但与此同时却增加了代码量和代码的嵌套层级。可以说各有利弊。

3、回调函数(callback)

类似于MSP函数,个人认为Callback函数主要帮助用户应用层的代码编写。
还是以USART为例,在标准库中,串口中断了以后,我们要先在中断中判断是否是接收中断,然后读出数据,顺便清除中断标志位,然后再是对数据的处理,这样如果我们在一个中断函数中写这么多代码,就会显得很混乱,这是标准库的处理:

void USART3_IRQHandler(void)                	//串口1中断服务程序
{
	u8 Res;
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Res =USART_ReceiveData(USART3);	//读取接收到的数据
		/*数据处理区*/
		}   		 
     } 
} 

而在HAL库中,进入串口中断后,直接由HAL库中断函数进行托管:

void USART1_IRQHandler(void)                	
{ 
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
	/***************省略无关代码****************/	
}

HAL_UART_IRQHandler这个函数完成了判断是哪个中断(接收?发送?或者其他?),然后读出数据,保存至缓存区,顺便清除中断标志位等等操作。
这就需要进去函数设置(嵌套性),比如我提前设置了,串口每接收五个字节,我就要对这五个字节进行处理。
在一开始我定义了一个串口接收缓存区:

/*HAL库使用的串口接收缓冲,处理逻辑由HAL库控制,接收完这个数组就会调用HAL_UART_RxCpltCallback进行处理这个数组*/
/*RXBUFFERSIZE=5*/
u8 aRxBuffer[RXBUFFERSIZE];

在初始化中,我在句柄里设置好了缓存区的地址,缓存大小(五个字节)

/*该代码在HAL_UART_Receive_IT函数中,初始化时会引用*/
	huart->pRxBuffPtr = pData;//aRxBuffer
    huart->RxXferSize = Size;//RXBUFFERSIZE
    huart->RxXferCount = Size;//RXBUFFERSIZE

则在接收数据中,每接收完五个字节,HAL_UART_IRQHandler才会执行一次Callback函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

在这个Callback回调函数中,我们只需要对这接收到的五个字节(保存在aRxBuffer[]中)进行处理就好了,完全不用再去手动清除标志位等操作。
所以说Callback函数是一个应用层代码的函数,我们在一开始只设置句柄里面的各个参数,然后就等着HAL库把自己安排好的代码送到手中就可以了~
 

参考

(30条消息) STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数_hal库句柄_Error_4O4的博客-CSDN博客

<think>嗯,用户想了解HAL的概念及用途。我需要先回忆一下HAL的基本定义HAL是硬件抽象层,对吧?它应该是介于硬件和软件之间的中间层,用来简化开发者的工作。记得在STM32中,HAL替代了原来的标准,提供了更高级的API。 那HAL的主要特点是什么呢?首先,硬件抽象,把底层硬件的操作封装成函数,这样开发者不需要直接操作寄存器。然后,跨系列兼容,比如不同型号的STM32芯片可以用相同的HAL函数,方便移植。还有,集成工具支持,比如STM32CubeMX可以自动生成初始化代码,节省时间。 应用领域方面,HAL常用于嵌入式系统开发。比如外设驱动开发,像GPIO、定时器、UART这些。还有快速原型开发,用CubeMX快速搭建项目框架。另外,IoT设备中用HAL简化通信模块的集成,比如Wi-Fi或蓝牙。显示屏驱动也是常见的应用,像SSD1306 OLED屏,引用里的那个GitHub项目就是基于HAL的驱动方案。 用户可能还想知道HAL和标准的区别,或者如何在项目中使用HAL。不过用户的问题主要是介绍和应用领域,所以需要集中在这些方面。需要确保引用的资料正确,比如引用1提到HAL引脚是软件实体,引用3提到结构体在HAL中的使用,引用4则提供了具体的应用案例。要确保回答结构清晰,分点说明,并且自然融入引用标记。 可能还需要生成相关问题,比如HAL与标准的区别,或者如何用CubeMX配置HAL。这些都能帮助用户进一步了解相关知识。要检查LaTeX格式是否正确,虽然问题中可能用不到数学公式,但如果有变量或代码,需要正确应用格式。</think>### HAL概念及用途解析 #### 1. **HAL定义** HAL(Hardware Abstraction Layer)STM32微控制器开发中的硬件抽象层,通过封装底层硬件操作(如寄存器配置、中断处理),为开发者提供统一的高层API接口。其核心目标是**降低硬件差异对软件开发的影响**,例如同一段代码可跨STM32F1/F4系列使用[^3]。 #### 2. **核心特点** - **硬件抽象** 将GPIO、定时器、ADC等外设操作抽象为函数调用,例如使用`HAL_GPIO_WritePin()`控制引脚电平,无需直接操作寄存器[^1]。 - **跨系列兼容** 支持STM32全系列芯片,代码移植时仅需调整时钟配置等少数参数。 - **集成工具链** 配合STM32CubeMX工具,可图形化配置外设并自动生成初始化代码[^4]。 #### 3. **典型应用领域** | 领域 | 具体应用场景 | |-------------------|----------------------------------------------------------------------------| | 外设驱动开发 | PWM呼吸灯(如引用2的LED控制)、SPI/I2C通信、ADC数据采集 | | 快速原型开发 | 使用CubeMX + HAL在10分钟内完成项目框架搭建 | | IoT设备开发 | 集成LoRa、Wi-Fi模块时简化底层驱动开发(如引用4的OLED显示屏驱动方案) | | 工业控制 | 通过HAL实现CAN总线通信、电机控制等实时操作 | #### 4. **代码示例:HALPWM配置** ```c // 使用CubeMX生成的PWM初始化代码片段 TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Prescaler = 79; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; HAL_TIM_PWM_Init(&htim2); // 初始化PWM HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动PWM通道 ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值