USART — 串口轮询收发与 printf 重定向(HAL 库)
固件库: PY32F0xx_Firmware V1.5.0
芯片: PY32F030
源文件:PUYA/PY32F0xx_Firmware_V1.5.0/Projects/PY32F030-STK/Example/USART/USART_HyperTerminal_Polling/Src/main.c
串口重定向:Drivers/BSP/PY32F030xx_Start_Kit/py32f030xx_Start_Kit.c(_write/__io_putchar)
功能简介
USART(通用同步异步收发器)即常说的“串口”,是 MCU 与电脑/模块通信、打印调试信息最常用的通道。本示例做两件事:
- 轮询收发:串口先发送欢迎语,再用
HAL_UART_Receive阻塞等待接收 12 字节,收到后原样回显,最后发结束语、点亮 LED。 - printf 重定向(本库特色):BSP 里已实现
_write/__io_putchar,把 C 库printf重定向到USART2,于是在 ADC 等示例里能直接printf("adc:%u\r\n", val)打印。
任务要求的 “UART_Printf(printf 重定向)”在 PUYA 固件里不是独立示例,而是由
BSP_USART_Config()+_write统一提供。下面先讲官方轮询示例,再专门讲 printf 重定向怎么用。
硬件准备
- USB 转串口模块(CH340 / CP2102 等)
- 接线:开发板 PA2(TX) → 模块 RX,PA3(RX) → 模块 TX,共地
- 电脑端串口助手(SSCOM / XCOM / PuTTY),波特率 115200-8-N-1
完整代码(官方轮询示例)
|
|
printf 重定向(重点)
py32f030xx_Start_Kit.c 中已实现如下重定向,使得任意示例调用 DEBUG_USART_Config() 后即可使用 printf:
|
|
使用步骤
-
在
main()里调用DEBUG_USART_Config();(它内部配置 PA2/PA3 为 USART2、115200-8-N-1 并使能时钟)。 -
工程需勾选 Use MicroLIB(Keil)或链接
libc(GCC/iar),否则_write不生效。 -
之后即可:
1printf("系统启动 ok,温度=%d℃\r\n", temp);注意:重定向版是阻塞发送,仅适合调试打印;高吞吐场景请用
HAL_UART_Transmit_DMA或中断。
代码分段讲解
- 波特率与时钟:USART2 挂在 APB1,时钟来自 HSI/PLL;波特率 115200 需系统时钟足够且分频匹配,否则乱码。
- 轮询发送
HAL_UART_Transmit:内部等TXE标志直到整帧发完或超时,简单但占用 CPU。 - 轮询接收
HAL_UART_Receive:阻塞直到收满指定长度或超时;若串口助手发的字节数不足,会一直等(超时 5000ms 后报错)。 - 重定向原理:C 库的
printf→fputc/_write→__io_putchar→ 写 USART 的TDR,从而形成“打印即串口输出”。
实验现象
- 串口助手收到欢迎语,提示输入 12 个字符;
- 输入 12 个字符后,开发板原样回显,再发“Example Finished”,绿灯常亮。
常见问题
-
串口助手全是乱码?
- 波特率必须与代码一致(115200);系统时钟(HSI/PLL)设置要匹配库里
DEBUG_USART的时钟来源。 - 确认
printf工程勾选了 MicroLIB / 正确链接 libc。
- 波特率必须与代码一致(115200);系统时钟(HSI/PLL)设置要匹配库里
-
printf 没输出?
- 忘记调用
DEBUG_USART_Config();或引脚不是 PA2/PA3(被改过需同步改 BSP)。 - 确认
HAL_UART_MODULE_ENABLED宏已开(否则printf重定向分支被编译掉)。
- 忘记调用
-
HAL_UART_Receive 卡住?
- 它要收满 12 字节才返回;串口助手发的字符数不够或没勾选“发送新行”都会超时。教学建议先固定长度,或用中断/不定长(见
USART_HyperTerminal_IT)。
- 它要收满 12 字节才返回;串口助手发的字符数不够或没勾选“发送新行”都会超时。教学建议先固定长度,或用中断/不定长(见
-
TX/RX 接反?
- 必须交叉:板 TX → 模块 RX,板 RX → 模块 TX,并共地。
小结
- 串口配置三要素:波特率、数据格式(8-N-1)、时钟来源。
- 轮询收发最简单但阻塞 CPU;正式项目用中断/DMA。
- 通过
_write/__io_putchar重定向printf,是最高效的调试打印手段。
拓展应用
- 用
printf打印变量/状态,做在线调试,替代单步。 - 升级为
HAL_UART_Transmit_IT/DMA做高吞吐日志或命令解析。 - 接收中断 + 环形缓冲实现“串口命令行”(解析
AT指令等)。 - 双 USART:一个接调试、一个接 WiFi/BLE 模块。