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发送到电脑串口助手,实现打印调试。

三、逐行拆解代码逻辑

  1. int fputc(int ch, FILE *f)

    • fputc:标准库单字符输出底层接口,printf循环调用它逐个输出字符
    • ch:要输出的单个字符(ASCII码,int类型兼容扩展字符)
    • FILE *f:文件指针,printf默认传入标准输出stdout,这里我们不需要用到,仅占位
  2. HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
    HAL库阻塞式串口发送函数,参数含义:

    • &huart1:串口1句柄(CubeMX生成,对应硬件USART1)
    • (uint8_t *)&ch:取字符ch的地址,强转为字节指针,供函数读取1字节数据
    • 1:本次只发送1个字节
    • 1000:发送超时时间1000ms,超时直接退出
  3. return (ch);
    标准规范:发送成功后返回原字符,兼容标准库逻辑,不能省略。

四、使用前提(必须满足,否则报错)

  1. CubeMX已配置USART1,生成huart1全局句柄,并且正确初始化串口;
  2. 工程需要勾选Use MicroLIB(Keil MDK),否则标准库FILE接口缺失,重定向失效;
  3. 头文件依赖:需要包含<stdio.h>,否则FILEprintf未定义;
  4. 硬件: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等格式化输出,调试更方便。

缺点

  1. HAL_UART_Transmit阻塞发送:串口发送时CPU卡死等待,大量打印会拖慢程序运行;
  2. 只能单向发送,若需要scanf串口接收,还要重写fgetc函数;
  3. 不加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,实现单片机向电脑串口助手打印调试信息。