1、聊一聊

今天跟大家推荐一首非常暖心的歌曲,一首歌曲的灵魂并不是歌曲本身,而是歌曲后面的故事,"或许喜欢这首歌,却心疼这个故事"。

最近有很多小伙伴问到一些HAL库的问题,也有一些小伙伴还在是否使用HAL库前徘徊,相信这个文章会带你正确抉择!

2、话题引出

小白,stm32标准库好久没更新了,现在入坑HAL库,用得我好难受呀!

额~,HAL库?stm32新的库吗?像安卓那种HAL层?

。。。,你不会还没玩过HAL库吧?

我们都是一些老项目了,之前用的标准库就一直用标准库咯,也没有新的外设需求。HAL库名字看上去有点高大上呀!

高大上倒看不出来,坑倒是找出来蛮多!

算了,跟你说也是白说,我去问问bug菌。

bug菌,你了解HAL库吗 ?

我知道你要问啥,最近很多人也这么问我,我这里仔细跟你讲下!

1

各个库分析

为什么很多小伙伴对于库的选择会如此的困难,终究是对库的认识还不够,当你对一个事物没有充分理解的时候,往往都会缺乏对一些标准的判断力,所以bug菌首先跟大家聊聊各个库都干了啥。

首先大家可以看一下ST官方文档对于这几个库的设计和规划,如下路径的pdf,同时bug把其中重要的几个图贴上:

(https://www.st.com/content/ccc/resource/sales_and_marketing/presentation/product_presentation/37/55/ff/bc/a8/71/4f/c5/stm32_embedded_software_offering.pdf/files/stm32_embedded_software_offering.pdf/jcr:content/translations/en.stm32_embedded_software_offering.pdf)

各种库的性能比较

各种库的抽象位置

1

寄存器

寄存器编程对于从51等等芯片过渡过来的小伙伴并不陌生,不管你是什么库,最终操作的还是寄存器,所以对于标准库、HAL库、LL库都是在寄存器上的编程,所以可以直接在各种库中直接操作寄存器。

大家都可以在库文件中找到像stm32f4xx.h这样的寄存器头文件(这里均以F4系列为例),该头文件中大概有如下几个方面的内容:

  • 寄存器地址:

  • 寄存器结构 :

  • 寄存器的位定义:

  • 操作位的宏等等:

  • 对于 “ 寄存器敲击大师 ”而言,基本上该头文件就可以搞定所有外设需求,相比其他库,直接操作寄存器来得更为直接、高效,省略了繁琐的调用和封装过程,但可移植性相对会降低一些。

  • 同时对于芯片的熟练程度也是提出了要求,对于一款相对外设比较丰富的芯片需要花一定的时间阅读文档的等等,对开发人员有一定的门槛。

2

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

标准库

标准库全名叫标准外设库(Standard Peripheral Library),其实标准库所做的事情就是对寄存器进行了封装,形成了一套API函数供用户使用,仅此而已。

  • 比如上图串口外设的API接口,其第一个参数即为串口的外设寄存器基地址,所以这些函数都是围绕寄存器来进行封装的,说白了就是寄存器的访问封装。

  • 相比直接操作寄存器,相关寄存器功能更加明确、易懂。

3

LL库

LL库是与HAL库打包发布的一部分库文件,其也叫底层库(Low-Layer),它也是对寄存器进行了封装,与标准库其实差别并不是很大。

  • 上图是LL库中的UART的相关实现,似乎函数声明部分该库中提供的API并没有标准库那么多,其实LL库中大部分API都是以static inline这样的内联函数形式进行定义的。

  • 内联函数的优势在于不会像函数调用需要跳转到定义处等额外处理,而有点像宏定义一样直接展开并copy代码到执行位置,相对效率会提高很多,当然如果代码特别大,运行时间长,也就没有内联的必要了,所以其内联函数内部代码都相对比较短小。

4

HAL库

终于到了备受关注的HAL库,HAL全名叫硬件抽象层(Hardware Abstraction layer),说实在的bug菌刚听到HAL库的时候,瞬间就把该库与windows和安卓的硬件抽象层放到同一水平线上,瞬间就把ST给拔高了,然而当我打开HAL库细细品味的时候,竟无语凝噎。

不过不管怎样,既然推出了新东西就有其存在的理由吧,比如更进一步的让开发者更少的关注底层硬件,加快产品的功能逻辑开发,降低MCU开发的门槛等等。那么下面我们一起看一下HAL库大体做了一些什么工作?

  • 在前面的标准库中提到过,所有的API接口都是围绕着外设寄存器基地址,而对于HAL其围绕的是Handle,即一个外设句柄。(如下图所示)

  • 那我们来看看这个Handle结构体到底有一些什么内容 ? (截图有点大,直接copy代码)

/**  * @brief  UART handle Structure definition  */typedef struct __UART_HandleTypeDef{  USART_TypeDef                 *Instance;        /*!  UART_InitTypeDef              Init;             /*!  uint8_t                       *pTxBuffPtr;      /*!  uint16_t                      TxXferSize;       /*!  __IO uint16_t                 TxXferCount;      /*!  uint8_t                       *pRxBuffPtr;      /*!  uint16_t                      RxXferSize;       /*!  __IO uint16_t                 RxXferCount;      /*!  DMA_HandleTypeDef             *hdmatx;          /*!  DMA_HandleTypeDef             *hdmarx;          /*!  HAL_LockTypeDef               Lock;             /*!  __IO HAL_UART_StateTypeDef    gState;           /*!                                                       and also related to Tx operations.                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */  __IO HAL_UART_StateTypeDef    RxState;          /*!                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */  __IO uint32_t                 ErrorCode;        /*!#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart);        /*!void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart);            /*!void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart);        /*!void (* RxCpltCallback)(struct __UART_HandleTypeDef *huart);            /*!void (* ErrorCallback)(struct __UART_HandleTypeDef *huart);             /*!void (* AbortCpltCallback)(struct __UART_HandleTypeDef *huart);         /*!void (* AbortTransmitCpltCallback)(struct __UART_HandleTypeDef *huart); /*!void (* AbortReceiveCpltCallback)(struct __UART_HandleTypeDef *huart);  /*!void (* WakeupCallback)(struct __UART_HandleTypeDef *huart);            /*!void (* MspInitCallback)(struct __UART_HandleTypeDef *huart);           /*!void (* MspDeInitCallback)(struct __UART_HandleTypeDef *huart);         /*!#endif  /* USE_HAL_UART_REGISTER_CALLBACKS */} UART_HandleTypeDef;
  • 从UART_HandleTypedef结构体里面的内容来看,其中不仅仅包括了UART_Typedef寄存器基地址数据结构,同时还包含通信过程的数据结构,比如缓存区指针及大小等,以及各种初始化和中断回调函数等等用户型数据。

  • 那么HAL库所实现的API不再是简单的像标准库那样封装寄存器了,而是实现了一个外设对象的数据结构封装,这样对于所有的处理只需要传入这个handle对象句柄即可对该对象进行所有操作。(可模仿学习!)

大家使用过HAL库都知道每个handle句柄结构体中都会存在MSP两个回调函数指针,如下图所示 :

这算是HAL库设计不错的地方,MSP(MCU Specific Package)表示单片机的具体方案,是MCU相关的初始化处理。

在早期使用标准库学习stm32的过程中,很多小伙伴都会有这样的体会,经常性的忘记初始化引脚、初始化时钟、处理中断优先级等等错误,那么现在HAL库通过这两个回调函数在初始化过程中用来处理与当前外设功能相关性并不大的硬件配置,这样一方面起到了提醒的目的,另一方面也增强了可移植性。

  • 当然HAL库缺点也非常明显,较多的函数嵌套以及结构体索引,会导致占用更多的程序空间,并且效率上大打折扣。

  • 对于函数指针的大量使用,虽然可以带来代码的更好的扩展和复用,但是其对于MCU的RAM占用也是一笔资源。

  • 然而HAL库性能上的损失,从而让更多的项目趋向于使用高性能MCU。

2

到底如何选择

ST并没有强制要求一定要使用哪一种库来进行开发,所以对于库的选择还是要看个人需求,通过上面的这些描述,大家应该对这些库有了一个清晰的认识,下面谈谈bug菌的几点看法 :

  • 1、寄存器库算是所有库的根基,对于技术研发非常规范的公司会直接去封装寄存库,根据自己本公司的编码规范从而实现自身的一套API,这样一方面兼容已开发算法等应用库,同时有利于代码风格统一。

  • 2、对于一些已使用标准库的老项目,如果技术到位的话,可以直接根据HAL或者LL库,进行版本上的升级和优化,从而降低产品开发风险和成本。

  • 3、对于一些新项目开发者已经非常熟悉标准库,却不想使用HAL库,但苦于标准库不再更新,可以选择LL库来进行开发。

  • 4、对于性能要求不高,且追求开发时效性,可以使用HAL与CubeMX工具结合开发,HAL 的结构更加容易整合 STM32Cube,而 STM32CubeMX 是 ST 这几年极力推荐的程序生成开发工具,bug再多应该也会得以修复,记得关注官方勘误表!

行吧,库的选择这块bug菌就谈这么多,大家可以多尝试着使用每种库,只有真正使用过了,才知道哪一种是真正适合自己的,当然在使用库的过程中你也会学到很多。

bug菌,明白了!

赶紧把每个库玩起来,别忘了三连哦!!

3、结束语

本文主要跟大家介绍了每种库的特点和选择库的一些建议,大家也可以在下面留言处留下你的观点!

好了,这里是公众号:“最后一个bug”,一个为大家打造的技术知识提升基地,如果你喜欢交流可以添加下方bug菌微信,我拉你加入公众号技术交流群。

推荐好文  点击蓝色字体即可跳转

☞【开源】bug菌把"动态数字显示"开源了!

☞【MCU】可怕,别人把我MCU固件给反汇编了!(逆向)

☞ 【程序人生】学不到东西,不想呆在这家公司了!

☞ 【C进阶】"最常见"却又"最不常用"的三个预编译

hal库开启中断关中断_【MCU】寄存器、标准库、HAL库、LL库,这么多库!你叫我怎么选?...相关推荐

  1. hal库开启中断关中断_「正点原子NANO STM32开发板资料连载」第十章 外部中断实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十章 外 ...

  2. hal库开启中断关中断_STM32 HAL库学习系列第9篇---NVIC按键外部中断函数

    原文首发于同名微信公号「Allen5G」,欢迎大家搜索关注! **针对HAL库的中断操作,使用按键实例进行说下,以供参考---------------------------**void HAL_GP ...

  3. 华图砖题库php文件怎么打印_事业单位招聘考试《工会基础知识》试题库及答案1380题...

    2020年事业单位招聘考试<工会基础知识>试题库及答案1380题 目录: 1.<中华人民共和国工会法>试题库及答案解析51题. 2.<中国工会章程>试题库及答案解析 ...

  4. hal库开启中断关中断_[STM32]HAL库下GPIO按键中断与去抖问题分析(分析源码解决问题)...

    自上篇文章STM32 非阻塞HAL_UART_ReceiveIT解析与实际应用,具体总结了HAL库下套娃函数中如何看清库函数的脉络,更细致的认识调用的过程,以解决潜在的问题.又又又遇到了新的问题(GP ...

  5. hal库开启中断关中断_(2)STM32使用HAL库操作外部中断——理论讲解

    1.中断触发过程 对主程序压栈--把中断服务函数的地址写入到程序计数器(PC)--执行中断服务函数 2.中断向量表 中断服务函数的地址在STM32的手册上的中断向量表中(如下是一部分): 如上表所示, ...

  6. hal库开启中断关中断_STM32对HAL库的定时器中断

    从串口中断,到外部中断再到现在的定时器中断,越来越感觉HAL库应用比较好用,虽然一开始理解上面有点怪,但是网上查询一下就能够学会. 定时器中断分为两个重点,1.在应用CUBEMX时配置定时器的分频数以 ...

  7. hal库开启中断关中断_stm32的HAL库开发学习笔记之外部中断

    外部中断 中断线----EXTI线0~15(对应外部IO口的输入中断) 每个IO口都可以作为外部中断输入 每个中短线可以独立的配置触发方式(上升沿,下降沿,双边沿),触发/屏蔽,专用状态位. GPIO ...

  8. python安装成功第三方库但import出问题_为什么会在pyspark在RDD中调用python第三方库失败?...

    问题描述 Hi, 我在公司线上运行pyspark时调用jieba分词, 发现可以成功import, 但是在RDD中调用分词函数时却提示没有 module jieba, 在本地虚拟机时没有这些问题 问题 ...

  9. stm32F051 HAL库+DMA+串口空闲中断

    STM32CubeMX 配置实现参考这里. 1. 串口空闲中断 1.1 UART_DMA方式接收数据 STM32串口使用DMA方式接收数据可以减小CPU的开销. 对于接收定长数据,可以将DMA接收缓冲 ...

  10. 【STM32+cubemx】0007 HAL库开发:外部中断,优先级和中断向量表

    这一节我们以外部中断为例子,讲讲中断的优先级和中断向量表的知识. 1)cubemx生成代码 首先还是在cubemx中生成代码,选择器件.设置SYS(调试接口).设置RCC(外部晶振时钟源). 然后设置 ...

最新文章

  1. 高薪必备的一些Spring Boot高级面试题
  2. windows 10下搭建pyspark与遇到的一些问题的解决方法
  3. 安卓USB开发教程 四 安卓 AOA
  4. Mysql(一)——基础知识
  5. MATLAB学习笔记(五)
  6. 女人活到后半生才会明白:兜里有钱,才有安全感
  7. 编写一份代码,支持多种布署方式
  8. pdf转HTML出现乱码,PDF转Word出现乱码解决方法
  9. 微信扫一扫二维码直接打开手机默认外部浏览器
  10. 央行企业征信异议、声明业务办理流程?
  11. halcon第六讲:基于颜色空间的颜色检测
  12. D3DTOP_DOTPRODUCT3的计算公式
  13. 【Axure原型图】——动态面板
  14. css使用定义动画anima,CSS Transform和动画
  15. 技术 KOL 龙神:永远挑战难度值增加 30% 的事情
  16. iPad怎么分屏?学会这个方法,轻松拿捏
  17. Android 实现GIF播放的几种方式
  18. markdown竖式计算
  19. ThinkPHP实现百度网盘下载功能,必备!
  20. Vegas Pro 18官方中文版激活序列号版下载,为何能成为大神级剪辑师的首选?

热门文章

  1. 为了满足自己的好奇心,搞了一个业余项目耍,没想到还给我带来了$3000的收入......
  2. 淘宝昨现重大线上bug,S1级事故,疑似程序员故意埋雷
  3. 亲,你们都在家办公吗?啥感受?hahaha
  4. 一篇全面的 MySQL 高性能优化实战总结!
  5. 架构师进阶:Linux进程间如何共享内存?
  6. 未来互联网还有哪些值得关注的趋势?
  7. 昨天发生的四件大事!
  8. 大部分人最缺的其实是「认知」
  9. java string的内存模型_Java String内存模型
  10. Delphi2010 RTTI + Attribute 简单实现ORM实例