本文为百问网&韦东山【物联网智能家居实战训练营】课程笔记
1 HAL库基本特点
官方固件包组织,以STM32CubeF1
为例(github链接):
标准库、HAL库、LL库对比:
HAL
库可移植性、易用性具有优势,但是存储空间占用大、执行效率相对较低。(牺牲了时间与空间效率,换来了兼容整个ST产品的封装性,同时上手简单)
2 HAL库驱动框架
2.1 框架分析
以定时器函数接口为例,展示HAL库编程模型:
/* Time Base functions ********************************************************/
// 初始化/复位
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim);
/* Blocking mode: Polling */
// 轮询模式
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
/* Non-Blocking mode: Interrupt */
// 中断模式
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
/* Non-Blocking mode: DMA */
// DMA模式
HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length);
HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim);
以串口中断为例,展示中断函数调用处理流程:
stm32f1xx_it.c
中的串口中断服务程序USART2_IRQHandler
:
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
}
stm32f1xx_hal_uart.c
中的串口中断处理函数HAL_UART_IRQHandle
r:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
/* ... */
if (errorflags == RESET)
{
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
}
/* ... */
- 串口接收中断处理函数
UART_Receive_IT(huart)
:
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
/* ... */
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
HAL_UART_RxCpltCallback(huart);
/* ... */
}
串口接收事件处理与接收完成中断回调函数(弱定义,用户可重新定义该函数):
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
UNUSED(huart);
UNUSED(Size);
}
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
}
2.2 用户代码添加位置
头文件、数据类型及函数声明的添加位置:
main.c
用户代码添加位置:
USER CODE BEGIN/END 0
:用户函数USER CODE BEGIN/END 1
:外设初始化前的代码(此时时钟还未配置)USER CODE BEGIN/END Init
:外设初始化代码USER CODE BEGIN/END 2
:外设启动代码USER CODE BEGIN/END WHILE
:while循环中的后台程序USER CODE BEGIN/END 3
:while循环结束函数(一般用不着)USER CODE BEGIN/END 4
:用户函数和中断回调函数代码
学习HAL库可以参考其中的注释#### How to use this driver ####
。
3 总结
- 外设句柄结构体包含两部分:属性与回调函数指针。
- HAL三种编程模型:轮询、中断、DMA。
HAL_xx_MspInit
用于初始化底层外设(GPIO、时钟、DMA、中断等),再调用HAL_xx_Init
初始化对应的外设寄存器,函数参数均为句柄结构体。- 以
ex
结尾的文件表示该芯片的特有功能,为了兼容产品系列中的不同芯片。
END