它很大程度上基于意见,如果这个问题因此而被关闭,我不会感到惊讶。这个答案只涉及您所询问的几个方面。这是一个非常广泛的主题,很难(如果不是不可能的话)将所有内容都包含在一篇文章中,最终不会有几页长。然而,为了给你我对这个话题的看法,在努力保持公正的同时,简短的回答是......这取决于。
如果您询问在最常见的情况下使用什么,很可能是您提到的 HAL(以前称为 StdPeriph)函数。原因是 - 他们在最常见的情况下完成了工作。毕竟,它总是归结为创建产品的成本。如果 HAL 函数对于该目的来说“足够好”,那么它们将被使用,因为它们的开发速度更快。开发成本越高,您就越想削减它(或将其移至其他地方),而使用抽象是这样做的一种方式。
但是,即使我认为可以安全地假设通常使用 HAL / Std Periph / 任何其他(包括专有)抽象层,但情况并非总是如此,至少有两个原因我能想到:
现有功能可能不适合您的目的。以 HAL 为例,它适用于大多数常见情况,但有时您的需求可能非常具体,以至于您不得不去“在幕后”搞砸,通常最终要么编写自己的函数变体在 HAL 之上构建新的东西。就我个人而言,我至少能想到几个例子,其中 HAL 函数并不是我所需要的。这并不一定意味着图书馆不好,只是有时要求非常具体。
出于性能原因,有时可能需要直接使用寄存器。HAL 和类似的东西是一个抽象层,与任何抽象一样,它们的执行时间比直接使用寄存器要多。如果您试图从给定的外围设备中挤出绝对最大值,则有时必须降低到寄存器级别。
现在到我的回答中更偏颇的部分。我明白你为什么问这个问题。来自闪存或 CPU 时钟更宝贵的 PIC 世界,直接在那里使用寄存器确实有意义。对于 STM32,它不再那么重要了。话虽如此,您有时会偶然发现“使用寄存器是唯一正确的方法”的观点,但我个人发现这样的讨论最终纯粹是学术性的。我将寄存器或建立在它之上的任何抽象视为工具,您应该为正确的工作使用正确的工具。不使用正确工具的两个例子:
你只使用寄存器作为“唯一正确的方法”,要么是因为你自己相信,要么是有人告诉你。您的产品需要两倍(如果不是更多)时间来开发,您的代码在闪存中占用的空间更少(所以现在您使用 46% 的 1MB 闪存而不是 48%)。对性能至关重要的代码可以实现其目标。放宽执行时间限制的代码也非常高效,但它不会对最终客户产生太大影响(如果有的话)。您的代码的可重用性也较低——您会发现每次为新的 MCU 系列发布新产品时,您都会一遍又一遍地重写相同的代码部分。
您只使用 HAL / 任何其他类似的抽象,因为“您没有选择如此强大的 MCU 必须下降到寄存器级别”,或者因为您被告知永远不应该触摸寄存器。您的开发速度要快得多,并且可以发布两种产品,而不仅仅是使用寄存器发布一种产品。但是,当您必须达到执行时间限制/传输速度时,您会发现自己选择的 MCU 比理论上需要的功能更强大。有时您会发现自己围绕 HAL 编写包装器,因为它们并没有为您提供所需的功能 - 感觉就像让它变得比应有的更复杂。
所以毕竟,如果我想说的是,你应该根据具体情况使用适合工作的东西。在 STM32 的情况下,您现在有 3 个选项:HAL(顶级抽象级别)、HAL LL(低级抽象 - 通常是围绕寄存器访问的简单包装函数)或直接使用寄存器。您选择哪一个应该来自您的要求。