在STM32上实现printf
函数的串口重定向
无论是在MDK(Keil)还是GCC编译器环境中,通过重写底层字符输出函数,使得标准库中的printf
系列函数可以通过UART串口发送数据到PC端进行查看和分析。
核心思想
- 重写或实现底层字符输出函数,使
printf
函数能够通过UART发送数据。 - 针对不同的编译器环境,采取不同的实现方式。
MDK(Keil)环境下
- 实现
fputc()
或__io_putchar()
函数: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()
。
GCC环境下
- 实现
_write()
函数来捕捉write()
调用:int _write(int fd, char *ptr, int len) { HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY); return len; }
兼容性处理
为提高代码复用性和可维护性,可以使用预处理器宏定义来统一代码风格,避免重复编写两个版本的重定向函数:
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
#ifdef __GNUC__
int _write(int fd, char *ptr, int len) {
HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);
return len;
}
#endif
切换编译器即可自动适配对应函数。
支持浮点数打印
- 如果需要支持浮点数格式化:你需要在Makefile中添加特定的链接选项来确保浮点数的支持。这是因为默认情况下,为了节省空间,某些嵌入式C库可能会禁用浮点数支持。要启用它,你需要在Makefile中添加以下内容:
这些选项的作用是:LDFLAGS += -lc -lrdimon -u _printf_float
-lc
:链接标准C库。-lrdimon
:链接一个提供I/O支持的库,这对于一些运行时环境是必要的。-u _printf_float
:强制链接器包含浮点数处理相关的符号,使得printf
能够处理浮点数格式化字符串。