为STM32F1和F4系列的单片机CMAKE工程打开软硬件浮点加速,解决无法sprintf浮点数的问题
摘要:本文介绍了在STM32F411CEU6(Cortex-M4F)和STM32F103C8T6(Cortex-M3)上配置CMake支持浮点运算的方法。对于F411需添加硬件FPU编译选项(-mfpu=fpv4-sp-d16 -mfloat-abi=hard)和printf浮点支持(-u_printf_float);F103仅需添加-u_printf_float实现软件浮点打印。两者都需要正确实
为在 STM32F411CEU6(基于 Cortex-M4F 内核,带 FPU)上使用 CMake 开启浮点数支持(包括硬件浮点运算和 printf浮点打印),你需要修改项目中的 CMakeLists.txt文件。
📝 配置步骤
-
启用硬件浮点单元 (FPU):添加编译选项,告诉编译器使用硬件浮点单元。
-
支持 printf 输出浮点数:添加链接选项,确保标准库的
printf函数包含对浮点数的支持。
将以下配置添加到你的 CMakeLists.txt文件中(通常在 add_executable之后添加链接选项):
# 启用硬件浮点支持 (针对STM32F4系列)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=fpv4-sp-d16 -mfloat-abi=hard")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=fpv4-sp-d16 -mfloat-abi=hard")
# 确保printf支持浮点数输出
target_link_options(${PROJECT_NAME} PRIVATE -u _printf_float)
🔧 参数说明
-
-mfpu=fpv4-sp-d16: 指定使用 Cortex-M4 的浮点单元(FPv4-SP-D16),这与 STM32F411CEU6 的 FPU 特性匹配。 -
-mfloat-abi=hard: 指示编译器生成硬件浮点指令,并利用硬件 FPU 进行浮点计算,这能显著提升效率。 -
-u _printf_float: 这是一个链接器选项。它强制链接器包含处理printf浮点数格式(如%f)所需的代码。默认情况下,为了节省空间,嵌入式标准库(如 newlib-nano)可能禁用了此功能。
⚠️ 注意
-
串口重定向: 以上配置确保了
printf本身支持浮点数,但你仍需将printf输出重定向到串口等外设。通常需要实现int _write(int fd, char *ptr, int len)或int __io_putchar(int ch)函数,内部调用HAL_UART_Transmit。 -
FPU 已存在: STM32F411CEU6 的芯片头文件中通常已定义
__FPU_PRESENT为 1,硬件上 FPU 默认是存在的,系统初始化代码(如SystemInit())通常会启用它。上述编译选项是让编译器利用它。 -
如果后续遇到
printf输出浮点数时卡住或无法输出,请检查串口重定向函数是否正确实现,以及串口硬件初始化是否正常。
STM32F103C8T6 基于 Cortex-M3 内核,没有硬件浮点单元 (FPU),因此所有浮点运算都通过软件模拟实现,效率相对较低。不过,你仍然可以在 CMake 中启用 printf的浮点数打印功能。
📝 配置步骤
在你的 CMakeLists.txt文件中添加以下配置,通常是在 add_executable之后:
# 确保printf支持浮点数输出
target_link_options(${PROJECT_NAME} PRIVATE -u _printf_float)
# 可选:为了节省代码空间,可以启用垃圾收集 section 以移除未使用的函数
target_link_options(${PROJECT_NAME} PRIVATE -Wl,--gc-sections)
🔧 参数说明
-
-u _printf_float: 这是一个链接器选项。它的作用是强制链接器包含处理printf浮点数格式(如%f)所需的代码。对于 STM32F103C8T6 这类没有硬件 FPU 的芯片,这是启用浮点数打印的关键步骤,因为默认的嵌入式标准库(如 newlib-nano)为了节省空间可能禁用了此功能。 -
-Wl,--gc-sections: 这个选项告诉链接器移除未使用的代码段,有助于在一定程度上减小最终生成的二进制文件大小。由于启用浮点打印可能会增加代码体积,这个选项很有用。
⚠️ 重要注意事项
-
串口重定向: 以上配置确保了
printf函数本身能够处理浮点数格式,但你仍需将printf的输出重定向到串口等外设。这通常需要你实现一个底层输出函数,例如:#include <stdio.h> #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { // 确保这里使用的串口句柄与你硬件上连接的串口一致,例如 huart1, huart2 等 HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; }请根据你的实际硬件连接,修改
HAL_UART_Transmit函数中使用的串口句柄(如huart1,huart2)。 -
性能与资源: 由于 STM32F103C8T6 没有硬件 FPU,所有浮点运算(包括
printf中的格式转换)都由软件完成,这会增加 CPU 开销和代码尺寸。如果项目对性能敏感或资源紧张,需谨慎使用浮点数。 -
芯片型号差异: 请注意 STM32F103C8T6(Cortex-M3)与 STM32F411CEU6(Cortex-M4F)的区别。STM32F103C8T6 不需要也不支持
-mfpu和-mfloat-abi=hard这类针对硬件 FPU 的编译选项。
💡 简单对比:F103 vs F411
|
特性 |
STM32F103C8T6 (Cortex-M3) |
STM32F411CEU6 (Cortex-M4F) |
|---|---|---|
|
硬件FPU |
不支持 |
支持 |
|
浮点运算 |
软件模拟,效率低 |
硬件加速,效率高 |
|
关键CMake选项 |
|
|
更多推荐



所有评论(0)