为在 STM32F411CEU6(基于 Cortex-M4F 内核,带 FPU)上使用 CMake 开启浮点数支持(包括硬件浮点运算和 printf浮点打印),你需要修改项目中的 CMakeLists.txt文件。

📝 配置步骤

  1. 启用硬件浮点单元 (FPU)​​:添加编译选项,告诉编译器使用硬件浮点单元。

  2. 支持 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: 这个选项告诉链接器移除未使用的代码段,有助于在一定程度上减小最终生成的二进制文件大小。由于启用浮点打印可能会增加代码体积,这个选项很有用。

⚠️ 重要注意事项

  1. 串口重定向: 以上配置确保了 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)。

  2. 性能与资源: 由于 STM32F103C8T6 没有硬件 FPU,所有浮点运算(包括 printf中的格式转换)都由软件完成,这会增加 CPU 开销和代码尺寸。如果项目对性能敏感或资源紧张,需谨慎使用浮点数。

  3. 芯片型号差异: 请注意 STM32F103C8T6(Cortex-M3)与 STM32F411CEU6(Cortex-M4F)的区别。​STM32F103C8T6 不需要也不支持 -mfpu-mfloat-abi=hard这类针对硬件 FPU 的编译选项

💡 简单对比:F103 vs F411

特性

STM32F103C8T6 (Cortex-M3)

STM32F411CEU6 (Cortex-M4F)

硬件FPU

不支持

支持

浮点运算

软件模拟,效率低

硬件加速,效率高

关键CMake选项

-u _printf_float

-u _printf_float-mfpu=fpv4-sp-d16-mfloat-abi=hard

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐