这两种printf()函数重定向方法,太实用了
内容提要
本文介绍了在STM32项目中植入printf()函数的两种策略。第一种策略是使用MicroLIB库,需要重定向fputc()函数。第二种策略是使用半主机模式,取消ARM的半主机工作模式。在不使用MicroLIB的前提下,仍能使用printf()函数将调试信息打印到USART1上。
延伸解读
MicroLIB 的取舍:代码体积与功能完整性的权衡
文章指出 MicroLIB 是缺省 C 库的备选库,经过高度优化以减小代码体积,但功能较少,不符合 ISO C 标准,且部分函数如 memcpy() 运行速度较慢。这意味着在资源受限的嵌入式项目中,选择 MicroLIB 可以节省存储空间,但可能牺牲标准兼容性和部分性能。开发者需根据项目对代码大小和功能完整性的实际需求来决定是否启用。
重定向 fputc() 是使用 printf() 的关键步骤
无论采用哪种策略,文章都强调需要重定向 fputc() 函数,将字符输出到 USART1。在 MicroLIB 方案中,printf() 依赖 fputc() 进行底层输出;而在非 MicroLIB 方案中,同样需要自定义 fputc() 并配合取消半主机模式的代码。这说明 printf() 本身并不直接操作硬件,必须通过重定向底层输出函数才能将调试信息发送到指定串口。
半主机模式:调试便利与独立运行的冲突
半主机模式允许 ARM 应用程序通过调试主机进行输入输出,例如使用主机的显示器和键盘,而无需在目标板上配备这些外设。但文章指出,一般 ARM 应用程序并不需要半主机操作,因此需要取消该模式,以避免链接 MicroLIB 的半主机相关函数。这提醒开发者,在最终产品中应确保程序不依赖调试主机,才能独立运行。
Q&A
STM32中如何通过MicroLIB库实现printf()重定向到USART1?
在KEIL-MDK中勾选Use MicroLib选项,然后重定向fputc()函数,将其中的输出改为通过USART1发送,例如使用USART_SendChar(USART1, (uint8_t)ch)。
MicroLib和标准C库有什么区别?
MicroLib是缺省C库的备选库,高度优化以减小代码大小,但不符合ISO C库标准,不支持某些ISO特性,功能较少,部分函数运行速度较慢,且不支持操作系统函数、宽字符等。
不使用MicroLIB时,如何让printf()输出到USART1?
需要取消ARM的半主机工作模式,并添加相关代码,如定义__FILE结构、FILE __stdout、_sys_exit函数以及重定向fputc()函数,将字符通过USART1发送。
什么是半主机模式?
半主机模式是ARM的一种机制,允许ARM应用程序通过调试器将输入/输出请求传送到主机,例如使用主机的显示器和键盘,而不需要在ARM系统上配备这些外设。
重定向fputc()函数时需要注意什么?
需要包含头文件stdio.h,否则FILE类型未定义。在MicroLib方式下,重定向fputc()后即可使用printf();在非MicroLib方式下,还需取消半主机模式并添加相应代码。
为什么勾选Use MicroLib后直接使用printf()无法输出到串口?
因为MicroLib中的printf()依赖fputc()函数进行输出,默认fputc()可能将字符输出到其他位置,需要重定向fputc()才能将调试信息打印到USART1。