USART — printf 重定向到串口
难度: ⭐(入门必学)
固件库: AT32F403A_407_Firmware_Library V2.2.2
源文件:project/at_start_f403a/examples/usart/printf/src/main.c
这个实验是干嘛的?
做嵌入式开发,最头疼的就是"程序跑起来了,但不知道里面发生了什么"。
在电脑上编程,你可以用 print() 打印变量值来调试。MCU 没有屏幕怎么办?
答案是:用串口把 printf 的输出发到电脑上。
这个实验教你把 C 语言的 printf 函数"重定向"到 USART 串口。之后你就可以在代码任意位置写 printf("温度=%d", temp),电脑串口助手就能看到输出。
这是嵌入式开发最常用、最实用的调试手段,没有之一。
硬件准备
你需要一个 USB 转串口模块(几块钱一个):
| 模块类型 | 价格 | 说明 |
|---|---|---|
| CH340 | ~3 块 | 最便宜,够用 |
| CP2102 | ~5 块 | 稳定 |
| FT232 | ~10 块 | 贵但好用 |
接线方式(3 根线):
|
|
注意:TX 接 RX,RX 接 TX,要交叉!GND 必须共地。
串口助手软件
电脑端需要一个串口助手来查看输出:
| 软件 | 平台 | 推荐度 |
|---|---|---|
| SSCOM | Windows | ⭐⭐⭐ 简单好用 |
| XCOM | Windows | ⭐⭐⭐ 功能全 |
| MobaXterm | Windows | ⭐⭐⭐ 自带串口 |
| minicom | Linux | ⭐⭐ |
打开串口助手,选择正确的 COM 口(设备管理器里看),设置:
- 波特率:115200
- 数据位:8
- 停止位:1
- 校验位:None
完整代码
|
|
代码逐行讲解
1. 头文件
|
|
2. 全局变量
|
|
__IO是volatile的宏定义,表示这个变量可能被意外修改(比如中断里),编译器不要做优化- 如果不加
__IO,编译器可能把time_cnt++优化掉,你就看不到计数器变化了
3. 串口初始化
|
|
这行代码做了两件事:
- 配置 USART1:设置波特率 115200、8 数据位、无校验、1 停止位
- 重定向 printf:把
printf的输出接到 USART1 的发送引脚
波特率 115200 意味着每秒可以传输约 11520 个字节(每个字节 10 bit),足够打印调试信息了。
4. printf 输出
|
|
%u— 无符号整数格式\r\n— 回车换行(串口助手需要这个才能正确显示)time_cnt++— 先打印值,再自增
5. 延时
|
|
如果不加延时,printf 会以 MCU 的速度疯狂输出,串口助手会收到一大堆数据。
printf 重定向的原理(进阶)
uart_print_init() 内部做了什么?其实很简单:
在 C 标准库里,printf 最终会调用一个叫 fputc 的函数来输出每个字符。我们只需要重写这个函数,让它把字符发到串口:
|
|
这就是"重定向"的全部秘密:替换 fputc,把输出目标从屏幕改成串口。
常用 printf 格式
|
|
实验现象
- 编译、下载程序
- 打开串口助手,选择正确的 COM 口,波特率 115200
- 应该看到:
|
|
每秒打印一行,计数器递增。
常见问题
Q: 串口助手收不到数据?
- 检查 COM 口是否选对(设备管理器里看)
- 波特率是否 115200
- TX/RX 是否交叉连接
- GND 是否共地
- 程序是否下载成功
Q: 收到乱码?
- 波特率不匹配!代码里是 115200,串口助手也要设 115200
- 如果时钟配置不对,实际波特率会偏移,也会乱码
Q: 只能用 USART1 吗?
uart_print_init()默认用 USART1- 如果想用其他串口(如 USART2),需要自己修改
fputc函数
小结
| 概念 | 说明 |
|---|---|
| USART | 通用同步异步收发器,最常用的串行通信接口 |
| 波特率 | 每秒传输的 bit 数,双方必须一致 |
| printf 重定向 | 替换 fputc,让 printf 输出到串口 |
\r\n |
回车换行,串口助手显示必需 |
学了串口能做什么?
串口是嵌入式开发的"万能接口"——调试、通信、联网都靠它:
调试与监控
| 用途 | 说明 |
|---|---|
| 变量监控 | printf("温度=%d\n", temp) 实时查看传感器数据 |
| 状态打印 | 程序跑到哪一步了、有没有进中断、错误码是什么 |
| 性能测量 | 打印代码执行时间,找出性能瓶颈 |
| 日志系统 | 带时间戳的运行日志,出问题后可以回溯 |
通信与控制
| 项目 | 原理 | 难度 |
|---|---|---|
| 串口控制 LED | 电脑发指令控制板子上的灯(“on”/“off”) | ⭐ |
| 上位机通信 | MCU 通过串口把数据发到电脑 Python/C# 程序 | ⭐⭐ |
| 蓝牙透传 | 接 HC-05 蓝牙模块,手机就能控制 MCU | ⭐⭐ |
| WiFi 联网 | 接 ESP8266 模块,MCU 通过串口发 AT 指令联网 | ⭐⭐⭐ |
| GPS 定位 | 接 GPS 模块,解析 NMEA 协议获取经纬度 | ⭐⭐⭐ |
| RS485 总线 | 多设备联网通信(工业 Modbus 协议) | ⭐⭐⭐ |
| CAN 转串口 | 汽车/工业设备数据采集 | ⭐⭐⭐ |
实际应用场景
- 智能家居:MCU + ESP8266 + 串口 → 手机远程控制家电
- 工业采集:MCU + RS485 + 串口 → 采集温湿度传感器数据上传
- 无人机:MCU + GPS + 串口 → 获取位置信息
- 调试一切:无论做什么项目,串口 printf 都是你的"眼睛"
核心思路:串口就是 MCU 的"嘴巴"和"耳朵"。能说(printf 发数据)能听(接收指令),就能和电脑、手机、其他设备对话。
下一步:学会了串口打印,接下来可以学 ADC 采样,用 printf 把 ADC 采样值打印出来。