STM32 printf 串口重定向代码完整解析
STM32 printf串口重定向代码完整解析
一、先提取图片完整代码
#include"usart.h"/* USER CODE BEGIN 0 */intfputc(intch,FILE*f){/* 发送一个字节数据到串口DEBUG_USART */HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,1000);return(ch);}/* USER CODE END 0 */二、核心概念:什么是串口重定向?
1. 标准C库默认行为
C语言标准函数printf()、putchar()底层依赖标准库函数fputc,默认是向**电脑屏幕(标准输出stdout)**输出字符。
但单片机没有屏幕,直接调用printf会报错、无任何输出。
2. 重定向本质
重写fputc函数,把原本输出到屏幕的字符,拦截下来,改用串口(USART1)发送出去。
之后你在代码里直接写printf("hello\r\n");,字符串就会通过串口1发送到电脑串口助手,实现打印调试。
三、逐行拆解代码逻辑
int fputc(int ch, FILE *f)fputc:标准库单字符输出底层接口,printf循环调用它逐个输出字符ch:要输出的单个字符(ASCII码,int类型兼容扩展字符)FILE *f:文件指针,printf默认传入标准输出stdout,这里我们不需要用到,仅占位
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
HAL库阻塞式串口发送函数,参数含义:&huart1:串口1句柄(CubeMX生成,对应硬件USART1)(uint8_t *)&ch:取字符ch的地址,强转为字节指针,供函数读取1字节数据1:本次只发送1个字节1000:发送超时时间1000ms,超时直接退出
return (ch);
标准规范:发送成功后返回原字符,兼容标准库逻辑,不能省略。
四、使用前提(必须满足,否则报错)
- CubeMX已配置USART1,生成
huart1全局句柄,并且正确初始化串口; - 工程需要勾选Use MicroLIB(Keil MDK),否则标准库FILE接口缺失,重定向失效;
- 头文件依赖:需要包含
<stdio.h>,否则FILE、printf未定义; - 硬件:USART1 TX/RX引脚接USB转串口模块,连接电脑串口助手。
五、完整使用示例
#include"stdio.h"// 必须加,printf、FILE定义在这里#include"usart.h"/* USER CODE BEGIN 0 */intfputc(intch,FILE*f){HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,1000);returnch;}/* USER CODE END 0 */intmain(void){HAL_Init();SystemClock_Config();MX_USART1_UART_Init();while(1){// 直接使用printf,自动走串口1输出printf("当前循环运行中\r\n");HAL_Delay(1000);}}六、优缺点 & 补充注意
优点
- 不用手动调用
HAL_UART_Transmit拼接字符串,直接用熟悉的printf格式化打印; - 支持
%d %s %f等格式化输出,调试更方便。
缺点
HAL_UART_Transmit是阻塞发送:串口发送时CPU卡死等待,大量打印会拖慢程序运行;- 只能单向发送,若需要
scanf串口接收,还要重写fgetc函数; - 不加MicroLIB会出现内存溢出、程序卡死。
优化拓展(非阻塞版本)
如果担心阻塞,可以改用中断/DMA发送,替换HAL_UART_Transmit:
// 非阻塞版本,不占用CPUHAL_UART_Transmit_IT(&huart1,(uint8_t*)&ch,1);while(HAL_UART_GetState(&huart1)==HAL_UART_STATE_BUSY_TX);七、一句话总结
这段代码是STM32 HAL库的printf串口重定向模板:通过重写标准库底层输出函数fputc,把printf打印内容转发到硬件串口1,实现单片机向电脑串口助手打印调试信息。
