使用HAL库开发STM32:概述与常用系统函数说明
日期: 2019-10-17 分类: 跨站数据测试 553次阅读
目的
使用HAL库开发STM32是目前ST官方主要推荐的方式,本篇文章对HAL做个基础说明。下面文章中以STM32F4为基础进行介绍,其它系列的HAL库在设计思路上也是差不多的。
HAL库概述
STM32F4的HAL库综述在文档《UM1725 - User Manual: Description of STM32F4 HAL and LL drivers》的第二篇章《Overview of HAL drivers》(文档版本DocID025834 Rev 5 ),官方文档本身写得非常详细,这里做下简单梳理。
下文中出现的。
文件说明
库文件
上图是HAL库文件与引用包含关系,其中 ppp
用来指代外设,例如 gpio
uart
adc
等,箭头起始文件引用包含了箭头指向的文件,如user file引用了stm32f4xx_hal.h文件。主要文件描述如下:
文件 | 描述 |
---|---|
stm32f4xx_hal_ppp.c stm32f4xx_hal_ppp.h | 外设基本驱动文件 |
stm32f4xx_hal_ppp_ex.c stm32f4xx_hal_ppp_ex.h | 外设扩展驱动文件 |
stm32f4xx_hal.c stm32f4xx_hal.h | 包含HAL初始化、DBGMCU、系统时间相关内容 |
stm32f4xx_hal_def.h | 公共枚举与宏定义等资源 |
用户文件
这里的用户文件指的是使用stm32cube生成的项目所需的文件:
文件 | 描述 |
---|---|
system_stm32f4xx.c | 主要包含SystemInit(),用来初始化系统时钟等 |
startup_stm32f4xx.s | 目标芯片启动文件 |
stm32f4xx_hal_msp.c | 外设系统级初始化与反初始化 |
stm32f4xx_hal_conf.h | HAL库配置,用以适配项目 |
stm32f4xx_it.c stm32f4xx_it.h | 包含项目涉及的中断服务程序 |
main.c main.h | 包含各类初始化以及用户程序主入口 |
API
分类与命名
HAL库大多数功能的外设API可以分为两类,Generic和Extension,这点从文档目录和库文件命名上就可以看出。
Generic APIs就是指普通的、通用的API,一般来说这部分API是兼容所有STM32系列芯片的,如果你的项目中只用到这部分API的话那就可以非常方便的更换MCU型号。很多时候我们也只用到这些API就可以完成项目开发了。
Extension APIs指扩展的API,这部分API涉及不同STM32系列MCU差异部分功能的操作,所以并不兼容所有STM32芯片。这部分API细分的话也可以分成两类Family specific APIs(不同系列芯片差异,比如F0、F1、F4等)和Device part number specific APIs(具体不同型号芯片差异,比如F401、F405、F429等)
命名规则见下表:
HAL库中命名还是挺统一与简单易懂的,比如使用某个GPIO口输出使用,一般就是设置输出电平,就算没有实际用过也能知道相关函数是 HAL_GPIO_xxxxx
,使用UART发送相关函数是 HAL_UART_xxxxx
,配合IDE的代码补全功能开发起来就得心应手:
基本API说明
功能分类
单个外设的API大体上可以分为四类:
类别 | 说明 | 举例 |
---|---|---|
Initialization | 初始化与反初始化 | HAL_ADC_Init() |
IO operation | 启动、停止、读写、回调函数等 | HAL_ADC_Start () HAL_ADC_ConvCpltCallback() |
Control | 相关参数设置 | HAL_ADC_ConfigChannel() |
State and Errors | 获取状态与错误信息 | HAL_ADC_GetState() HAL_ADC_GetError() |
操作模型
对于外设IO中很多耗时操作HAL库提供了三种模型:轮询、中断、DMA。比如串口读写数据就有三类方式:
- 轮询:HAL_UART_Transmit() & HAL_UART_Receive()
- 中断:HAL_UART_Transmit_IT() & HAL_UART_Receive_IT()
- DMA:HAL_UART_Transmit_DMA() & HAL_UART_Receive_DMA()
轮询是一种阻塞的方式、中断和DMA是非阻塞方式(一般结合回调函数一起使用)。对于同一个外设使用时最好不要混用,不然可能会发生不可预知的问题。
回调函数
HAL库对很对操作编写了用 __weak
符号修饰的回调函数,用户可以在自己的代码中重新定义该回调函数实现具体功能,比如下面就是串口收发完成的回调函数:
HAL_UART_TxCpltCallback() & HAL_UART_RxCpltCallback()
公共资源
公共资源指全局的宏定义、枚举、结构体等,主要定义在stm32fxxx_hal_def.h文件中。
这里主要提一个HAL Status:
typedef enum
{
HAL_OK = 0x00U,
HAL_ERROR = 0x01U,
HAL_BUSY = 0x02U,
HAL_TIMEOUT = 0x03U
} HAL_StatusTypeDef;
这个枚举类型经常出现在操作设置等的返回值中,比如HAL_StatusTypeDef HAL_UART_Transmit(),写代码时可以通过该状态知道操作是否成功等。
常用系统函数
STM32F4的HAL库系统函数介绍在文档《UM1725 - User Manual: Description of STM32F4 HAL and LL drivers》的第五篇章《HAL System Driver》(文档版本DocID025834 Rev 5 )。这里列出在STM32CubeMX生成代码时不会用到的部分常用的函数:
__weak uint32_t HAL_GetTick(void)
返回从系统运行开始经过的时间,默认情况下单位为ms;__weak void HAL_Delay(uint32_t Delay)
延时,该延时是阻塞的,默认情况下延时单位为ms,该函数不能在等于或高于系统时钟源优先级(默认情况下为0)的中断程序中使用,不然程序就阻塞在这里不动了;__weak void HAL_SuspendTick(void)
暂停系统时间运行,记得与HAL_ResumeTick()成对使用;__weak void HAL_ResumeTick(void)
继续系统时间运行;uint32_t HAL_GetUIDw0(void)
uint32_t HAL_GetUIDw1(void)
uint32_t HAL_GetUIDw2(void)
STM32芯片 96位全球唯一ID。
特殊函数
特殊操作一般用的不多,这里列举部分常用的:
全局中断
使用下面函数关闭/开启全局中断:
__disable_irq(); //关闭全局中断,等同于__set_PRIMASK(1);
__enable_irq(); //开启全局中断,等同于__set_PRIMASK(0);
__disable_irq()操作相当于把当前运行的代码优先级调整至0,所有其它用户中断程序将不会运行,直至重新开启全局中断。
使用下面函数也可以关闭/开启全局中断(有些系列的芯片没有该组函数):
__disable_fault_irq(); //关闭全局中断,等同于__set_FAULTMASK(1);
__enable_fault_irq(); //开启全局中断,等同于__set_FAULTMASK(0);
__disable_fault_irq()操作相当于把当前运行的代码优先级调整至-1,硬件错误也将被屏蔽;
软复位系统
使用 NVIC_SystemReset()
函数可以软复位系统,最好配合关闭全局中断使用,以免出现意外操作。
总结
HAL整体功能组织、命名还是比较不错的。刚从标准外设库(STD)转过来的开发者可能会不太习惯,主要是两者的设计思路上有区别。了解HAL库的功能组织和命名习惯对于理解HAL库设计思路、使用HAL库进行开发还是有促进作用的。
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐