【IoT】(零)HAL

网友投稿 977 2022-05-30

选择HAL

HAL直译硬件抽象层,而库就是函数的集合,HAL库的作用是向下操作寄存器进行封装,向上提供用户函数调用的接口(API)。 从 STM32F7 开始 ST(意法 半导体) 将不会提供配套的标准库,只提供 HAL 库。

在 51 的开发中我们作法是直接操作寄存器,比如要控制某些 IO 口的状态,我们直接操作寄存器: P0=0x11;

而在 STM32 的开发中,我们同样可以操作寄存器: GPIOx->BSRR=0x00000001;

但是这种方法的需要去掌握每个寄存器的用法,我们才能正确使用 STM32,而对于 STM32 这种级别的 MCU,数百个寄存器记起来又是谈何容易。于是 ST推出了官方HAL库,大多数场合下,我们不需要去知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。

比如上面的控制 BSRRL 寄存器实现电平控制,官方 HAL 库封装了一个函数:

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

官方的相关文档或是函数定义处(stm32l4xx_hal_gpio.c)会有相关参数的介绍

HAL的函数都有语义化设计特点,从函数名很容易了解函数作用,能够便于开发者阅读和写出更优雅的代码,回顾时能更快分析代码功能。

HAL在CubeMX加持下,对STM32的开发将显著加快。

一、HAL库目录结构(了解即可)

Drivers 文件夹:BSP板级支持包,是官方开发板的硬件驱动API

CMSIS(Cortex Microcontroller Software Interface Standard):ARM Cortex™ 微控制器软件接口标准,是arm提供内核与外设、实时操作系统和中间设备之间的通用接口。

STM32L4xx_HAL_Driver:包含了所有的 STM32l4xx 系列 HAL 库头文件和源文件,也就是所有底层硬件抽象层 API 声明和定义。该文件 夹包含 Src 和 Inc 两个子文件夹,其中 Src 子文件夹 存放的是.c 源文件,Inc 子文件夹存放的是与之对应 的.h 头文件。每个.c 源文件对应一个.h 头文件。源文件名称基本遵循 stm32l4xx_hal_ppp.c 定义格式, 头文件名称基本遵循 stm32l4xx_hal_ppp.h 定义格 式。比如 gpio 相关的 API 的声明和定义在文件 stm32l4xx_hal_gpio.h 和 stm32l4xx_hal_gpio.c 中。 该文件夹中一般会存放用户参考手册,各种函数API都可以在.chm文件中查找。

Utilities:一些其他组件

二、MDK工程中项目操作

1、添加group

蓝色添加方式是一般网上教学选择方式,多文件添加时速度更快

对工程文件夹右键-Add Group-即可获得新组

2、添加项目

文件夹右键Add New Item

单文件添加时速度更快

【IoT】(零)HAL

这种方式要求type规范,不会发生忘记输入后缀的情况

3、添加头文件

3、添加全局宏定义标识符

USE_HAL_DRIVER 和 STM32L431xx,他们之间是用“,”或“。”隔开的

那么为什么添加全局宏定义标识符

因为其相当于

#define USE_HAL_DRIVER

#define STM32L431xx

...

进行这部操作就像打开了一个执行下面代码的按钮

#if defined (USE_HAL_DRIVER) #include "stm32l4xx_hal.h" #endif /* USE_HAL_DRIVER */

预编译的时候会判断条件USE_HAL_DRIVER, STM32L431xx等等,成立后包含头文件。stm32l4xx_hal.h,该头文件有着HAL的所有模块驱动程序;stm32l431xx_hal.h文件包含:①所有l431外设的数据结构和地址映射②外设的寄存器声明和位定义③访问外设寄存器硬件的宏

不同的芯片使用到的全局宏定义标识符不一样

4、勾选创造HEX文件,HEX文件才是我们下到芯片中的文件

三、关键文件 (ppp 代表任意外设)

stm32l4xx_hal_ppp.c/.h

基本外设的操作 API。其 中 stm32l4xx_hal_cortex.c/.h 比较特殊,它是 一些 Cortex 内核通用函数声明和定义,例如 中断优先级 NVIC 配置,系统软复位以及 Systick 配置等。

stm32l4xx_hal_ppp_ex.c/.h

拓展外设特性的 API。

stm32l4xx_hal.c/.h

包含 HAL 通用 API(比如 HAL_Init,HAL_DeInit,HAL_Delay 等)。

stm32l4xx_hal_conf.h

HAL 的配置文件,主要用来选择使能何种外 设以及一些时钟相关参数设置。其本身应该被业务代码所包含。

stm32l4xx_hal_def.h

包含 HAL 的通用数据类型定义和宏定义

stm32l4xx_II_ppp.c/.h

在一些复杂外设中实现底层功能,它们在stm32l4xx_hal_ppp.c 中被调用

stm32l4xx_it.c/stm32f4xx_it.h

stm32l4xx_it.h 中主要是一些中断服务函数的申明。

stm32l4xx.h

它是所有 stm32l4 系列的顶层头文件。 使用 STM32l4 任何型号的芯片,都需要包含这个头文件。同时,因为 stm32l4 系列芯片型 号非常多,ST 为每种芯片型号定义了一个特有的片上外设访问层头文件,比如 STM32L431 系列,ST 定义了一个头文件 stm32l431xx.h,然后 stm32l4xx.h 顶层头文件会根据工程芯片型号,来选择包含对应芯片的片上外设访问层头文件。

stm32l431xx.h

stm32l431xx.h 是 stm32l431 系列芯片通用的片上外设访问层头文件,只要我们进行 STM32l431开发,就必然要使用到该文件。打开该文件我们可以看到里面主要是一些结构体和宏定义标识符。这个文件的主要作用是寄存器定义声明以及封装内存操作。

system_stm32l4xx.c/.h

主要是声明和定义了系统初始化函 数 SystemInit 以及系统时钟更新函数 SystemCoreClockUpdate。SystemInit 函数的作用是进行 时钟系统的一些初始化操作以及中断向量表偏移地址设置,但它并没有设置具体的时钟值, 这是与标准库的最大区别,在使用标准库的时候,SystemInit 函数会帮我们配置好系统时钟配置相关的各个寄存器。

在启动文件 startup_stm32l431xx.s 中会设置系统复位后,直接调用 SystemInit 函数进行系统初始化。SystemCoreClockUpdate 函数是在系统时钟配置进行修改后,调用这个函数来更新全局变量 SystemCoreClock 的值,变量SystemCoreClock 是一个全局变量,开放这个变量可以方便我们在用户代码中直接使用这个变量来进行一些时钟运算。

tm32l4xx_hal_msp.c

MSP,全称为 MCU support package,函数名字中带有 MspInit 的函数,它们的作用是进行 MCU 级别硬件初始化设置,并且它们通常会被上一层的初始化函数所调用, 这样做的目的是为了把MCU相关的硬件初始化剥夺出来,方便用户代码在不同型号的MCU 上移植。

stm32l4xx_hal_msp.c 文件定义了两个函数 HAL_MspInit 和 HAL_MspDeInit。这两个函数分别被文件 stm32l4xx_hal.c 中的 HAL_Init 和 HAL_DeInit 所调用。HAL_MspInit 函数的主要作用是进行 MCU 相关的硬件初始化操作。

例如我们要初始化某些硬件,我们可以硬件相关的初始化配置写在 HAL_MspDeinit 函数中。这样的话,在系统启动后调用了 HAL_Init 之后,会自动调用硬件初始化函数 。

startup_stm32l431xx.s

STM32 系列所有芯片工程都会有一个.s 汇编启动文件。对于不同型号的 stm32 芯片启动文件也 是不一样的。启动文件的作用主要是进行堆栈的初始化,中断向量表以及中断函数定义等。启动文件有一个很重要的作用就是系统复位后引导进入 main 函数。

接下来我们看看 HAL 库工程中各个文件之间的包含关系

看不懂没关系,顶层头文件 stm32l4xx.h(stm32xxxx.h ) 直接或间接包含了其他所有工程必要头文件,所以在我们的用户代码中,我们只需要包含顶层头文件 stm32l4xx.h 即可。

参(C)考(V)自:

杰杰

mculover666等大佬

Description of STM32L4/L4+ HAL drivers UM1884 User manual

嵌入式 IoT 单片机

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:C++ on 华为云DevCloud
下一篇:Excel表格打印区域如何排版更美观
相关文章