HAL库 vs 标准库:用STM32CubeMX+Keil5实测GPIO翻转速度差异
最近在做一个电机驱动项目,对IO口的翻转速度要求比较高,用STM32CubeMX生成的HAL库代码跑起来总觉得有点“肉”,响应不够干脆。这让我想起了以前用标准库时那种直接、利落的感觉。于是,我决定做个实验,用同样的硬件(一块STM32F103C8T6核心板)和同样的开发环境(STM32CubeMX + Keil MDK5),分别生成基于HAL库和标准库的工程,然后用最直接的方式——翻转一个GPIO引脚,看看两者在速度、代码体积上到底有多大差别。这个测试不是为了否定HAL库,而是想搞清楚它的效率瓶颈在哪里,以及在不同场景下,我们该如何做出更明智的选择。
1. 实验环境搭建与工程配置
为了确保对比的公平性,我决定从零开始,用STM32CubeMX为同一块芯片生成两个功能完全相同的工程,唯一的变量就是底层库。我手头有一块常见的“蓝色小药丸”核心板,主控是STM32F103C8T6,外部晶振是8MHz。
首先,打开STM32CubeMX,新建一个工程,选择STM32F103C8Tx系列,然后找到具体的C8T6型号。在Pinout & Configuration界面,我做了最简化的配置:
- 将PC13引脚(核心板上通常连接了一个LED)配置为GPIO_Output模式,并给它起个标签叫
USER_LED。 - 在SYS设置里,将Debug选为Serial Wire,这是为了能用ST-Link进行调试和下载。
- 在RCC设置里,将HSE(高速外部时钟)设置为Crystal/Ceramic Resonator,因为板子上有8MHz的外部晶振。
接下来是关键的时钟树配置。我手动将HSE的输入频率设为8MHz,然后通过PLL倍频,将系统时钟(SYSCLK)设置为72MHz,这是F103系列在常规电压下的最高主频。APB1总线时钟(PCLK1)设为36MHz,APB2总线时钟(PCLK2)设为72MHz。这个配置在两个工程中必须完全一致。
注意:STM32CubeMX在生成标准库工程时,其时钟树配置逻辑与HAL库工程略有不同,需要手动核对
system_stm32f1xx.c文件中的SystemCoreClock全局变量值,确保最终的系统时钟频率一致。
配置完成后,进入Project Manager标签页。这里就是决定库类型的关键所在。
- 我先创建HAL库工程:在“Toolchain / IDE”中选择MDK-ARM V5。在“Code Generator”选项卡中,确保“Generated files”下的“Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral”被勾选,这会让代码结构更清晰。最重要的是,在“Advanced Settings”中,所有外设默认都使用HAL库。我将工程命名为
HAL_GPIO_Toggle并生成代码。 - 接着创建标准库工程:我回到CubeMX的Project Manager,将工程名改为
StdLib_GPIO_Toggle,并换一个输出路径。然后,我需要在软件包管理器中,为这个芯片安装标准外设库(StdPeriph Library)支持包。安装后,在“Advanced Settings”中,将所有外设(尤其是GPIO)的驱动从HAL/LL切换为“Standard Peripheral Library”。再次生成代码。
生成后,用Keil MDK5分别打开两个工程。我首先检查了魔术棒(Options for Target)中的配置,确保两个工程的优化等级一致。为了反映初始开发状态,我将优化等级都设置为-O0(不优化),以便更清晰地观察原始代码效率。后续我也会测试-O2优化下的表现。


1万+

被折叠的 条评论
为什么被折叠?



