数据传输实验演示
227.4.1 数据传输实验演示
本节的重点是搭建硬件、理解数据链路并验证自定义协议,视频没有现场编写业务源码。串口转 CAN 和 CAN 接收解析代码会从后续课程开始逐步编写,因此这里不把配套工程中的最终代码提前贴入,以免打乱学习顺序。
一、数据传输实验演示
1.1 整体框架
1.1.1 数据从电脑到仪表盘的完整路径
本实验使用两块 STM32F103 开发板,模拟“数据采集/转发节点”和“仪表显示节点”:
| 顺序 | 设备或接口 | 本实验中的作用 |
|---|---|---|
| 1 | 电脑上的串口助手 | 按十六进制发送一条 8 字节测试指令 |
| 2 | USB 转 TTL 模块 | 把电脑 USB 数据转换成 MCU 串口电平 |
| 3 | STM32F103C8T6 的 USART2 | 接收测试指令 |
| 4 | C8T6 与 CAN 收发器 | C8T6 把 8 字节数据放进 CAN 数据帧;收发器把 MCU 侧逻辑电平转换成 CANH/CANL 差分信号 |
| 5 | CANH、CANL 总线 | 把 CAN 帧传到另一块开发板 |
| 6 | STM32F103ZET6 与 CAN 收发器 | 收取 CAN 帧并解析数据 |
| 7 | ZET6 上的 LVGL 仪表盘 | 更新指针、报警图标、日期和时间 |
可以把这条路径记成:
电脑 → USB 转 TTL → C8T6 USART2 → C8T6 CAN → CANH/CANL → ZET6 CAN → LVGL 仪表盘。
C8T6 的 USART1 另接一只 USB 转 TTL 模块,只负责向电脑打印调试日志,不参与测试指令的输入。复位 C8T6 后,日志串口会输出 C8T6 running,可据此判断两个串口中哪一个是日志口、哪一个是数据口。
1.1.2 ZET6 侧硬件连接
| 外设 | 外设引脚 | ZET6 开发板连接 | 信号方向与含义 |
|---|---|---|---|
| LCD | 按前面课程已有接线 | ZET6 对应 LCD 接口 | 显示 LVGL 仪表盘 |
| CAN 收发器 | VCC | 开发板 5V | 按视频所用模块的供电方式给收发器模块供电 |
| CAN 收发器 | GND | 开发板 GND | 电源地与信号参考地 |
| CAN 收发器 | TX/TXD | PA12(CAN_TX) | MCU 的 CAN 发送信号进入收发器 |
| CAN 收发器 | RX/RXD | PA11(CAN_RX) | 收发器把总线数据送入 MCU |
ZET6 开发板在视频中通过数据线供电。PA11、PA12 是 MCU 的 CAN 控制器信号脚,不能直接接到另一块 MCU;两端必须各经过 CAN 收发器,再由收发器之间的 CANH、CANL 相连。
1.1.3 C8T6 侧硬件连接
CAN 收发器:
| CAN 收发器引脚 | C8T6 连接 | 作用 |
|---|---|---|
VCC | 开发板 5V | 按视频所用模块给收发器模块供电 |
GND | 开发板 GND | 共地 |
TX/TXD | PA12(CAN_TX) | MCU 向 CAN 收发器发送逻辑信号 |
RX/RXD | PA11(CAN_RX) | MCU 从 CAN 收发器接收逻辑信号 |
USB 转 TTL 模块 1——USART1 日志口:
| USB 转 TTL 引脚 | C8T6 连接 | 原因 |
|---|---|---|
GND | GND | 两端必须有共同电位参考 |
TX | PA10(USART1_RX) | 发送端接对方接收端 |
RX | PA9(USART1_TX) | 接收端接对方发送端 |
USB 转 TTL 模块 2——USART2 数据口:
| USB 转 TTL 引脚 | C8T6 连接 | 原因 |
|---|---|---|
GND | GND | 两端必须共地 |
TX | PA3(USART2_RX) | 串口助手下发的数据由这里进入 MCU |
RX | PA2(USART2_TX) | 为双向通信预留;本节主要使用电脑到 MCU 的方向 |
串口接线要“交叉连接”,即一端的 TX 接另一端的 RX;CAN 收发器模块标注的 TXD、RXD 则按信号功能连接到 MCU 的 CAN_TX、CAN_RX。两者不要混淆。
1.1.4 CAN 总线侧连接与终端电阻
两只 CAN 收发器之间至少要连接:
CANH对CANH;CANL对CANL;- 实验台上建议同时连接参考地,避免两块板的地电位差过大。
CANH/CANL 是一对差分信号线。接收器判断的是两根线之间的电压差,所以它比单根信号线更能抵抗两线共同受到的干扰。高速 CAN 推荐采用总线型(线型)拓扑,并在物理总线的两个末端各放置一个与线缆阻抗匹配的 120 Ω 终端电阻,以抑制信号反射。
本实验只有两个节点时,两块收发器模块通常分别位于总线两端。若模块自带 120 Ω 电阻或跳帽,应先查看模块丝印/原理图,不能再盲目并联额外终端。断电后用万用表测量 CANH 与 CANL,两个 120 Ω 并联的等效阻值约为:
[ R_{eq}=\frac{120\times120}{120+120}=60\ \Omega ]
实际读数会受板上其他器件和万用表影响,但明显接近 60 Ω 可作为“两端终端都已接入”的快速检查。若约为 120 Ω,通常只有一只终端;若显著小于 60 Ω,要排查是否接了过多终端。
1.1.5 供电与 USB 接口注意事项
- 视频给出的 C8T6 供电方式是:使用开发板数据线供电,或者由 USB 转 TTL 模块的
5V给开发板供电。应选择一种明确、可靠的供电路径。 - 不要在不了解电源电路的情况下,把多个电脑 USB 口的
5V输出直接并接在一起;不同端口之间可能出现反向灌电流。若已经用数据线给板供电,USB 转 TTL 通常只接GND/TX/RX即可。 - “模块以 5 V 供电”不等于“串口信号应使用 5 V 电平”。STM32F103 的 I/O 工作电压和具体引脚耐压要以芯片数据手册、开发板原理图及 USB 转 TTL 模块电平选择为准。实验中优先确认 TTL 模块的逻辑电平档位与目标板兼容。
- 电脑 USB 口不足时可以使用 USB HUB,但连接多个开发板、两个串口模块和屏幕后,应关注 HUB 的供电能力及枚举稳定性。
1.1.6 两个串口助手窗口的设置与识别
视频中使用两个串口助手实例:
| 窗口 | 对应接口 | 发送/显示方式 | 用途 |
|---|---|---|---|
| 数据窗口 | C8T6 USART2 | 发送区选择 HEX | 下发 8 字节二进制协议 |
| 日志窗口 | C8T6 USART1 | 接收区按 ASCII 文本显示 | 查看启动信息和 CAN 发送日志 |
串口参数为 115200 波特率、8 个数据位、无校验、1 个停止位、无流控,常简写为 115200,8N1。视频里的 COM3、COM5 只是授课电脑当时分配的端口号,在另一台电脑上不一定相同。可按以下方法确认:
- 在设备管理器或串口助手中观察插拔前后的端口变化;
- 给两个 USB 转 TTL 模块贴上“USART1 日志”“USART2 数据”标签;
- 复位 C8T6,能看到
C8T6 running的窗口就是 USART1 日志口; - 若乱码,先检查波特率、数据位、校验位和停止位,而不是立刻怀疑 CAN。
1.1.7 C8T6 在本实验中的角色
课程用 C8T6 模拟 VCU。VCU 的规范英文名称是 Vehicle Control Unit(整车控制器),不是“Central Control Unit”。在真实电动汽车中,VCU 一般参与整车状态协调、驾驶意图处理、扭矩仲裁和能量管理,并与 BMS、电机控制器、仪表等多个控制器通信。
本实验中的 C8T6 只是一个教学用数据网关:从串口接收人工构造的数据,再转发到 CAN 总线。它帮助理解“多个 ECU 经 CAN 交换数据”的基本结构,但并不等同于量产 VCU。真实车规控制器还要考虑车规器件、电源保护、EMC、诊断、故障降级和功能安全等问题。
1.2 实验演示
1.2.1 日期与时间校准
1.2.1.1 8 字节应用层协议
本节所有测试报文都固定发送 8 字节:
| 字节位置 | 含义 | 说明 |
|---|---|---|
| Byte0 | 帧头 0xAF | C8T6 只转发首字节为 0xAF 的一组数据 |
| Byte1 | 指令 ID | 决定本帧更新哪一个仪表项目 |
| Byte2~Byte7 | 参数或填充字节 | 具体含义由指令 ID 决定;未使用的位置在演示中填 0xAF |
配套工程可核对出:C8T6 的 USART2 每次按固定长度接收 8 字节,随后用标准 CAN 数据帧、标识符 0x0B4、数据长度 8 字节进行转发;ZET6 只解析标识符为 0x0B4 且 Byte0 为 0xAF 的帧。0x0B4 属于 CAN 帧头中的标识符,不占上表的 8 字节数据区。
这里要区分两层概念:
- 经典 CAN 的数据区上限是 8 字节,所以课程把一条应用消息设计成 8 字节;
0xAF是课程自定义的应用层帧头,不是 CAN 标准规定的固定帧头;- 当前应用协议没有额外的长度字段、序号或应用层校验和,但 CAN 控制器仍会在底层使用 CAN 自身的 CRC 等差错检测机制;
- 串口侧采用“每收到 8 字节就处理一次”的定长分组。如果传输中少一个或多一个字节,后续分组可能错位。量产协议通常还会增加长度、校验、超时与重新同步机制,本节暂不展开实现。
1.2.1.2 指令定义
| Byte1 指令 ID | 功能 | 参数定义 |
|---|---|---|
0x01 | 仪表指针 | Byte2:0~100 的百分比,当前工程将其映射到约 0~250°;这不是直接发送真实转速值 |
0x02 | 水温报警图标 | Byte2:0 为白色/不报警,1 为红色/报警 |
0x03 | 安全带图标 | Byte2:0 为白色,1 为红色 |
0x04 | 灯光图标 | Byte2:0 为白色,1 为黄色,2 为红色 |
0x05 | 转向灯图标 | Byte2:0 为关闭,1 为点亮/红色 |
0x06 | 设置日期 | Byte2:年份前两位;Byte3:年份后两位;Byte4:月;Byte5:日 |
0x07 | 设置时间 | Byte2:时;Byte3:分;Byte4:秒 |
视频思维导图把小时范围写成 0~12、分秒写成 0~60,这两处不准确。本实验使用 24 小时制,合理范围应为:小时 0~23,分钟和秒 0~59。月份应为 1~12,日期还必须符合当月天数和闰年规则,不能只检查是否小于等于 31。
1.2.1.3 串口助手中的实际测试指令
发送区必须选择 HEX(十六进制)发送。如果选择 ASCII 发送,输入字符 AF 实际发送的是字符 'A'、'F' 的编码 0x41 0x46,不会得到一个字节 0xAF。
| 测试项目 | 发送的 8 字节 | 预期现象 |
|---|---|---|
| 指针 17% | AF 01 11 3B 30 01 AF AF | Byte2 的 0x11=17,指针移到约 17% 位置 |
| 指针 49% | 将上条 Byte2 改为 31 | 0x31=49,指针继续向右转 |
| 指针 81% | 将上条 Byte2 改为 51 | 0x51=81,指针再向右转 |
| 水温不报警 | AF 02 00 AF AF AF AF AF | 水温图标为白色 |
| 水温报警 | AF 02 01 AF AF AF AF AF | 水温图标变红 |
| 安全带白色 | AF 03 00 AF AF AF AF AF | 安全带图标为白色 |
| 安全带红色 | AF 03 01 AF AF AF AF AF | 安全带图标变红 |
| 灯光白色 | AF 04 00 AF AF AF AF AF | 灯光图标为白色 |
| 灯光黄色 | AF 04 01 AF AF AF AF AF | 灯光图标变黄 |
| 灯光红色 | AF 04 02 AF AF AF AF AF | 灯光图标变红 |
| 转向灯关闭 | AF 05 00 AF AF AF AF AF | 转向灯图标关闭 |
| 转向灯点亮 | AF 05 01 AF AF AF AF AF | 转向灯图标点亮/变红 |
指针测试第一条中的 Byte3~Byte7 对当前接收程序没有业务意义,只是占满固定 8 字节;它们不是校验码。变量名虽然沿用了 rpm,本节协议实际传递的是 0~100 的位置百分比,不能把 0x11 理解为 17 r/min。
1.2.1.4 日期校准
视频发送:
AF 06 14 19 07 14 AF AF
各字节必须按十六进制换算:
- Byte2
0x14=20,表示年份前两位; - Byte3
0x19=25,表示年份后两位; - Byte4
0x07=7,表示 7 月; - Byte5
0x14=20,表示 20 日。
因此该指令表示 2025-07-20,不是原笔记中的 2025-07-30。视频里仪表实际显示 7 月 20 日,讲师随后也纠正了口误。后续把 Byte4 改成 0x08、Byte5 改成 0x16,则表示 2025-08-22,因为 0x16=22。
配套接收工程虽然把 Byte2~Byte5 全部打包保存,但真正调用 STM32 RTC 设置日期时只取 Byte3、Byte4、Byte5;显示字符串的世纪部分又固定写为 20。因此本课程当前实现实质上只适合显示 2000~2099 年,Byte2 尚未真正参与 RTC 年份设置。这里记录的是现有课程行为,不应误认为 STM32F1 RTC 自带四位年份寄存器。
1.2.1.5 时间校准
视频发送:
AF 07 10 08 21 AF AF AF
换算结果为:
- Byte2
0x10=16:16 时; - Byte3
0x08=8:8 分; - Byte4
0x21=33:33 秒。
因此该指令设置的是 16:08:33。这也直接证明协议采用 24 小时制,而不是思维导图误写的 0~12 小时。
1.2.1.6 完整实验步骤
- 断电检查两块开发板、两只 CAN 收发器、CANH/CANL、参考地和两个 USB 转 TTL 模块的接线。
- 检查 CAN 总线两端的终端电阻,不要重复接入过多的
120 Ω电阻。 - 给 ZET6 和 C8T6 上电,打开两个串口助手窗口。
- 把两个窗口都配置为 115200、8N1、无流控;数据窗口选择 HEX 发送,日志窗口按文本接收。
- 复位 C8T6,通过
C8T6 running确认日志口。 - 从 USART2 数据窗口逐条发送 8 字节指令。
- 同时观察三处结果:数据窗口是否确实发出 8 字节、日志窗口是否打印 CAN 发送记录、ZET6 仪表盘是否产生对应变化。
- 一次只修改一个字段并重发,结合十六进制到十进制的换算判断结果是否正确。
1.2.1.7 常见故障的分段定位
| 现象 | 优先检查 |
|---|---|
| 两个串口都打不开 | COM 口是否被其他程序占用、USB HUB 是否供电不足、驱动是否正常 |
| 日志窗口乱码 | USART1 的波特率和 8N1 参数是否正确 |
没有 C8T6 running | 是否选错串口、C8T6 是否上电、USART1 TX/RX 是否接反、GND 是否共地 |
| 能看到启动日志,但发指令无 CAN 日志 | 是否从 USART2 对应窗口发送;是否选了 HEX;是否恰好为 8 字节;首字节是否为 AF |
| C8T6 显示 CAN 已发送,ZET6 无变化 | CANH/CANL 是否接反、终端电阻是否正确、两块板是否共参考地、两端 CAN 波特率是否一致 |
| 只有某一类指令无效 | Byte1 指令 ID 或参数范围是否写错,ZET6 是否只接收 0x0B4 标识符 |
| 日期或时间与预期不同 | 是否把十六进制误当十进制;例如十六进制 14 是十进制 20,不是 14 |
调试时应按“串口输入 → C8T6 日志 → CAN 物理链路 → ZET6 解析 → LVGL 显示”的顺序逐段确认。这样能把问题限制在某一段,而不是一看到仪表没变化就同时改串口、CAN 和界面代码。
二、本节应建立的认识
- 串口、CAN 控制器和 CAN 收发器是三个不同层次:串口负责电脑到 C8T6,CAN 控制器生成/解析 CAN 帧,CAN 收发器负责把逻辑信号转换为 CANH/CANL 差分信号。
- CAN 标识符
0x0B4用来标识这类报文,应用数据区里的0xAF和指令 ID 则由课程自定义;二者位置和职责不同。 - 串口助手中的“HEX 发送”和“ASCII 发送”决定实际在线路上传输的字节,界面上看起来相同的
AF可能代表完全不同的数据。 - 协议字段是二进制数值。串口助手用十六进制显示它们,所以读报文时必须正确进行进制换算。
- 一次成功演示只能证明当前接线与测试数据能工作。要形成可靠系统,还需在后续课程中完善接收、校验、超时、错误处理和业务边界检查。
三、资料依据
- 课程视频、转录文本,以及配套工程
26Can_Recv、27C8T6_Send;工程用于核对PA2/PA3、PA9/PA10、PA11/PA12的复用功能、8 字节接收方式、CAN 标识符0x0B4和接收端字段解释。 - STMicroelectronics:STM32F103xC/D/E 数据手册:核对 STM32F103 的 USART 与 CAN 引脚复用。
- CAN in Automation:Designing a CAN network:经典 CAN 数据区最大 8 字节及线型拓扑说明。
- CAN in Automation:CAN high-speed transmission:高速 CAN 总线两端
120 Ω终端匹配说明。 - MathWorks:Electric Vehicle Reference Application:核对 VCU 在电动车控制器中涉及扭矩仲裁和功率管理,而不只是简单转发数据。