STM32printf重定向到串口含armcc和gcc两种方案
STM32串口重定向:MDK与GCC环境下需重写的函数差异
在嵌入式开发中,尤其是使用 STM32系列微控制器 的项目中,调试信息的输出是不可或缺的一部分。为了方便调试,开发者通常会选择将 printf
等标准输出函数通过 UART 串口发送到 PC 端进行查看和分析。
然而,在不同的编译器环境中(如 MDK(Keil) 和 GCC),实现标准输出函数重定向的方式存在差异。本文将详细介绍如何在这两种环境下完成串口重定向,并指出它们之间需要重写的函数区别。
✅ 一、重定向的基本原理
无论是在 MDK 还是 GCC 编译环境下,串口重定向的核心思想都是通过重写底层的字符输出函数,使得标准库中的 printf
系列函数能够通过串口发送数据。
标准 C 库中的 printf
函数最终会调用底层的字符输出函数,而不同编译器对这些底层函数的命名和接口定义略有不同。因此,开发者需要根据所使用的编译器环境,选择并实现对应的函数。
🛠️ 二、在不同编译器下的实现方法
1. Keil MDK 环境(ARMCC / AC6)
在 Keil MDK 中,标准输入输出函数依赖于 ARM 自带的 C 标准库。要重定向 printf
,需要重写 _sys_write()
或者更常用的 fputc()
函数。
// Keil MDK 下的标准重定向函数
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}
或者使用传统的:
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}
⚠️ 注意:如果使用的是 ARM Compiler 6(即基于 LLVM 的编译器),建议优先使用
__io_putchar()
。
2. GCC 编译器环境(适用于 STM32CubeIDE、Makefile + arm-none-eabi-gcc)
在 GCC 环境下,标准输出函数依赖于新lib库(newlib-nano)。此时需要实现 _write()
函数来捕捉 write()
调用,从而完成串口输出。
// GCC 下的重定向函数
int _write(int fd, char *ptr, int len)
{HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);return len;
}
该函数接收文件描述符 fd
(通常我们忽略它)、指向字符串的指针 ptr
,以及长度 len
,然后将整个缓冲区通过串口发送出去。
🔁 三、统一方式:使用宏定义简化适配
为了兼容不同编译器,可以使用预处理器宏定义统一代码风格,避免重复编写两个版本。
// 通用重定向头文件或代码段
#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endifPUTCHAR_PROTOTYPE
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}// GCC 特定部分
#ifdef __GNUC__
int _write(int fd, char *ptr, int len)
{HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);return len;
}
#endif
这样处理后,只需切换编译器即可自动适配对应函数,提高代码复用性和可维护性。
💡 四、注意事项
- 串口句柄:确保
&huart1
已被正确初始化并在全局作用域中可用。 - 阻塞问题:
HAL_UART_Transmit()
是阻塞函数,若用于中断上下文或实时性强的场景,请改用非阻塞方式(如DMA或中断发送)。 - 性能优化:频繁调用
printf()
可能影响性能,建议仅用于调试阶段。 - 重定向范围:除了输出,还可以重定向输入(如
scanf
),但需重写对应的_read()
或fgetc()
。
📌 五、总结
编译器 | 需重写的函数 | 函数原型 |
---|---|---|
MDK(Keil) | fputc / __io_putchar | int fputc(int ch, FILE *f) / int __io_putchar(int ch) |
GCC | _write | int _write(int fd, char *ptr, int len) |
通过以上方式,我们可以灵活地在 STM32 开发中实现串口重定向,为调试提供极大的便利。
📚 参考资料
- CSDN 博客 - 原文链接
- ST官方 HAL 库文档
- GCC 新版标准库(newlib-nano)说明文档
📢 如您发现任何错误或有改进建议,欢迎留言交流!
版权声明:本文为原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请注明出处并保留原文链接。