目录

  • HAL库外设设计思想
    • HAL库和Cube MX相结合
  • 一、对外设的封装——句柄结构体
  • 二、外设初始化
    • 初始化结构体
    • 初始化的逻辑
  • 三、外设使用逻辑
    • 通用接口函数
      • 初始化函数
      • I/O操作函数
      • 控制函数
      • 状态参数
    • 扩展接口函数
  • 总结

HAL库外设设计思想

HAL库借鉴面向对象的设计思想,将外设驱动封装为对象。

采用此种开发方式有以下特点:

  • 屏蔽底层硬件:只需了解相关接口函数的功能和参数要求即可
  • 提高开发效率:开发难度较小,开发周期较短,后期的维护升级、以及硬件平台的移植等工作量小
  • 程序执行效率:由于考虑了程序的稳健性、扩充性和可移植性,程序代码比较繁琐和臃肿,执行效率较低

HAL库和Cube MX相结合

一、对外设的封装——句柄结构体

围绕着芯片设计的外设多种多样,功能也越来越多,为了能够统一管理这些外设,HAL库设计了统一的外设句柄数据类型PPP_HandleTypeDef(PPP代表外设名称)。如定时器句柄:

/*** @brief  TIM Time Base Handle Structure definition*/
typedef struct
{TIM_TypeDef                 *Instance;     /*!< Register base address             */TIM_Base_InitTypeDef        Init;          /*!< TIM Time Base required parameters */HAL_TIM_ActiveChannel       Channel;       /*!< Active channel                    */DMA_HandleTypeDef           *hdma[7];      /*!< DMA Handlers array This array is accessed by a @ref DMA_Handle_index */HAL_LockTypeDef             Lock;          /*!< Locking object                    */__IO HAL_TIM_StateTypeDef   State;         /*!< TIM operation state               */
} TIM_HandleTypeDef;

保护锁是HAL库提供的一种安全机制,以避免对外设的并发访问。

二、外设初始化

由上述的句柄结构体可知,我们需要定义一个外设句柄指针,并向其中填充参数,其中最重要的就是初始化参数,为此HAL库为不同的外设定义了不同的初始化结构体,且相同外设的不同功能也有不同的初始化结构,如定时器,有时基单元初始化结构体、输入初始化结构体和输出初始化结构体等,分别用于输入捕获和输出比较等不同功能。
初始化这一步骤使用CubeMX配置,可自动生成初始化代码,大大减少了开发难度。如下的初始化函数代码即由CubeMX自动生成的,带有MX前缀。

初始化结构体

代码如下(示例):

/*** @brief  TIM Time base Configuration Structure definition*/
typedef struct
{uint32_t Prescaler;         uint32_t CounterMode;  uint32_t Period;           uint32_t ClockDivision;    uint32_t RepetitionCounter;  uint32_t AutoReloadPreload;
} TIM_Base_InitTypeDef;
/*** @brief  TIM Input Capture Configuration Structure definition*/
typedef struct
{uint32_t  ICPolarity;  uint32_t ICSelection;  uint32_t ICPrescaler;  uint32_t ICFilter;
} TIM_IC_InitTypeDef;
/*** @brief  TIM Output Compare Configuration Structure definition*/
typedef struct
{uint32_t OCMode;   uint32_t Pulse;        uint32_t OCPolarity;    uint32_t OCNPolarity;   uint32_t OCFastMode;   uint32_t OCIdleState;   uint32_t OCNIdleState;
} TIM_OC_InitTypeDef;

初始化的逻辑


如我们在串口笔记中讲到的串口初始化过程,在HAL_PPP_Init()初始化函数中,将句柄结构中的初始化参数存入寄存器,即进行相关参数的传入赋值,然后调用HAL_PPP_MspInit()函数完成具体的时钟、引脚等资源初始化,完成围绕具体MCU的配置;MSP函数调用完成后,回到HAL_PPP_Init()函数调用现场,根据返回值情况进入下一步,最后完成外设初始化。
以串口为例:
代码如下(示例):

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}
}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USART1 DMA Init *//* USART1_RX Init */hdma_usart1_rx.Instance = DMA1_Channel5;hdma_usart1_rx.Init.Request = DMA_REQUEST_2;hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_rx.Init.Mode = DMA_NORMAL;hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);/* USART1_TX Init */hdma_usart1_tx.Instance = DMA1_Channel4;hdma_usart1_tx.Init.Request = DMA_REQUEST_2;hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_tx.Init.Mode = DMA_NORMAL;hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);}
}

三、外设使用逻辑

通用接口函数

初始化函数

通过上述的初始化步骤完成调用。

I/O操作函数

根据不同的功能使用,设计了三种不同的编程模型:轮询、中断和DMA。
以后缀区分,入口参数均为外设句柄的指针,其中轮询模式还需要传入超时时间参数。三种不同编程模型的具体实现可参考串口的三篇笔记。

控制函数

可以在使用中,动态的调节外设的参数,如中断及时钟。

状态参数

可以清除和查询一些标志位,获取外设的运行状态以及出错信息。

扩展接口函数

设计扩展接口函数可以兼顾STM32各产品系列的特有功能和扩展功能,兼顾同一个产品系列中不同芯片的特有功能。通过单独定义后续为ex的文件来实现。如stm32fxxx_hal_ppp_ex.hstm32fxxx_hal_ppp_ex.c

总结

HAL库外设的使用步骤总结如下:

  1. 定义并填充PPP外设句柄结构体
  2. 如果遵循HAL库规范,通过HAL_MspInit()函数,实现外设底层资源的初始化,包括但不限于GPIO、时钟、DMA、中断等资源的初始化
  3. 调用HAL库的对应外设初始化函数,形如:HAL_PPP_Init()
  4. 初始化完成,开始使用外设
  5. 使用方法具体查看对应外设的HAL库驱动包中的说明:##### How to use this driver#####

HAL库学习笔记-10 HAL库外设驱动框架概述相关推荐

  1. STM32 HAL库学习笔记2 HAL库介绍

    STM32 HAL库学习笔记2 HAL库介绍 CMSIS标准 一.再次认识HAL库 HAL库设计思想 HAL库实现方式 以GPIO模块为例 GPIO外设数据类型 GPIO外设接口函数 二.使用HAL库 ...

  2. python的gdal库说明_GDAL库学习笔记(一): GDAL库介绍

    可能你不玩GIS,不懂这个库到底有什么用,或者和python有什么关系.但是你要玩GIS,RS,你就应当知道这个库的价值.就算你不玩GIS,我想这个库对你也应该有致命的吸引力.为什么?看下面的介绍吧! ...

  3. poco库学习笔记(1) poco库的安装

    1.下载安装 到官网http://pocoproject.org/下载最新版本poco-1.4.4.tar.gz,解压tar -xzvf poco-1.4.4.tar.gz,然后./configure ...

  4. C++标准库学习笔记——标准模板库笔记

    目录 1. STL组件 2. 容器 2.1 容器分类 2.2 三种容器实现原理 2.3 关联式和无序容器的小知识点 2.4 容器适配器 3. 迭代器 3.1 迭代器概念与基本操作 3.2 迭代器的半开 ...

  5. 我的内核学习笔记10:Intel GPIO驱动源码分析

    本文对Intel e3800的GPIO驱动源码进行分析. 一.概述 1.1 内核配置 Intel e3800的GPIO在Linux内核中使用的驱动名为gpio_ich(为了行文方便,将对应的设备称为& ...

  6. STM32 HAL库学习笔记1-HAL库简介

    STM32 HAL库学习笔记1-HAL库简介 HAL库 SPL 库 和 HAL 库两者相互独立,互不兼容.几种库的比较如下 目前几种库对不同芯片的支持情况如下 ST 中文官网上有一篇<关于ST库 ...

  7. Python_pygame库学习笔记(1):pygame的由来,特点以及模块简介

    Python_pygame库学习笔记 1 Pygame库的由来: Python适合用来开发游戏吗? Pygame的安装 Pygame模块简介 Pygame库的由来: 2000年,作者Pete Shin ...

  8. STM32 HAL库学习笔记4-SPI

    STM32 HAL库学习笔记4-SPI 前言 一.SPI协议简介 SPI物理层 SPI协议层 1.基本通讯过程 2. 通讯的起始和停止信号 3. 数据有效性 4. CPOL/CPHA 及通讯模式 二. ...

  9. STM32F407霸天虎HAL库学习笔记——使用ADC采集MQ135的数据并通过OLED显示

    STM32F407霸天虎HAL库学习笔记--使用ADC采集MQ135的数据并通过OLED显示 一.软件准备 二.硬件准备 三.CubeMX配置 四.Keil MQ135.c MQ135.h main函 ...

  10. STM32F407霸天虎HAL库学习笔记——串口发送

    STM32F407霸天虎HAL库学习笔记--串口收发 一.软件准备 二.硬件准备 三.CubeMX配置 四.Keil printf重写 main函数 五.实验效果 一.软件准备 软件准备 二.硬件准备 ...

最新文章

  1. Linux CPU数量判断命令
  2. vmware tools安装程序无法继续,Microsoft Runtime DLL安装程序未能完成安装。的解决方法
  3. discuz 的 group.php,DiscuzX用户组过期问题解决方法
  4. oracle00333,Oracle数据库REDO损坏ora-00333修复手札
  5. 为什么程序必须得会C语言?
  6. Redis面试刁难大全
  7. Enjoy模板里使用layui模板引擎laytpl
  8. CenterOS yum 使用
  9. icmp协议_ICMP协议全解析
  10. 数据结构与算法(三)-线性表之静态链表
  11. java for 变量赋值_Java 如何引用变量赋值?
  12. 西安互联网公司和生活成本
  13. 我(和谐)草(和谐)尼(和谐)玛
  14. android 3d翻转动画 viewpage,利用ViewPager实现3D画廊效果及其图片加载优化
  15. 经典游戏PK:魔兽争霸VS星际争霸VS红警
  16. webAppRootKey
  17. 一朵花的组成结构图_请问一朵完整的花由哪几部分组成
  18. 视频片段怎么做成gif图?快试试这2种方法
  19. 路由器局域网IP(内网IP)和外网IP的关系
  20. 雷军:天使投资人不是上帝只是配角

热门文章

  1. 方波正弦波三角波信号发生电路
  2. vnc远程控制linux密码,如何使用VNC远程控制Linux(Centos)?
  3. 中国正从法律入手编织公民信息保护网
  4. Rust的各种花式汇编操作
  5. 【免费】前端设计师必须知晓的网站(1)
  6. VirtualBox安装增强功能
  7. 《活着》读后感4500字
  8. 2019年伯克利大学 CS294-112《深度强化学习》第4讲:强化学习简介(笔记)
  9. pytorch实现resnet50
  10. 第六章 平均绝对误差(MAE)与均方根误差(RMSE)