📌 你是否遇到这样的情况?

printf("Hello STM32");        // ❌ 没输出!
printf("Hello STM32\r\n");    // ✅ 输出了!

🧠 一、核心原因:printf() 是缓冲输出

在 C 标准库中,printf() 会先把数据写进缓冲区,只有满足条件才真正发送。

常见触发缓冲区刷新的条件:

条件 说明
字符串包含换行符 \n 自动刷新缓冲区,立即发送
手动调用 fflush(stdout) 强制刷新
设置为无缓冲 _IONBF 关闭缓冲,每次立即发送

🧪 二、STM32 默认是“全缓冲(fully buffered)”

STM32 常用的 newlib 标准库默认缓冲策略:

printf("ABC");      // ❌ 只写入缓冲区,没发送
printf("ABC\n");    // ✅ 含换行符,自动刷新,立即发送

因为 \n 触发 newlib 调用 fflush(stdout),进而调用用户实现的 _write() 函数,通过 UART 发送数据。


🛠️ 三、如何解决?

1. 推荐:加换行符 \r\n

printf("Weight: %.2f\r\n", weight);

\r\n 是大部分串口终端的换行标准。

2. 手动刷新缓冲区

printf("Weight: %.2f", weight);
fflush(stdout);  // 强制刷新

3. 关闭缓冲

setvbuf(stdout, NULL, _IONBF, 0);  // 禁用缓冲区,立即输出

⚙️ 四、确保 printf() 正常输出的关键步骤

PlatformIO (GCC + newlib)

  • 必须实现 _write(),例如:
int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, HAL_MAX_DELAY);
    return len;
}
  • platformio.ini 加入支持浮点格式输出的链接选项:
build_flags =
  -Wl,-u,_printf_float

Keil (ARMCC/ARMCLANG + Microlib)

  • 通常实现字符级重定向函数 fputc()
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
  • 不需要实现 _write(),因为 Keil 库默认调用 fputc()

📊 五、行为对比表

编译环境 关键重定向函数 printf 是否输出 说明
PlatformIO + GCC _write() ✅ (实现后) 需要实现 _write()
Keil MDK fputc() ✅ (实现后) 需要实现 fputc()
不实现重定向 无法输出
Logo

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

更多推荐