RX玩家在玩 STM32、图传模块、视频采集设备时,最先被问住的往往不是算法,而是串口接线。明明代码能编过,波特率也选对了,可就是收不到数据。排查到最后才发现,TX 接了 TX,RX 接了 RX,同名相连,数据自然进不来。更麻烦的是,不同板子、不同模块上的丝印写法还不统一,有的标“RXD/TXD”,有的只标“RX/TX”,到底哪根接哪根,很容易把人绕晕。
这篇文章主要写给两类人。一类是刚接触 STM32F103、USB 转串口、图传模块、视频采集模块的嵌入式玩家,另一类是想把采集到的视频素材快速整理成项目演示、答辩或汇报材料的开发者。核心是解决三件事:怎么准确识别 RX 和 TX,STM32F103 的 PA9/PA10 哪个是 TX 哪个是 RX,以及串口通信链路跑通之后,怎么把图传和摄像头采集到的素材快速剪辑成可交付的视频。
先说结论:串口调试不要一上来就追求复杂功能,先把“发送端 TX 接接收端 RX”这条规则刻进脑子里,再按“短接回环测试、PC 和模块通信、模块和外设通信、视频采集与剪辑”这个顺序逐步推进。下面按实际落地顺序拆开讲。
1. 为什么 RX 玩家总是被 TX/RX 搞懵
UART 串口通信里,TX 是发送端,RX 是接收端。两个设备通信时,A 设备的 TX 必须接 B 设备的 RX,B 设备的 TX 再接 A 设备的 RX。也就是说,发送和接收要交叉连接。如果 A 的 TX 接了 B 的 TX,两个设备都在发送,谁也没办法接收,自然收不到任何数据。
这个规则说起来简单,实际操作时却经常出问题。原因是不同模块的丝印逻辑不一样。
有些模块上的“TX”指的是“本模块的发送脚”,所以它必须接对端设备的 RX。有些模块上的“TX”被标注成“你应该往这里发送”,那么它实际要接对端设备的 TX。这两种标注逻辑完全不同,只看丝印不看原理图,很容易判断错。尤其是买的 USB 转 TTL 模块、图传模块、GPS 模块、传感器模块来自不同厂家,标注风格五花八门,踩坑概率非常高。
我自己的习惯是:拿到一块新模块,先不急着连线,先做三件事。
第一,找模块的数据手册或原理图,看它上面写的 RXD 和 TXD 到底是“模块自己的接收脚/发送脚”,还是“需要你从外部输入的接收/发送信号”。第二,看板子背面有没有印网络名,比如 PA9、PA10、UART1_TX、UART1_RX。第三,如果手册和原理图都没有,就用回环测试法判断,把疑似的 TX 和 RX 短接,在串口助手发数据,能收到说明这组引脚本身是通的。
下面把三种判断方法整理成一个表。
| 方法 | 操作 | 判断标准 |
|---|---|---|
| 查原理图和数据手册 | 找到串口部分引脚定义 | 手册标注的 TX/RX 通常指芯片自身发送/接收 |
| 看丝印和板载说明 | 观察 TX、RX、RXD、TXD 旁的小字 | 确认是否标注了对应 MCU 引脚号 |
| 回环测试 | 将模块的两个引脚短接,用串口工具自发自收 | 能收到自己发的数据,说明这对引脚可通 |
回环测试只能验证引脚本身通不通,不能直接确定哪根是 TX 哪根是 RX。要最终确认极性,还是得靠原理图和实测电平。
2. STM32F103 的 PA9/PA10 到底是哪根线
很多 STM32F103 入门板上,USART1 对应的引脚就是 PA9 和 PA10。默认复用功能下,PA9 是 USART1_TX,PA10 是 USART1_RX。也就是说,PA9 发送数据,PA10 接收数据。
这里要强调一个前提:这是默认复用功能,不等于所有板子都一定这样。如果你的开发板把 PA9/PA10 做了其他用途,或者通过跳线、拨码开关切换到了别的外设,那就要以板子原理图为准。也有一些板子会把串口引脚重映射到 PB6/PB7,或通过板载调试器直接复用 USB 口,不一定会引出 PA9/PA10。
所以正确的确认顺序是:
- 查芯片型号,确认具体是 STM32F103 的哪个型号,例如 STM32F103C8T6 还是 STM32F103ZET6。
- 查开发板原理图,找到串口部分,看 PA9/PA10 接到哪里。
- 看数据手册中 USART1 的引脚复用表,确认 GPIO 配置成 Alternate Function 后对应什么功能。
- 再用代码实际验证,比如让串口循环发送一个固定字符串。
PA9 和 PA10 的 GPIO 配置不能想当然。PA9 作为 USART1_TX,通常要配置成复用推挽输出,PA10 作为 USART1_RX,要配置成复用开漏输入或浮空输入。下面给一段基于 HAL 库的初始化片段,只展示关键配置。
/* USART1 GPIO Configuration */ GPIO_InitStruct.Pin = GPIO_PIN_9; /* PA9 作为 TX */ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; /* PA10 作为 RX */ GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT; /* 复用输入,通常为浮空或带上拉 */ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);注意,实际工程里还需要配置 USART1 的波特率、数据位、停止位、校验位和中断或 DMA。这里只列出和 GPIO 引脚相关的部分,方便排查接线问题时对照。标准库的配置方式会有所不同,但只要抓住“TX 配成复用输出,RX 配成复用输入”这个核心思路即可。
如果手头没有原理图,又想快速验证 PA9/PA10 哪根是 TX,可以用一个笨办法:写一段代码,让疑似 TX 的引脚输出高低电平循环跳变,然后用万用表测该引脚电压。能看到电压在 0V 和 3.3V 之间跳变,说明这个引脚大概率被配置成了输出模式,可以作为 TX 的初步判断。但最靠谱的方法还是查手册和原理图,不要只靠猜。
3. 连接 STM32 与 USB 转串口模块时,接线逻辑要统一
STM32 和 USB 转串口模块之间的接线规则是:STM32 的 TX 接模块的 RXD,STM32 的 RX 接模块的 TXD。这个规则和“发送接接收、接收接发送”完全一致。
具体到 PA9/PA10 上,就是:
| STM32F103 引脚 | 功能 | 接 USB 转 TTL 模块的引脚 |
|---|---|---|
| PA9 | USART1_TX | RXD |
| PA10 | USART1_RX | TXD |
| GND | 地 | GND |
很多新手会把 STM32 的 PA9 接模块的 TXD,觉得“都是 TX,名字一样应该好配对”。结果当然是收不到数据。记住一句话:不要按名字直接对,要按数据流方向对。数据从 MCU 的 TX 发出,必须流入接收端模块的 RX。
另外,地线必须共地。两边不共地,即使信号线接对了,也可能出现电平参考不一致,导致乱码或完全无数据。用杜邦线连接时,优先把 GND 接好,再接 TX 和 RX。
电压匹配也需要留意。STM32F103 的 IO 电平是 3.3V,很多 USB 转 TTL 模块也是 3.3V 电平,可以直接连。但有些老式模块输出 5V 电平,直接接到 STM32 引脚上可能会有风险。如果你不确定模块电平,先看模块标识或说明书。稳妥做法是选择支持 3.3V TTL 电平的模块,或者用带电平转换的板子。电平不匹配时,常见表现是模块能收到数据,但数据是乱码,或者 MCU 引脚发热、异常复位。
4. 从回环测试到图传模块控制,先跑通一条最小链路
我建议第一次调试不要直接接图传模块,而是分三步走,每一步都能明确知道自己是否成功。
第一步,短接 USB 转串口模块自身的 TX 和 RX。打开串口助手,选对串口和波特率,发送一帧数据,比如“HELLO”。如果模块和驱动正常,发送窗口会收到同样的内容。这一步通过了,说明 PC 端的串口助手、驱动、线缆和模块基本没问题。
第二步,断开短接,把 STM32 和 USB 转串口模块连接起来,烧录一个最简单的循环发送程序,让 STM32 每隔一秒钟发送一个字符串,比如“uart test\r\n”。串口助手里能看到内容,说明 STM32 的串口发送链路通了。再写一个接收程序,在串口助手里发送字符,让 STM32 收到后原样返回,能返回说明接收链路也通了。
第三步,才接入图传模块或视频采集设备。图传模块和视频采集板通常通过串口接收控制指令,比如切换信道、设置波特率、查询版本、调整视频格式。调试之前,先找到这些指令的格式,很多模块采用的是 AT 指令或自定义十六进制帧。不要蒙着头试,先发最简单的查询指令,看模块有没有返回。例如很多模块支持“AT\r\n”返回“OK”,或者“AT+VERSION”返回版本号。
下面是一段最简单的 STM32 循环发送代码逻辑:
while (1) { HAL_UART_Transmit(&huart1, (uint8_t *)"uart test\r\n", 12, 1000); HAL_Delay(1000); }这里只用于发送链路验证,所以不需要复杂逻辑。如果这段代码能让串口助手收到完整、不乱码的字符串,就可以继续做接收和指令控制。
在接入图传模块前,还要检查模块的串口参数。不同模块默认波特率不同,常见的有 9600、57600、115200。不要觉得 115200 是万能默认值,必须查模块手册。串口参数不匹配时,最常见现象是模块有反应但返回乱码,或者完全没反应。收到乱码时,优先检查波特率、数据位、停止位、校验位,然后再检查电平匹配和地线。
5. 视频素材来了之后,怎么快速剪成可演示的成品
串口链路通了之后,就能通过指令控制图传模块或视频采集设备。此时会面临一个新问题:采集到的视频往往很长,格式不统一,直接打开很卡,或者剪辑软件不认。如果只是想快速整理演示视频,用 FFmpeg 比打开大型剪辑软件更省事。
先确认视频信息。命令行输入:
ffprobe input.mp4输出里会显示编码格式、分辨率、帧率、时长、码率。看到 H264 编码、AAC 音频、分辨率正常,就可以直接处理。如果视频是 MJPEG 或者裸 H264 流,很多播放器不一定能直接打开,先转成通用 MP4 再说。
常用转码命令:
ffmpeg -i input.avi -c:v libx264 -preset veryfast -crf 23 -c:a aac output.mp4参数含义:
| 参数 | 作用 |
|---|---|
| -c:v libx264 | 视频编码改成 H264,兼容性最好 |
| -preset veryfast | 编码速度快,画质也能接受 |
| -crf 23 | 画质控制,数字越小画质越高、文件越大 |
| -c:a aac | 音频编码改成 AAC |
如果只需要保存某一段视频,可以用裁剪命令:
ffmpeg -ss 00:01:00 -to 00:01:30 -i input.mp4 -c copy cut.mp4-ss 指定起始时间,-to 指定结束时间。-c copy 表示直接复制编码,不重新编码,所以速度非常快。但这种方式的时间点可能不太精确,因为关键帧对齐问题。如果是要精确到帧,可以去掉 -c copy,改用重编码:
ffmpeg -ss 00:01:00 -to 00:01:30 -i input.mp4 -c:v libx264 -crf 23 cut.mp4多段视频拼接时,先准备一个文件列表。假设有两个片段,文件名分别为 part1.mp4 和 part2.mp4,在文本文件 concat.txt 里写入:
file 'part1.mp4' file 'part2.mp4'然后执行:
ffmpeg -f concat -safe 0 -i concat.txt -c copy merged.mp4注意,用 -c copy 拼接时,每个片段的编码格式、分辨率、帧率必须一致,否则可能拼接失败或出现音画不同步。如果参数不一致,可以统一转码后再拼接,或者直接用重编码命令:
ffmpeg -f concat -safe 0 -i concat.txt -c:v libx264 -crf 23 -c:a aac merged.mp4还有一个常用需求是给视频加字幕。准备一个 UTF-8 编码的 srt 文件,然后执行:
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" -c:v libx264 -crf 23 output.mp4如果只是想快速生成一张封面图,用抽帧命令:
ffmpeg -i input.mp4 -ss 00:00:05 -frames:v 1 cover.jpg这套流程很适合演示素材整理:图传模块采集的视频可能很长,先用 ffprobe 看信息,再用 -c copy 快速裁掉首尾无用画面,如果多个片段参数一致就拼接,最后统一转成 MP4。整个过程不需要打开大型剪辑软件,脚本化之后可以重复执行,效率会高很多。
6. 串口调试和视频处理中常见的故障排查链路
我调整了几次之后,发现这类问题的绝大多数根源不是功能不支持,而是基础设施没打好。下面按现象给出排查顺序。
6.1 串口收不到数据
不要先怀疑代码,先查接线和硬件。
- 确认 TX/RX 有没有接反,发送端 TX 必须接接收端 RX。
- 确认两边 GND 是否共地,不共地几乎必出问题。
- 确认串口号有没有选错,尤其在板载调试器和外接 USB 转串口同时存在时。
- 确认波特率、数据位、停止位、校验位是否一致。
- 确认 STM32 的 GPIO 是否配置成对应复用功能。
- 确认程序有没有真正烧录进去,可以用点灯或打印方式验证主循环在跑。
6.2 串口收到乱码
按以下顺序排查。
| 顺序 | 检查点 | 处理方式 |
|---|---|---|
| 1 | 波特率是否一致 | 重新确认两端串口参数 |
| 2 | 电平是否匹配 | 3.3V 设备不要硬接 5V 信号 |
| 3 | GND 是否稳定 | 换更短更稳定的杜邦线 |
| 4 | 供电是否不足 | 图传模块单独供电,避免大电流拉低电平 |
| 5 | 模块是否损坏 | 用另一块模块交叉验证 |
6.3 视频文件无法播放或剪辑软件打不开
优先检查视频编码。很多采集设备输出的是 H264 裸流或者 MJPEG 格式,扩展名虽然是 .mp4,但实际编码可能不被播放器支持。这时候不要直接在剪辑软件里反复尝试,先用 ffprobe 看编码信息,再转成 H264 + AAC 的 MP4。另一种情况是设备录制出的文件没有完整封装,播放器只认到前几帧,需要重新转码修复。
6.4 图传模块不出图,但串口能通信
串口能通信只是说明控制链路好,图像链路是另一套通道。需要检查:
- 图传模块有没有正常供电,电流是否满足要求。
- 天线是否接好,信道和接收端是否一致。
- 视频制式是 NTSC 还是 PAL,采集端是否切到对应制式。
- 采集卡或接收机是否选对输入通道。
- 视频信号线和控制线是不是用了同一根串口线,方向有没有混接。
这类问题最忌讳只盯一个点。先确认电源,再确认控制指令返回,最后才排查图像通道。
7. 从“能通信”到“能交付”的落地建议
串口通了、视频也能剪了,但这只代表功能验证完成,离真正交付还有一段距离。如果要做成工具化、可重复使用的流程,下面的经验可以参考。
7.1 先跑单条任务,再跑批量
不管是串口指令还是一段视频的剪辑,先跑通一条,再写循环。比如要控制图传模块切换多个信道,先手动发单条信道切换指令,确认模块有正确返回,再写自动循环切换多条信道。剪辑视频也一样,先裁一段 30 秒的素材,确认输出文件能正常播放,再批量处理所有片段。
一上来就搞批量循环,遇到失败时很难判断是逻辑问题、链路问题还是参数问题。
7.2 日志和文件命名要提前规划
串口调试时,不要只盯着串口助手的窗口,要把收到的数据写到文件里,加上时间戳,这样回看时才不会一头雾水。视频处理更要统一命名,避免输出一堆“output(1).mp4”“output(2).mp4”。
比如按日期和用途命名:
20250118_demo_channel1.mp4 20250118_demo_channel2.mp4 20250118_summary.mp4这样后续做多段拼接、归档、查找都方便很多。
7.3 把串口指令和视频处理脚本串起来
到了这个阶段,就可以把整个流程工具化。先通过串口控制采集设备录制一段素材,再用 FFmpeg 裁掉多余部分,最后统一转码并拼接。这个过程可以用一个脚本完成,脚本里留好参数:串口号、波特率、输出目录、剪辑起止时间。
脚本化最直接的好处是,换了输入素材之后不需要手动打开多个软件,重新执行一次就能得到新的交付物。
7.4 接受功能边界,不要硬调参数
有的模块默认只支持 3.3V 电平,硬接 5V 不一定坏,但不稳定。有的图传模块只支持固定信道值,发一个手册范围外的参数返回错误码,这时不要反复试,先看手册。有的 FFmpeg 转码命令在 A 电脑上正常,在 B 电脑上报错,大概率是版本不同或缺少编码器,不要一上来就怀疑素材坏了。
我自己的原则是:如果某个参数连续调几轮都没有改善,先停下来确认输入条件,再继续调。很多问题不是“参数不够”而是“前置条件没满足”。
玩 RX/TX 串口到最后会发现,真正花时间的不是写代码,而是确认接线、参数和输入输出。PA9 是 TX、PA10 是 RX,这是 STM32F103 入门板上很常用的默认配置,但比记住这个更重要的是掌握判断方法。把回环测试、共地接线、串口参数、输出日志这四件事做好,串口链路基本不会再有大坑。视频素材快速处理也不需要多么复杂的剪辑软件,FFmpeg 几条命令就能完成大部分工作。先跑通一条最小链路,再扩展批量流程,这套思路不管是做图传控制、采集设备调试,还是整理项目演示素材,都能稳定往下走。