本文主要是介绍STM32F1 HAL库笔记0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
参考UM1850 Description of STM32F1 HAL and low-layer drivers
1、STM32Cube 包括:
• STM32CubeMX,图形软件配置工具,使用图形向导生成 C 初始化代码。
• 嵌入式软件平台,按系列提供(例如用于STM32F1的STM32CubeF1),包括:
——STM32Cube HAL,STM32抽象层嵌入式软件,确保在STM32产品组合中实现最大的可移植性。HAL API 可用于所有外围设备。
——低层 API (LL) 提供快速、轻量级、面向专家的层,比 HAL 更接近硬件。LL API 仅适用于一组外围设备。
—— 一组一致的中间件组件,例如 RTOS、USB、TCP/IP 和图形。
——所有嵌入式软件实用程序,随附全套示例。
!!!以上的意思,写STM32的程序的方法是,通过使用STM32CubeMX生产初始代码,调用HAL APIs、LL APIs或者搭配RTOS来完成开发工作。有示例程序可参考的。
2、HAL的特征
HAL针对功能模块,不是外设器件。啥意思?例如,一个USART 外设会存在这么几个模块:UART 驱动程序模块、USART 驱动程序模块、SMARTCARD 驱动程序模块和 IRDA 驱动程序模块。模块,在程序里理解为C语言数据结构struct,或者C++的类,使用时实例化为实例instance。
API分为通用API和扩展API(也就是当初没设计,后来又设计了一些特殊功能)。
三种 API 编程模型:轮询、中断和 DMA。(API里有不同的后缀区分)
API 符合 RTOS 标准:完全可重入的 API (RTOS不同线程调用同一API,不会死锁);在轮询模式下系统地使用超时(阻塞延时,RTOS可以重新调度运行其它线程)。
支持外设多实例,允许对给定外设的多个实例(USART1、USART2...)进行并发 API 调用。
三种用户回调函数(写程序只用启动,然后写好回调函数就行):
——初始化外设 Init/DeInit回调函数,执行外设系统级初始化/取消初始化(一般操作这些:时钟、GPIO、中断、DMA)
——外设中断事件回调,中断处理函数里已经清除中断标志,直接写业务逻辑
—— 错误事件回调
对象锁定机制:安全的硬件访问,防止对共享资源的多次虚假访问。
用于所有阻塞进程的超时:超时可以是简单的计数器或时基。超时和延时在HAL里很重要,一般默认为systick为时基。
3、HAL数据结构
有三种,外设句柄结构、初始化和配置结构、处理流程结构。
——外设句柄结构:PPP_HandleTypeDef *handle;每个外设/模块实例都有自己的句柄,实例资源是独立的。外设进程通信:句柄结构有通信资源,全局指针、DMA 句柄、状态机。存储:句柄可以有全局变量,存储数据。
例子:usart句柄,可以实例化为USART1、USART2......结构体有发送接收过程的buffer,有DMA的句柄,状态机,出错控制等。还有初始化句柄。
typedef struct
{
USART_TypeDef *Instance; /* USART registers base address */
USART_InitTypeDef Init; /* Usart communication parameters */
uint8_t *pTxBuffPtr;/* Pointer to Usart Tx transfer Buffer */
uint16_t TxXferSize; /* Usart Tx Transfer size */
__IO uint16_t TxXferCount;/* Usart Tx Transfer Counter */
uint8_t *pRxBuffPtr;/* Pointer to Usart Rx transfer Buffer */
uint16_t RxXferSize; /* Usart Rx Transfer size */
__IO uint16_t RxXferCount; /* Usart Rx Transfer Counter */
DMA_HandleTypeDef *hdmatx; /* Usart Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /* Usart Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /* Locking object */
__IO HAL_USART_StateTypeDef State; /* Usart communication state */
__IO HAL_USART_ErrorTypeDef ErrorCode;/* USART Error code */
}USART_HandleTypeDef;
多实例特性意味着应用程序中使用的所有 API 都是可重入的,例子???
GPIO、SYSTICK、NVIC、PWR、RCC、FLASH这些共享外设,不适用句柄结构来描述,直接使用HAL函数。
——初始化和配置结构,这个好理解,例如UART_InitTypeDef、HAL_ADC_ConfigChannel (ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)。
——处理流程结构,例如:HAL_PPP_Process (PPP_HandleTypeDef* hadc,PPP_ProcessConfig* sConfig)。
4、API分类
通用APIs
HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc);
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);
扩展APIs
系列特定API
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t Sing
leDiff); uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t S
ingleDiff);
指定型号API
HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_tLengt
h);
HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc);
5、HAL 驱动程序规则
5.1、HAL API 命名规则
File names stm32f1xx_hal_ppp.c/stm32f1xx_hal_ppp.h
Module name HAL_PPP_ MODULE
Function name HAL_PPP_Function、HAL_PPP_FeatureFunction_MODE
Handle name PPP_HandleTypedef
Init structure name PPP_InitTypeDef
Enum name HAL_PPP_StructnameTypeDef
PPP 前缀是指外设功能模式,而不是外设本身。例如,如果 USART,PPP 可以是 USART、IRDA、UART 或 SMARTCARD,具体取决于外设模式。
一个文件中使用的常量在此文件中定义。在多个文件中使用的常量在头文件中定义。所有常量都以大写形式写入,但外设驱动程序函数参数除外。
typedef 变量名称应以 _TypeDef 为后缀。
寄存器被视为常量。在大多数情况下,它们的名称为大写,并使用与 STM32F1 参考手册中相同的首字母缩略词。
外设寄存器在 CMSIS 标头的 PPP_TypeDef 结构(例如 ADC_TypeDef)中声明:stm32f1xxx.h 对应于 stm32f100xb.h、stm32f100xe.h、stm32f101x6.h等
外设函数名称以 HAL_ 为前缀,然后是相应的外设首字母缩略词(大写),后跟下划线。每个单词的首字母为大写(例如 HAL_UART_Transmit())。函数名称中只允许使用一个下划线,以将外设首字母缩略词与函数名称的其余部分分隔开。
包含 PPP 外设初始化参数的结构命名为 PPP_InitTypeDef (例如 ADC_InitTypeDef)。
包含 PPP 外设设备的特定配置参数的结构命名为 PPP_xxxxConfTypeDef (例如 ADC_ChannelConfTypeDef)。
外设句柄结构命名为 PPP_HandleTypedef (例如 DMA_HandleTypeDef)
用于根据 PPP_InitTypeDef 中指定的参数初始化 PPP 外设的函数命名为 HAL_PPP_Init (例如 HAL_TIM_Init())。
用于将 PPP 外设寄存器重置为默认值的函数命名为 HAL_PPP_DeInit (例如 HAL_TIM_DeInit())。
MODE 后缀是指进程模式,可以是轮询、中断或 DMA。例如,当除了原生资源之外还使用 DMA 时,应该调用该函数:HAL_PPP_Function_DMA () 。
Feature 前缀应引用新功能。示例:HAL_ADC_Start()是指注入模式。
5.2、HAL 一般命名规则
对于共享外设和系统外设,不使用句柄或实例对象。此规则适用于以下外围设备:GPIO、 SYSTICK、NVIC、RCC、FLASH。
GPIO示例:HAL_GPIO_Init() 只需要 GPIO 地址及其配置参数。
HAL_StatusTypeDef HAL_GPIO_Init (GPIO_TypeDef* GPIOx, GPIO_InitTypeDef *Init)
{
/*GPIO Initialization body */
}
中断示例:在每个 peripheral/module driver中,定义了处理中断和特定时钟配置的宏。这些宏将导出到外设驱动程序头文件中使用它们。这些宏的列表定义如下:
__HAL_PPP_ENABLE_IT(__HANDLE__, __INTERRUPT__) //中断使能
__HAL_PPP_DISABLE_IT(__HANDLE__,__INTERRUPT__) //中断失能
__HAL_PPP_GET_IT (__HANDLE__, __ INTERRUPT __) //获取中断IT标志
__HAL_PPP_CLEAR_IT (__HANDLE__, __ INTERRUPT __) //清除中断IT标志
__HAL_PPP_GET_FLAG (__HANDLE__, __FLAG__) //获取中断flag
__HAL_PPP_CLEAR_FLAG (__HANDLE__, __FLAG__) //清除中断flag
__HAL_PPP_ENABLE(__HANDLE__) //使能外设
__HAL_PPP_DISABLE(__HANDLE__) //失能外设
__HAL_PPP_XXXX (__HANDLE__, __PARAM__) //特定的PPP HAL driver宏
__HAL_PPP_GET_ IT_SOURCE (__HANDLE__, __INTERRUPT __) //获取中断源
NVIC 和 SYSTICK 是 Arm® Cortex® 的两个核心功能。与这些功能相关的 API 位于 stm32f1xx_hal_cortex.c 文件中。
(原书应该写错了)PPP_InitTypeDef句柄在使用 HAL_PPP_Init() API之前有效。init 函数在修改 handle 字段之前执行检查。如下形式:
hppp = HAL_PPP_Init(PPP_InitTypeDef)
if(hppp == NULL){ return HAL_ERROR;}
宏包括,条件宏:使用?:运算符而已。
#define ABS(x) (((x) > 0) ? (x) : -(x))
伪代码宏 (多指令宏):使用do{}while(0)包含多个指令而已。
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD_, __DMA_HANDLE_) \
do{ \
(__HANDLE__)->__PPP_DMA_FIELD_ = &(__DMA_HANDLE_); \
(__DMA_HANDLE_).Parent = (__HANDLE__); \
} while(0)
5.3、HAL 中断处理程序和回调函数
HAL 外设驱动程序还包括 中断处理程序HAL_PPP_IRQHandler()(在stm32f1xx_it.c),用户回调函数(具有 “weak” 属性的空函数,必须在用户代码中定义)。
有三种类型的用户回调函数:外设初始化/去初始化回调:HAL_PPP_MspInit() 和 HAL_PPP_MspDeInit();处理完成回调:HAL_PPP_ProcessCpltCallback(); 错误回调:HAL_PPP_ErrorCallback()。
回调函数 示例
HAL_PPP_MspInit() / _DeInit()
例如:HAL_USART_MspInit():HAL_PPP_Init() API 函数调用此函数,以执行外设系统级初始化(即初始化GPIO、时钟、DMA、中断)。
HAL_PPP_ProcessCpltCallback()
例如:HAL_USART_TxCpltCallback():当USART TX完成时由外设或DMA的中断处理程序调用
HAL_PPP_ErrorCallback()
例如:HAL_USART_ErrorCallback(): 发生错误时由外设或DMA的中断处理程序调用
6、HAL 通用 API
有4组通用API:
初始化/去初始化:HAL_PPP_Init()、HAL_PPP_DeInit()
IO 操作:HAL_PPP_Read()、HAL_PPP_Write()、HAL_PPP_Transmit()、HAL_PPP_Receive()
控制功能:HAL_PPP_Set()、HAL_PPP_Get()。
State 和 Errors 函数:HAL_PPP_GetState()、HAL_PPP_GetError()
初始化和去初始化功能允许初始化外设和配置硬件资源,主要是时钟、GPIO、替代功能 (AF) 以及可能的 DMA 和中断。HAL_DeInit() 函数恢复 外设默认状态,释放硬件资源并删除与硬件的任何直接依赖关系。
IO 操作函数对外设有效数据执行基本的写入和读取访问。
控制功能用于动态更改外设设备配置,并设置另一种操作模式。
外设状态和错误功能允许在运行时检索外设和数据流状态,并识别发生的错误类型。
下面的示例基于 ADC 外设。泛型 API 的列表并不详尽。它仅作为示例给出。
初始化组
HAL_ADC_Init() //此函数初始化外设并配置相关资源(时钟、GPIO、AF 等)
HAL_ADC_DeInit() //此函数恢复外设默认状态,释放相关资源并消除与硬件的任何直接依赖关系。IO 操作组
HAL_ADC_Start () //此函数在使用轮询方法时启动 ADC 转换
HAL_ADC_Stop () //此函数在使用轮询方法时停止 ADC 转换
HAL_ADC_PollForConversion() //此函数允许在使用轮询方法时等待转换结束。在这种情况下,超时值由用户根据应用程序指定。
HAL_ADC_Start_IT() //此函数在使用中断方法时启动 ADC 转换
HAL_ADC_Stop_IT() //此函数在使用中断方法时停止 ADC 转换
HAL_ADC_IRQHandler() //此函数处理 ADC 中断请求
HAL_ADC_ConvCpltCallback() //在 IT 子例程中调用的回调函数,以指示当前进程的结束或当 DMA 传输完成时
HAL_ADC_ErrorCallback() //在 IT 子例程中调用的回调函数,如果发生外设错误或 DMA 传输错误 控制组
HAL_ADC_ConfigChannel() //此功能配置选定的 ADC 常规通道、定序器中的相应列和采样时间
HAL_ADC_AnalogWDGConfig //此功能为选定的 ADC 配置模拟看门狗状态和错误组
HAL_ADC_GetState() //此功能允许在运行时获取外设和数据流状态。
HAL_ADC_GetError() //此功能允许在运行时获取 IT 例程中发生的错误
7、HAL 扩展 API
扩展 API 为特定系列或同一系列中的特定型号提供特定功能或覆盖修改后的 API。扩展API位于 stm32f1xx_hal_ppp_ex.c、stm32f1xx_hal_ppp_ex.h。
基于 ADC 外设的示例:HAL_ADCEx_CalibrationStart() //此功能用于启动自动 ADC 校准
添加新功能的扩展API怎么扩展:5种方式如下:
(1)在文件stm32f1xx_hal_ppp_ex.c(h)里增加API HAL_PPPEx_Function()
例如stm32f1xx_hal_adc_ex.c/h里
#if defined(STM32F101xG) || defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F
105xC) ||
defined (STM32F107xC) || defined (STM32F103xE) || defined(STM32F103xG)
/* ADC multimode */
HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint
32_t Length);
HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc);
#endif
(2)新增一个.c文件stm32f1xx_hal_newppp.c,并在stm32f1xx_hal_conf.h使用宏开启:#define HAL_NEWPPP_MODULE_ENABLED
(3)将stm32f1xx_hal_ppp.c的API加__weak修饰,在文件stm32f1xx_hal_ppp_ex.c里覆写此API
(4) 加入数据结构中,使用#if defined来控制开启
#if defined(STM32F100xB)
typedef struct
{
(...)
}PPP_InitTypeDef;
#endif /* STM32F100xB */
8、include头文件
stm32f1xx_hal_conf.h:PPP 驱动程序是项目中使用的独立模块。用户必须在配置文件stm32f1xx_hal_conf.h中使用相应的 USE_HAL_PPP_MODULE define 语句来使能某个PPP驱动程序。例如:#define USE_HAL_USART_MODULE、 #define USE_HAL_IRDA_MODULE
stm32f1xx_hal.h:stm32f1xx_hal.h包含了整个 HAL 库的通用配置。用户程序和 HAL C源文件中只需包含包含此头文件调用HAL资源。stm32f1xx_hal.h包含了stm32f1xx_hal_conf.h。
9、HAL 通用的定义
在 stm32f1xx_hal_def.h 中定义了常见的枚举、结构和宏。
待续,要去练车,科目三
这篇关于STM32F1 HAL库笔记0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!