STM32 printf 串口重定向代码完整解析
·
STM32 printf串口重定向代码完整解析
一、先提取图片完整代码
#include "usart.h"
/* USER CODE BEGIN 0 */
int fputc(int ch, 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 */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}
/* USER CODE END 0 */
int main(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:
// 非阻塞版本,不占用CPU
HAL_UART_Transmit_IT(&huart1, (uint8_t *)&ch, 1);
while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);
七、一句话总结
这段代码是STM32 HAL库的printf串口重定向模板:通过重写标准库底层输出函数fputc,把printf打印内容转发到硬件串口1,实现单片机向电脑串口助手打印调试信息。
更多推荐

所有评论(0)