结论:2011 款沃尔沃 C30 T5 是少数可以直接从诊断口同时够到两条总线的车:它的高速总线 500 kbit/s、低速总线 125 kbit/s,全部使用 29 位扩展 ID、每帧固定 8 字节,且诊断口与整车之间不存在网关,两条总线都被引到 OBD 连接器上。配套研究留下两份清单——35 个广播 ID 的嗅探记录(24 条带功能注释)与 462 条 VIDA 请求条目,其中 147 个是唯一的 ECM 故障码。真正需要警惕的是请求表里混着执行器动作、ECU 复位、擦除与全总线静默这几类命令,它们和读数据命令只有第三个字节的差别。
双总线拓扑:为什么这台车的嗅探门槛很低
这台车有两条 CAN 网络。高速总线挂 ECU、转向模块、制动及其他模块,低速总线挂收音机、车门模块、仪表组合及附属电器,中央电子模块 CEM 在两者之间做网关。关键在于:诊断口与整车其余部分之间没有额外网关,两条总线都被引到了 OBD 连接器上,因此不需要任何中继设备就能同时观察两侧流量。
代价是物理层和寻址方式都比常见乘用车更特殊:29 位扩展 ID、每帧一律 8 字节、两条总线速率差四倍。作者也说明,同年代更早的车型需要先通过 K 线激活诊断继电器才能从诊断口访问 CAN,这台车不需要,因此那份资料对老车型不适用。兼容性方面的表述很克制——其他采用同款博世 ME9 实现的车型大概率无需改动即可工作,但有报告称广播 ID 会随车辆变化,需要自行调整。
| 总线 | 速率 | 主要节点 | 接入方式 |
|---|---|---|---|
| 高速总线 | 500 kbit/s | ECU、转向模块、制动模块 | 诊断口直连,29 位扩展 ID |
| 低速总线 | 125 kbit/s | 收音机、车门模块、仪表组合 | 诊断口直连,29 位扩展 ID |
| 网关 | — | 中央电子模块 CEM | 诊断口与整车之间无额外网关 |
| 帧长度 | — | 所有 ECU 的所有帧 | 一律 8 字节 |
| 前置条件 | — | 更老车型 | 需经 K 线激活诊断继电器 |
VIDA 请求帧:与 UDS 的差别只在开头两个字节
VIDA 是与 UDS 类似的诊断协议,但帧结构不同:第一个字节是数据长度码,第二个字节才是 ECU 地址。这一点决定了它不能直接用标准 UDS 工具发。以读取增压压力为例,请求帧 ID 为 0x000FFFFE,数据为 CD 7A A6 12 9D 01 00 00:首字节 CD 等于 C8 加上后续有效字节数,7A 是发动机 ECU 的地址,A6 是按标识符读当前数据,12 9D 是增压压力参数,01 大概是「只回送一次」,其余补零凑满 8 字节。
响应帧 ID 为 0x00400021,数据 CD 7A E6 12 9D 95 00 00:E6 是对 A6 的正响应,12 9D 回显所请求的参数,95 才是返回值。也就是说,解析时要先按首字节裁出有效长度,再按「地址—命令—参数—值」的顺序取值,不能假定整帧都是有效载荷。
| 字节位置 | 请求帧示例 | 响应帧示例 | 含义 |
|---|---|---|---|
| 帧 ID | 0x000FFFFE |
0x00400021 |
请求与响应使用不同 CAN 地址 |
| 字节 0 | CD |
CD |
C8 加后续有效字节数 |
| 字节 1 | 7A |
7A |
ECU 地址,此处为发动机 ECU |
| 字节 2 | A6 |
E6 |
按标识符读当前数据及其正响应 |
| 字节 3–4 | 12 9D |
12 9D |
参数标识,此处为增压压力 |
| 字节 5 | 01 |
95 |
请求侧为回送次数,响应侧为返回值 |
| 字节 6–7 | 00 00 |
00 00 |
补零至 8 字节 |
命令字节全集与风险分档
第三个字节决定动作类型,资料里列出的取值及其含义如下。需要特别注意的是其中几类并非只读:跳转执行、运行代码段、启动引导、擦除、复位,以及以 FF 为 ECU 标识的全局命令「全总线静默」与「全总线复位」。这些命令与读数据命令在帧结构层面完全相同,只差一个字节的值,因此任何把请求表整体接入自动化脚本的做法都必须先做白名单过滤。
| 命令字节 | 含义 | 风险档 |
|---|---|---|
A6 |
按标识符读当前数据 | 只读 |
AE |
发送数据(资料中主要用于读故障码) | 只读 |
B9 |
读 ECU 硬件/软件件号与序列号、防盗通信计数 | 只读 |
A3 |
防盗安全访问:发送或重锁防盗 PIN | 写入 |
A8 |
设置引导段结束 | 写入 |
AF |
清除全部已存储的 2 字节故障码 | 写入 |
B1 |
执行器动作,如逐缸喷油器开启 | 动作 |
B2 |
启停泄漏快检 | 动作 |
B4 |
结束取数与校验和 | 写入 |
B8 |
写防盗 PIN 与安全码 | 写入 |
9C / A0 / C0 |
跳转地址 / 运行跳转点代码段 / 启动引导 | 高危 |
C8 / F8 |
复位 ECU / 擦除 | 高危 |
86 / C8(ECU 为 FF) |
全总线静默 / 全总线复位 | 高危 |
462 条请求条目:规模与命令分布
请求清单共 507 行,其中 462 行是带分号分隔的有效条目,按命令字节分布为:A6 读数据 236 条、AE 读故障码 152 条、B1 执行器动作 59 条,其余十余条分散在 B9、A3、B2、B8、AF 上。也就是说,这张表约八成是只读请求,但剩下的两成里有 59 条会直接驱动执行器。
每条只读请求附带换算式,这是它比起单纯的参数列表更有价值的地方。换算形态有三类:线性乘系数、含偏移的线性式(如温度统一按乘 0.75 减 48 得摄氏度)、以及按位掩比较(用于开关量与状态位)。同一参数在不同条目里出现不同换算式的情况也存在,例如喷油时间在两处分别给乘 0.002666 与除 375,使用时应以实车回归为准。
| 参数 | 请求数据 | 换算式 | 单位 |
|---|---|---|---|
| 增压压力 | A6 12 9D 01 |
乘 10 | hPa |
| 增压压力传感器电压 | A6 12 9C 01 |
乘 5.0/1024 | V |
| 发动机转速 | A6 10 1D 01 |
乘 40 | rpm |
| 车速 | A6 11 40 01 |
乘 1.25 | km/h |
| 冷却液温度 | A6 10 D8 01 |
乘 0.75 减 48 | 摄氏度 |
| 进气温度 | A6 10 CE 01 |
乘 0.75 减 48 | 摄氏度 |
| 点火提前角 | A6 10 36 01 |
乘 191.25/255 | BTDC |
| 空气质量流量 | A6 10 29 01 |
乘 4 | kg/h |
| 蓄电池电压 | A6 10 0A 01 |
乘 0.07 | V |
| 油门踏板(模拟输入) | A6 10 04 01 |
乘 100/65535 | % |
故障码清单:147 个唯一码与它的取法
读故障码统一使用 AE 11,即按 2 字节故障码请求,清单里共出现 147 个唯一的 ECM 前缀码,覆盖增压压力传感器、点火线圈逐缸信号、喷油器逐缸、节气门单元内部故障、控制模块内部故障、前后氧传感器、失火逐缸与催化器损伤、涡轮控制阀、燃油泵继电器、系统继电器、5 V 供电、配置故障等。清单中还有一条写作 ECM-XXXX,标注为「当前控制模块版本下的未知故障码」,这是解读时的一个重要提示:同一数值在不同软件版本上可能对应不同含义。
清码使用 AF 11,描述为「清除全部已存储的 2 字节故障码」。这是一次性的 bus-write 动作,在只读采集脚本里不应出现。与此相对,B9 F0、B9 F5、B9 F8 分别读取 ECU 硬件件号、软件件号与硬件序列号,是确认所连车辆软件版本最安全的方式,排在读故障码之前更合理。
35 个广播 ID 的嗅探记录
广播侧的记录共 35 条,字段为 ID、数据长度码、8 字节数据、周期、观测计数与注释;其中 24 条带功能注释,11 条留空。周期列取值从 30 到 1088,观测计数从 8029 到 184057。注释里最有价值的是「CRITICAL FOR CLUSTER」这一类标记——它指出哪些帧是仪表正常工作所依赖的,一旦在总线上缺失或篡改,仪表会出现可见异常;这类帧在实验里应只观察、不注入。
| ID | 周期 | 观测计数 | 注释要点 |
|---|---|---|---|
021204B8 |
30 | 184057 | 转向灯 |
03C3F7FC |
31 | 170711 | 点火状态 |
09C050B8 |
52 | 91376 | 仪表与里程计数;字节 1 的第二个半字节为亮度,字节 4 与 5 为转速,标记「仪表关键」 |
0EE0500A |
101 | 50799 | 气囊灯,标记「仪表关键」 |
1093F7FC |
248 | 8029 | 标记「仪表关键」,无进一步说明 |
1760E008 |
153 | 29186 | 仪表车速与告警灯 |
1AD10068 |
600 | 12205 | 字节 1 为油量;字节 2 在仪表开时为 0x04、关时为 0x07 |
19F010FC |
201 | 25299 | 巡航控制按键 |
16124008 |
97 | 38201 | 胎压告警灯 |
16801028 |
233 | 32269 | ABS 与制动失效灯 |
这份记录也说明了作者的实现策略:优先从广播帧取数,因为开销和总线占用都低;只有在广播里根本不出现的量(增压压力就是典型)才改用请求。仪表亮度、点火状态、方向盘按键都在后台循环里持续更新全局变量,供显示循环使用——代码采用一种伪多任务结构,接收循环在其他循环不运行时始终在跑,因此广播变化不会漏掉。此外还记录了一个交互细节:长按巡航取消键超过 2 秒切换显示页面。
硬件侧也有参考价值:控制器用 Arduino Due 配合其双 CAN 接口的库,显示屏是一块 2.2 英寸圆形串口屏,两者都挂在诊断口上而不经过任何改装线束。显示项最终定为增压压力、冷却液温度、进气温度与点火提前角四个,其中三项要靠请求才拿得到。仪表指针还做了模拟化处理:数值跳变超过 1 时不允许瞬时跨越,必须逐级走完中间值,以避免数字仪表的跳变感。
常见问题
这台车的诊断口能直接读到两条总线吗?
能。它的高速总线 500 kbit/s、低速总线 125 kbit/s,诊断口与整车之间不存在网关,两条总线都被引到 OBD 连接器上。但要注意更老的同品牌车型需要先通过 K 线激活诊断继电器才能访问 CAN,这份资料不适用。
VIDA 协议能不能用标准 UDS 工具发?
不能。它与 UDS 的差别在帧开头:第一个字节是数据长度码,第二个字节才是 ECU 地址,而 UDS 的寻址方式不同。解析响应时也要先按首字节裁出有效长度,再按地址、命令、参数、返回值的顺序取值。
增压压力为什么必须靠请求而不是广播?
因为这类量在广播帧里根本不出现。该研究优先使用广播帧取数以降低总线开销,只有广播中不存在的数据才走请求路径,增压压力就是其中之一,对应请求数据为 A6 12 9D 01、换算为乘 10 得百帕。
请求表里有哪些命令不能随便发?
约两成条目不是只读。59 条 B1 会直接驱动执行器(如逐缸喷油器开启),AF 清除全部故障码,A3 与 B8 涉及防盗 PIN,9C、A0、C0 涉及跳转与引导,C8、F8 是复位与擦除,而以 FF 为地址的 86 与 C8 会作用于整条总线。自动化脚本应先做命令白名单过滤。
这些广播 ID 能套用到其他车吗?
不能默认可以。作者明确表示与其他车辆的兼容性未知,采用同款博世 ME9 实现的车型大概率无需改动,但有报告称广播 ID 会随车辆变化。此外清单里存在 ECM-XXXX 这类条目,标注为当前控制模块版本下的未知故障码,说明同一数值在不同软件版本上含义可能不同。
延伸阅读
- UDS 诊断工具为什么不能随手调:只读、会话与写 ECU 的分权设计 —— 请求表的权限分档思路
- Freelander 2 中速 CAN 梳理:两个 DBC 版本、39 报文与 125 kbit/s —— 同为双总线与低速网的对照
- Alfa Giulia 的 177 行 PID:header 错了会触发防盗 —— 私有诊断请求的风险边界
- 84% 的 PID 没有公开证据:OBD 私有协议解析的现实边界 —— 换算式可信度怎么判断
- 车型数据库 —— 按车型查 CAN 与诊断档案
参考资料
- 项目 01 ——
public-can-dbc-datasets/additional/alfaa123-volvo-c30-research/README.md(车辆年份与型号、双总线速率、29 位扩展 ID、硬件构成与兼容性说明) - 项目 01 ——
public-can-dbc-datasets/additional/alfaa123-volvo-c30-research/Codes.txt(VIDA 请求帧结构、命令字节全集与 462 条带换算式的请求条目) - 项目 01 ——
public-can-dbc-datasets/additional/alfaa123-volvo-c30-research/Sniffing/RX List.txt(35 个广播 ID 的数据、周期、观测计数与功能注释)
免责声明
本文所述的总线参数、请求帧结构与故障码清单均为社区逆向工程的研究笔记,不代表车辆制造商的官方数据,文中数字均来自上述公开仓库的说明文件,未经独立实车验证。该仓库快照中未发现任何许可证,仅可作私有离线研究副本,再分发或集成前须先行确认权利。文中列出的执行器动作、故障码清除、ECU 复位与擦除、全总线静默等命令不得在未知车辆或公共道路上使用;诊断请求与主动 CAN 流量不得假定对另一辆车安全。涉及安全相关用途时请以官方资料与实际测量为准。
更新记录
- 2026-10-15 初稿