标签: UDS

  • 沃尔沃 C30 嗅探记录:35 个 29 位 ID 与 462 条 VIDA 请求

    结论: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 这类条目,标注为当前控制模块版本下的未知故障码,说明同一数值在不同软件版本上含义可能不同。

    延伸阅读

    参考资料

    • 项目 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 初稿

  • 思域 FL5 的 25 个 DID 与 109 个信号:只读 UDS 请求流程

    结论:这份参考给出 25 个 UDS 服务 22 的 DID 与 109 个解码信号,来自同一辆 Civic Type R FL5(K20C1 2.0T,6 速手动)在 2026-09-08 至 2026-09-16 的八轮只读采集。第一件事不是数信号,而是承认它的形态:这辆车 OBD 口后面有网关,被动监听 24.8 分钟、59 万帧里 16 个 CAN ID 全是 18DAxxxx 诊断帧,广播帧数为 0。所以主键是「模块地址 + DID + 字节 / 位偏移」,不是 CAN ID。

    形态决定主键:为什么它不是一份 DBC

    钥匙 ON、怠速、行驶全程广播帧数都是 0,文档里每一个数字都是「主动问、ECU 答」得到的正应答字节。同一条物理通道上靠 29 位 ID 里的目标地址区分四个已解码 ECU(ECM、VSA、EPS、组合仪表)。

    因此 DBC 不适合作为主格式:DBC 描述周期广播帧的布局,而这里没有广播帧可描述。要机器读,应该用 data/signals.json 或 data/signals.csv,或者 OBDb signalsets/v3 兼容的 obdb-signalset.json——后者只收录「已确认(研究级)」与「中」两档,低置信与候选留在文档里不进 signalset。

    层 事实
    物理 OBD-II 口:6 脚 CAN-H、14 脚 CAN-L、4 脚 GND、16 脚 12 V 常电。6 / 14 按插进车的公头方向数,数反会得到 0 帧
    链路 经典 CAN 2.0B,500 kbit/s,单帧不超过 8 字节,无 CAN FD(12 份日志约 190 万帧,FD 帧计数 0)。只证明网关外的 OBD 侧
    寻址 29 位 ISO 15765 物理寻址:请求 18DA 加目标地址加 F1,应答 18DAF1 加目标地址;诊断仪地址固定 F1。点名全车用功能广播 18DB33F1。11 位 7E0 / 7E8 上 Mode 01 无任何应答
    传输 ISO 15765-2:请求单帧 03 22 DID高 DID低,用 0x55 填满 8 字节;应答 54 到 63 字节数据区 = 首帧 FF 加 8 到 9 个连续帧 CF。流控 30 00 00(填充 0xAA)必须在几毫秒内回,晚了 ECU 直接放弃
    应用 UDS 服务 22 ReadDataByIdentifier。本车默认会话免握手(不需要 10 03,更不需要 27);3E 保活实测不需要(600 s 连续采样零错误)。此条只在本车验证过
    偏移口径 offset 指去掉应答头 62 加 DID 两字节之后的数据偏移;[a:b] 不含 b;value = raw 乘 scale 加 add。默认大端,明确标注小端的除外

    时序与预算:单 ECU 串行上限约 33 Hz

    下表是主机侧观测值,不是 ECU 的硬限制。采集用的适配器无硬件时间戳,所以「VSA 80 ms」应读作首帧到末帧的整段,而不是帧间隔,也不能据此断定是 STmin 硬限制。

    模块 / DID 请求到完整 p50 p95 相邻 CF 间隔
    ECM 10:2610 24.9 / 27.4 ms 30.7 / 30.6 ms 约 2 ms
    ECM 10:2611 29.3 ms 33.5 ms 约 2 ms
    ECM 10:268F 27.3 ms 29.8 ms 约 2 ms
    VSA 28:4001/4004/4007/4073 约 100.1 ms 约 100.6 ms 约 10 ms
    EPS 30:48BD/48C0/48C4 约 67.9 ms 约 69 ms 约 8 ms

    串行模型是成立的:2051 轮逐轮恒等式「周期 = 各请求到完整之和 + 各间隙之和」残差为 0,轮间开销 1.48 ms/轮,由此得到单 ECU 串行上限约 1 秒除以 30.5 ms,即约 33 Hz(仅 ECM)。跨模块并发在协议上允许(不同地址各挂一个未完成请求),本车从未验证;按模块求和再取最大的理想周期只比串行快约 28%,不是 100 ms。作为对照,原厂调校工具自己轮询 22 2610 与 22 2611 各 18.13 Hz。

    NRC 含义 本车观察
    0x31 requestOutOfRange(该 DID 不存在) 扫描时的主力否定应答,全归档最常见
    0x11 serviceNotSupported 服务 21(五个模块各 256 个 LID)与服务 24 全部返回它,本车不支持,不必再试
    0x22 conditionsNotCorrect 有处理逻辑;扫描中零星出现
    0x78 requestCorrectlyReceived-ResponsePending 有处理(最多 5 乘 timeout);全归档统计里不计入否定应答
    0x80 厂商自定义 / 未列入标准表 第二轮扫 ECM 时出现过一次

    两条吃了亏才写下的采集纪律

    其一,一笔请求超时会触发对该地址的隔离,所以采样组的第一笔要放最稳的 DID。其二,行驶中不要把扫描和核心采样混在一条串行链上——边行驶边扫描的一份日志里核心采样最长断流 7.891 s,而纯核心采样的另一份最长只有 1.244 s。

    模块清单与扫描覆盖

    零件号由 22 F181 或 22 F110 读出,是同款车共有的零件号,不是单车序列号;数据集不含 VIN、ECU 序列号或任何单车唯一标识。功能广播点名时,公开信号集里有而本车无应答的地址有 0x2A、0x0E、0x11、0x1D、0x01、0x15、0x16。

    地址 身份 零件号 扫描覆盖 有正应答 DID 收录 状态
    0x10 ECM/PCM 发动机控制 37805-66V-H020 0000–FFFF 全段 77 个(26xx 52 + 30xx 5 + DC59–FFFF 段 20) 10 个 扫描中 6F2B / 6F8A / DC58 三个单点无应答触发隔离,未复读
    0x28 VSA 车身稳定(ABS/ESC) 57114-T60-AA20 0000–A082 31 个(4000–400A、4030–403B、4070–4073、0EEC、4100、48AF、48F5) 5 个 A083–FFFF 未扫
    0x30 EPS 电动转向助力 39990-T60-J030 0000–7EEB 20 个(全在 48xx) 5 个 重扫 0000–2A30 无新增;2A31–FFFF 待续
    0x3A ADS 自适应减振 39390-31M-A040 0000–FFFF 全段 16 个(48AF、48F5、52xx、5280/5281、E600、E602、F1xx) 0 个 10 个数据类里 9 个逐字节恒定,唯一在动的 520A 未解码
    0x53 SRS 气囊 77959-T60-H830 未扫 — 0 个 故意不碰
    0x60 组合仪表 78108-T60-H020 7000–70FF 18 个(有数据的 6 个) 5 个 其余段未扫
    0x70 未知(33137 系,疑似大灯控制) 33137T24Y112M1 未扫 — 0 个 功能广播点名有应答
    0xB0 多用途摄像头(Honda Sensing) 36161-T60-H050 0000–00C5 0 0 个 对服务 22 基本不配合,两次都在 00xx 某个 DID 超时被隔离;已放弃
    0xB3 Honda Sensing 子单元 36162-T51-H010 未扫 — 0 个 功能广播点名有应答
    0xB7 驻车雷达控制单元 39670T60E010M1 未扫 — 0 个 功能广播点名有应答
    0xED 车身控制 / 网关之一(38898 系) 38898-T60-H010 未扫 — 0 个 与 EF 成对
    0xEF 网关 / 车身控制之一(38897 系) 38897-T60-H010 未扫 — 0 个 功能广播时它最先应答,疑似网关

    信号总表摘录

    四个模块、25 个 DID、109 个信号,置信度分布为已确认(研究级)52、中 39、低 / 候选 18。文档不升不降任何一条的置信度。下面摘录 ECM 两个主包与几个跨模块的对照项;「实测范围」是全部采集里出现过的最小 / 最大值与样本数,只说明观察到过什么,不定义量程也不定义报警阈值。

    模块 : DID 信号 偏移 解码 单位 实测范围(样本数) 置信
    10:2610 ENGINE_RPM 6(2 B 大端) raw 乘 0.25 rpm 0 到 5300(53,908) 已确认(研究级)
    10:2610 MAP_ABS 9(2 B 大端) raw 乘 0.0078125 kPa 22.27 到 282.35(53,908) 已确认(研究级)
    10:2610 ECT 11(1 B) raw 减 40 摄氏度 33 到 90(53,908) 已确认(研究级)
    10:2610 VEHICLE_SPEED 18(1 B) raw km/h 0 到 137(53,908) 已确认(研究级)
    10:2610 BATTERY_V 22(1 B) raw 乘 0.1 V 6 到 14.6(53,908) 已确认(研究级)
    10:2610 OIL_PRESSURE 44(2 B 大端) raw kPa 0 到 626(53,908) 已确认(研究级)
    10:2611 LAMBDA 8(2 B 大端) raw 乘 3.0517578e-05 lambda 0.765 到 2.000(42,797) 已确认(研究级)
    10:2611 SHORT_TRIM 10(1 B) raw 乘 0.78125 减 100 % -10.16 到 17.97(42,797) 已确认(研究级)
    10:2611 GEAR 19(1 B) raw gear 0 到 6(42,797) 已确认(研究级)
    10:2611 PEDAL 20(2 B 大端) raw 乘 0.005 % 0 到 60.83(42,797) 已确认(研究级)
    10:2611 BOOST_PRESSURE 24(2 B 大端) raw 乘 0.013157894736842105 kPa 绝压 94.51 到 215.08(42,797) 已确认(研究级)
    10:2611 WASTEGATE 28(2 B 大端,有符号) raw 乘 0.001 mm(未证实) -0.176 到 8.412(42,797) 已确认(研究级)
    10:268F OIL_TEMP_MODEL 15(1 B) raw 减 40 摄氏度 32 到 82(20,684) 已确认(研究级)
    28:4005 BRAKE_PRESSURE 7(2 B 大端) raw 减 25 bar 0 到 106(4,840) 已确认(研究级)
    28:4007 REVERSE_GEAR 11(bit 1,掩码 0x2) raw 与 0x2 bool 0 到 2(3,515) 已确认(研究级)
    28:4007 CLUTCH_PEDAL 24(1 B) raw % 0 到 100(3,515) 已确认(研究级)
    30:48BD STEER_ANGLE 11(2 B 大端,有符号) raw 乘 0.1 deg -405.6 到 408.1(5,164) 中
    30:48C4 WHEEL_SPEED_FL 23(2 B 大端) raw 乘 0.01 km/h 0 到 115.23(3,193) 已确认(研究级)
    60:7022 ODOMETER_CLUSTER 6(3 B 大端) raw km 不公开(1,394) 已确认(研究级)
    60:7028 AMBIENT_TEMP 17(1 B) raw 摄氏度 26 到 34(2,059) 已确认(研究级)
    60:7029 FUEL_LEVEL 12(2 B 大端) raw 乘 0.01 L 16.46 到 43.88(1,393) 已确认(研究级)

    三条容易读错的约定

    同名信号出现在两个 DID 时(VEHICLE_SPEED_COPY、STEER_ANGLE_COPY),是两个不同位置的独立字段,解码与置信度各按所在 DID 读。标 kPa_abs 的是绝压;要增压表压请用同一应答包内的 MAP_ABS 减 BARO(同包相减,不要减 101.325 这类常数)。带掩码的位字段在「实测范围」列显示的是掩码后的原始值,例如掩码 0x8 的置位状态显示为 8,而不是 1。

    证据边界:未映射的变化字节与不可辨识项

    已映射的 25 个 DID 里还有 206 个未映射的变化字节、1,183 个位,其中在单次采集内部就会变的有 189 字节、1,124 位——由位级覆盖分析从全部采集算出。其中 4 个字节里「未映射位」与「已映射位」同处一室,按整字节做候选筛选的工具看不到它们。

    类型 位置 现状 缺什么
    未映射 10:2610 [8] 与 [27] 完全相同,燃压低字节镜像 未命名,仅登记
    未映射 10:2610 [16] 日志内变化,只有低 4 位(掩码 0x0F),5 种取值,与水温 r 约 -0.77 位域身份未定
    未映射 10:2610 [51] 0 到 240 阶梯,步长约 7.5 未扫,性质未知
    未映射 10:2611 [53:55] / [55:57] ECM 内部短时负向修正量,值域 -53 到 0;位宽不可辨识(该值域内 s8 与 s16 小端恒等);两者是单向包含关系 需要一个绝对值大于 127 的样本才能分开
    未映射 10:268F [12] / [13] / [14] 带 255 端点码;[12] 与转速的关系在差分与配对两道检验下都存活(r = 0.21 / 0.256),是 50 个候选里唯一存活的 不命名
    未映射 3A:520A 整包 64 B ADS 唯一在动的数据包,未解码;多字节字段候选 3 个(10:12、36:38、38:40,均大端) 整包未扫
    不可辨识 偏航率刻度 0.0045(运动学模型)对 0.003924(后轮差速几何法) 需外部偏航率参考(不低于 10 Hz、误差小于 3%)或实测轮距与滚动周长
    不可辨识 2610[39] 的门限 单一压力门限与 Schmitt 迟滞均已推翻;转速 / 档位分层使留出集 log-loss 改善 17 到 18% 未过 20% 门槛,判不出,不是无效应
    不可辨识 AIRC_MAX / AIRC_PROT / AIRC_COMP 三个字节 [49] / [57] / [58] 全程相等 三个名字在现有数据里无法区分
    不可辨识 扫描期链路停摆的机制 现象强相关;单 ECU 忙已排除,网关限流 / ISO-TP 异常 / 工具实现 / 静默超时四种都证据不足 缺适配器状态遥测,分不开「工具阻塞」与「总线 / 网关静默」

    常见问题

    这份参考能直接转成 DBC 吗?

    不能,也不该转。DBC 描述的是周期广播帧的布局,而这辆车的 OBD 侧广播帧数为 0,全部数据来自服务 22 的问答。主键是模块地址加 DID 加字节 / 位偏移,同一条物理通道上靠 29 位 ID 里的目标地址区分四个已解码 ECU。要机器读请用 signals.json、signals.csv 或 OBDb 兼容的 signalset。

    为什么按 7E0 / 7E8 发 Mode 01 收不到任何东西?

    因为这辆车走 29 位物理寻址:请求是 18DA 加目标地址加 F1,应答是 18DAF1 加目标地址,诊断仪地址固定 F1;11 位地址上 Mode 01 全程零应答。另一个常见失误是引脚数反了——6 脚 CAN-H、14 脚 CAN-L 要按插进车的公头方向数,数反了同样得到 0 帧。

    轮询频率能开到多高?

    串行模型下约 33 Hz(仅 ECM),由 1 秒除以单事务约 30.5 ms 得出,轮间开销 1.48 ms/轮,2051 轮恒等式残差为 0。跨模块并发在协议上允许但本车从未验证,理想化估算只比串行快约 28%。作为对照,原厂调校工具自己只跑 18.13 Hz。

    为什么两条里程信号不给出实测范围?

    因为精确里程读数能定位到具体某一辆车,作者主动不公开。样本数照常给出:ECM 的 ODOMETER 是 365 个样本,仪表的 ODOMETER_CLUSTER 是 1,394 个,两条相互核对一致且单位都是 km(公开信号集里写成英里是错的)。

    「已确认(研究级)」是不是等于已经标定过?

    不等于。它只表示这一辆车上证据强——与独立仪表逐点对上、或与调校工具的未取整导出逐列拟合到 r 约等于 1、或有干净的前后对照动作。它不代表已用独立仪器标定,也不代表在原厂车上成立。这辆车装有调校工具,ECU 已解锁,市场版本也未确认。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/SOURCE.md(固定修订、许可条款、25 DID / 109 信号的范围与限制)
    • 项目 01 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/README.zh-CN.md(分层事实、逐事务耗时、NRC、模块扫描覆盖与信号总表)
    • 项目 01 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/README.md(英文版信号总表与已推翻说法)
    • 项目 01 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/CHANGELOG.md(数据版本 1.0.0 与 1.0.1 的变更记录)

    免责声明

    本文所述 DID 与信号均为社区只读诊断所得,不代表本田的官方数据,全部来自同一辆装有调校工具(ECU 已解锁)的 Civic Type R FL5,年款与市场版本均未确认。采集与本文档制作全程只使用服务 22 及配套只读服务,不含任何刷写、安全访问或内存读取内容;被明确排除且不得据本文尝试的服务包括 27、23、2E、31、11、14 与 34 到 37。把这里任何一条用在别的车上之前请自行复核。涉及安全相关用途时请仅作参考。

    更新记录

    • 2026-10-15 初稿

  • canlab-zn6:四层只读约束与 9 个受限诊断查询

    结论:canlab-zn6 的「只读」不是一个 UI 设计选择,而是四层各自独立的关:固件跑控制器 listen-only 并持续拉住收发器的 silent 引脚、wire protocol 里根本没有发帧命令、Host 只在 decode-only 门面后面用 can_decode、 contributing scope 直接把写诊断与 ECU 仿真列为不接受。它的价值恰恰在于这套自限——看懂这四层,就知道为什么它是稳妥的上车第一步,也知道它当前拿不到什么。

    四层只读约束分别拦住了什么

    大多数「只读工具」只在应用层藏了一个按钮。这份 Rust 工具链把约束下沉到了四个不同层次,每一层的失效模式都不一样,因此值得逐层拆开看。

    层次 机制 拦住的动作 残余风险
    固件 控制器 listen-only 模式,并持续把收发器硬件 silent 输入保持在有效状态 ESP32-S3 / ESP32-C6 板卡自发帧 依赖电气连接正确,官方要求接车前用电表验证 silent 引脚
    协议 主机 CLI、Web 应用、SocketCAN 适配器、wire protocol、MCP server 均无任意发送命令 来自上位机的单帧注入 与本工具同栈协作时才成立;换成其他 CAN stack 自行接入则不受此约束
    解码 Host 通过 decode-only 门面调用 can_decode,其编码方法不暴露给采集、诊断、固件、Web 服务与 MCP 构造并编码报文的能力 无;但若有人 fork 后改动门面,需重新审计
    社区 贡献指南明确不接受增加在车控制、刷写、写诊断或 ECU 仿真的改动 通过 PR 把写能力带进来 fork 版本不受此约束

    这四层里真正悬而未决的是第二层的物理版本落差:受保护的状态机与 Wokwi 诊断仿真器都已就位,但实体板卡的诊断发送仍处于关闭状态,要等板级的 ARM 与 fail-silent 电气测试完成。也就是说,当前 S3 与 C6 的实体发布包是采集专用(capture-only),诊断只能通过 Linux 上的 receive-only SocketCAN 之外的路径得到 仿真,不能指望在真车上读 Mode 21。

    值得把这句警告当回事:作者在文档里明确写了这不是车规产品,而是实验性研究设备。把它接上一台日常代步车之前,先读完安全边界那一章并用电表验证 silent 引脚,是唯一负责任的顺序。

    为什么自动变速箱的 DBC 是空的

    这份工具的 ZN6 DBC 定义被拆成 common / manual / automatic 三层 profile,每层显式声明它叠加哪些 DBC 文件、以及是否加载 candidate 条目。空文件是有意保留的一种状态。

    层/文件 内容 是否加载 证据状态
    zn6_gen1_common.dbc 已发布信号,基于 MIT 授权的 FT86 Gen1 map 与 RaceChrono 映射 三个 profile 共同底层 published,含测试向量
    zn6_gen1_mt.dbc 手动挡专有部分 由 MT profile 叠加加载 published
    zn6_gen1_at.dbc 自动挡专有部分 由 AT profile 叠加加载 目前为空,刻意不出表
    zn6_gen1_at_inventory.toml 仅登记存在性与标称速率,不断言任何位布局 独立引用,来源为 Toyobaru CAN ID map 6 个 ID:328/329/330 均 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz
    evidence.toml 13 条逐信号证据,含来源 URL、车型变体、观测量与测试向量 始终随定义引用 12 条 published + 1 条 candidate

    AT DBC 空着不是因为没人做,而是源于一条明确写进文档的原则:看起来合理却是编造出来的字段,比明确标注「未知」更糟。因此 include_candidates 默认 false,candidate 级别的条目(例如 ID 865 那个未经验证的三位挡位字段)不会被加载,除非显式要求。

    这套结构的直接推论是:evidence.toml 里的每一行都带车型变体限定,比如车门与尾箱的标志位分配只在右舵车上验证过、安全带只有驾驶员侧测过而乘客侧行为未知。把 published 当成「全变体通用」而不加甄别地套用,左舵车的车门信号就会错位。

    九个诊断查询的参数与限速

    诊断目录是整套工具里最容易被低估的部分:它把每个请求的预算写死了,包括超时与轮询上限,而不是靠调用方自觉。

    查询 service / 参数 解码方式 timeout / max_hz 置信度
    车速 1 / PID 13 linear_u8,offset 2,factor 1.0 250 ms / 2.0 Hz published
    发动机转速 1 / PID 12 linear_u16_be,factor 0.25 250 ms / 2.0 Hz published
    冷却液温度 1 / PID 5 linear_u8,bias −40 250 ms published
    节气门位置 1 / PID 17 linear_u8,factor 0.3921568627 250 ms / 2.0 Hz published
    控制模块电压 1 / PID 66 linear_u16_be,factor 0.001 250 ms / 1.0 Hz published
    VIN 9 / PID 2 ascii,offset 3,length 17 750 ms / 0.2 Hz published
    存储故障码 3 / 无参数 trouble_codes,offset 1 750 ms / 0.2 Hz published
    机油温度 33(Mode 21)/ PID 1 linear_u8,bias −40 400 ms / 1.0 Hz candidate,opt_in
    变速箱油温裸值 33(Mode 21)/ PID 130 raw,offset 2 400 ms / 1.0 Hz candidate,opt_in

    请求 ID 统一为 2016、响应为 2024,即 0x7E0 / 0x7E8 这一对标准 OBD 地址。真正的判别价值在中间两列:四个 PID 用 250 ms 超时、400 ms 给 Mode 21,而 VIN 与故障码给到 750 ms 并把轮询压到 0.2 Hz。这个分配隐含一个判断—— identification 类请求慢且贵,只能偶尔问;物理量类请求便宜,但也不能无上限。自己做轮询调度时,这份表是最省事的初始值。

    另外两个 Toyota Mode 21 查询都带 opt_in = true 且标记 candidate。它们的 expected_prefix 是十进制的 [97, 1] 与 [97, 130],正响应前缀落在 Mode 21 的规则内;但把 raw 类型的 ATT 温度直接做成仪表读数是不合适的,它连缩放系数都没有。

    常见问题

    这套工具能在实车上发送 CAN 帧吗?

    不能。固件跑控制器 listen-only 模式并保持收发器 silent 引脚有效,主机 CLI、Web 应用、SocketCAN 适配器、wire protocol 与 MCP server 都没有任意发送命令,且 Host 只用 can_decode 的解码面。当前 S3/C6 实体发布包是采集专用,实体诊断发送要等板级 ARM 与 fail-silent 电气测试。

    为什么自动挡的 DBC 文件是空的?

    这是一个刻意的选择。作者认为看起来合理却是编造的字段比明确标注未知更危险,因此 zn6_gen1_at_inventory.toml 只登记自动挡报文的存在性与标称速率(328/329/330 为 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz),不断言位布局;真正的信号定义要等到有可辩护的定义与测试向量再进 DBC。

    candidate 级别的信号默认会参与解码吗?

    不会。三个 profile 的 include_candidates 都是 false,Candidate 条目需要显式请求才加载。目前 evidence.toml 的 13 条里只有 1 条是 candidate——ID 865 那个未经验证的三位挡位字段,其余 12 条为 published。

    贡献一份新的信号定义需要提供什么?

    来源、车型变体、观测记录与测试向量,四项缺一不可。并且面向在车控制、刷写、写诊断或 ECU 仿真的改动明确不在接收范围内——这条贡献禁令与前述四层只读约束是一致的。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/README.md(read-first 定位、ESP32-S3/C6 与 TJA1051T/3 收发器、listen-only 与 silent 引脚、无任意发送命令、capture-only 实体发布、诊断 TX 待测试、capture 的四种输入源、Rust 1.96 与 2024 edition、MIT OR Apache-2.0)
    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/docs/definitions.md(common/manual/automatic 三层 profile、candidate 不默认加载、AT 清单仅登记存在与速率、AT DBC 保持为空的原则、Host 只用 decode-only 门面)
    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/definitions/zn6_gen1_at_inventory.toml、definitions/evidence.toml、definitions/diagnostics.toml(6 个 AT ID 与标称速率、13 条证据的置信分布、9 个诊断查询的 service、参数、解码器、timeout_ms 与 max_hz)

    免责声明

    本文所述工具行为、定义分层与诊断参数均来自公开开源仓库的说明与配置文件,属社区研究产物,未经实车独立验证,也不代表车辆制造商的官方数据。该项目自我定位为实验性研究设备而非车规产品。涉及在用车接入的操作请以官方资料与实际测量为准。

    更新记录

    • 2026-10-14 初稿

  • LiveWire S2 Del Mar:60 报文副总线与 9 个 UDS 模块

    结论:2024 LiveWire S2 Del Mar 的公开 CAN 资料给出了两件东西,用途完全不同:副总线的广播 .dbc(60 条报文、111 个信号)和一份跨 9 个诊断模块的 UDS DID 目录。转速、车速这类实时量直接从广播拿;电池单体电压、ABS 轮速、绝缘电阻这类不广播的数据,必须走 BCM 网关用 0x22 读——把它们混为一谈是初学者最常见的错。

    总线事实:先记这四条

    这份社区资料把前置条件写得非常干净,接入之前四条必须对齐。

    维度 取值 错配后果
    速率与类型 500 kbit/s,classical CAN,11 位标准 ID 按 CAN FD 或扩展帧配置时完全解不出帧
    字节序 big-endian,Motorola 起始位记作 @0 多字节信号反向拼接,数值量级明显偏大
    保护机制 约 36 个 ID 带 E2E 保护(AUTOSAR Profile-1 风格) 自定义解析时未跳过校验字节,信号整体错位
    拓扑 副总线上只有 BCM、IM、TCU、DLC;电机、BMS、ABS 在主总线 在副总线上找电机转速,永远找不到

    第三条 E2E 保护值得单独说:D7 是 6 位 alive counter,D8 是覆盖 D1 到 D7 的 CRC-8 / SAE-J1850(多项式 0x1D,初值与异或输出均为 0xFF)。它的价值不在于安全,而在于充当解码预言机——位对齐一旦算错,CRC 立即失败,不需要等到物理量不合理才发现问题。这是逆向过程中极少数可以机器判定对错的抓手。

    九个模块各管什么

    副总线的广播成员是 BCM(网关)、IM(仪表)、TCU、DLC 四个,其余全部在主总线上,通过 BCM 网关用 ISO-TP 上的 0x22 ReadDataByIdentifier 读取。下面这张表是挑选 UDS 模块时的直接依据。

    模块 请求与响应 ID 角色 能拿到的关键数据
    BCM 0x7E2 → 0x7EA 车身控制器,副总线网关 纵向加速度 ADC 快照、内部 mV 电源轨、时间同步、骑行模式配置表、防盗与钥匙块
    VSC 0x7E4 → 0x7EC 车辆监控控制器,监管 ABS 与 IMU 实时电机转速与驱动状态、扭矩记录、油门位置、电池包端电压、当前骑行模式序号及逐模式标定三元组
    RESS 0x7E6 → 0x7EE 高压电池管理,信息价值最高的模块 逐单体电压阵列、逐单体温度阵列、包电流双传感 A/B、SoC/SoE/SoH、累计安时
    EHCU 0x7E7 → 0x7EF Bosch ABS 液压单元 双路逐轮轮速、前制动压力、制动激活标志、12 V 辅助电源轨、ABS 事件计数器
    OBC / HV 0x7D3 → 0x7DB 车载充电机,交流充电时才活跃 充电器与枪状态、充电电流与功率、充电机散热片温度、母线电压
    TCU 0x7D4 → 0x7DC 远程通信,含 eSIM 与 GPS,隐私敏感 GPS 位置、信号强度、归属网络、固件版本

    表里没有列的还有 LHCM(0x7E3,识别信息与硬件件号,同时携带 VIN)、RHCM(0x7E5,制动激活标志与内部参考电源轨)、以及一个 ID-only ECU(0x7F0 → 0x7F8,只有供应商件号、没有任何实时数据块,属于硬上限)。

    需要注意的是,9 个已映射响应者是下限而不是总数。资料明确提到存在一个未映射的响应方(响应 0x6E6 / 请求 0x6DE)被被动观察到,另有目标地址 0x7F2;并且 IMU 本身没有 UDS 地址,它由 VSC 监管。这意味着你在总线上看到的地址比这张表多,是预期行为。

    读懂它的置信度标注

    这份资料最值得模仿的不是结论,而是它把不确定性强塞进数据结构里:每条信号的行内注释都带四类信息——置信度、标定依据、已撤回的假设与尚未解决的疑问。[CONFIRMED](两种以上方式交叉验证)、[STRONG](一次干净抓包且物理一致)、[TENTATIVE](数据不足)。已撤回的假设会原样保留而不是删除,避免后来者重复尝试同一条死路。

    这套标注的实际用法:写解析代码时,只对 [CONFIRMED] 与 [STRONG] 做断言和告警,[TENTATIVE] 一律只记录不做判断。把三级标注 flatten 成一个 schema,等于把作者的证据强度信息彻底丢弃。

    它的取证方法也相当严格:单人单次动作隔离抓包 + 差分分析;一次相关只构成假设,必须有第二次「专门设计来推翻它」的抓包失败才算成立;未被动作覆盖的字节标记为未解,而不是当作常量写死。这套流程解释了为什么 111 个信号里真正能用作线上判据的比例并不高——大量位置至今没有足够证据。

    三条使用边界

    第一,0x27 SecurityAccess 门禁:BCM、VSC、TCU 上有 16 个 DID 被上锁,种子为 128 位随机数,其内容是按相邻关系推测的,不是读出来的。任何把推测值当成实测值的下游都会出错。第二,隐私:车主 PII 在这份公开副本中被抽掉,VIN、模块序列号、GPS 坐标与 SIM 标识都变成占位符,但结构完整,复现时必须自己填自己的值。第三,版本状态:整体标注为 v0.1 进行中,TENTATIVE 条目可能错误或不完整;并且它只描述如何读取与理解总线,不含任何执行动作的方法。

    常见问题

    电机转速和电池单体电压能不能直接从副总线广播里读?

    不能。副总线上的广播成员只有 BCM、IM、TCU、DLC 四个,电机/逆变器、电池、ABS、充电机、远程通信都在主总线上,需要通过 BCM 网关用 ISO-TP 上的 0x22 ReadDataByIdentifier 主动读取。能直接广播读到的只有广播成员的那些信号。

    E2E 的 CRC 除了校验还有什么用?

    它是逆向时的位对齐预言机。约 36 个 ID 采用 AUTOSAR Profile-1 风格保护,D7 为 6 位 alive counter,D8 为覆盖 D1 到 D7 的 CRC-8 / SAE-J1850,多项式 0x1D、初值与异或输出 0xFF。只要起始位或长度算错,CRC 立即失败,可以在物理量失真之前发现错位。

    已映射的 9 个模块是不是这辆车的全部 ECU?

    不是,作者明确写这是一个下限。被动观察到的还有一个未映射响应方(响应 0x6E6、请求 0x6DE)以及目标地址 0x7F2;IMU 没有自己的 UDS 地址,由 VSC 监管。也就是说实际地址数会多于这 9 个。

    为什么有些 DID 的内容看起来是「猜」出来的?

    因为 BCM、VSC、TCU 上有 16 个 DID 被 0x27 SecurityAccess 上锁,种子是 128 位随机数,作者无法读取其值,只能按相邻关系推测其含义。使用这类字段时必须标注为推测值,不能参与任何判定逻辑。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/inklit-livewire-s2-delmar/README.md(500 kbit/s、11 位 ID、Motorola @0、约 36 个 ID 的 E2E 与 CRC-8 参数、60 报文 111 信号、9 个 UDS 模块、CONFIRMED/STRONG/TENTATIVE 标注体系、取证方法论、CC BY 4.0 授权)
    • 项目 01 —— public-can-dbc-datasets/additional/inklit-livewire-s2-delmar/MODULES.md(九个诊断模块的请求与响应 ID、角色与关键数据;9 为下限的说明、0x27 上锁 16 个 DID、IMU 无 UDS 地址、PII 抽除说明)

    免责声明

    本文所述总线参数、模块地址与信号数量均来自社区公开整理的说明文件,属第三方逆向工程产物,未独立实车验证,也不代表 LiveWire 或任何制造商的官方数据。不同年份、市场与固件版本的 ECU 可能存在差异。涉及 0x27 安全访问的字段为作者推测值。任何改动请以实际测量与官方资料为准,操作在用车存在风险。

    更新记录

    • 2026-10-14 初稿

  • KTM TBI mapswitch:31 条 BO_ 里只有 4 条真实帧

    结论:这份 KTM TBI mapswitch 的 DBC 有 31 条 BO_ 报文与 36 条 SG_ 信号,但其中只有 0x6DA、0x6DB、0x4C0、0x4C1 四条是真正的 CAN 广播或地图按键 / 命令帧;其余 27 条把 UDS 的 DID、IOID、RID 当作伪 CAN ID,用来描述响应载荷。配套的车型矩阵则把 TBI(2024 年起)与两代 TPI 的 27 项能力分成三档。

    31 条报文里只有 4 条是真实总线帧

    这是使用这份 DBC 前必须先看清的一点。归档说明按文件自身的头部描述作了分类:只有四条条目属于 CAN 广播或地图按键 / 命令流量,其余 27 条用的是 UDS 诊断标识符(DID、IOID、RID)充当伪 CAN ID,目的是描述请求之后的响应数据结构。

    条目性质 数量 标识示例 能不能当总线报文监听
    真实 CAN 广播或按键 / 命令帧 4 0x6DA、0x6DB、0x4C0、0x4C1 能,可直接按 ID 过滤与解析
    UDS DID / IOID / RID 伪 ID 27 文件头声明为响应载荷描述 不能,需先发起请求再解析响应

    UDS 传输层本身使用请求 0x7E0、响应 0x7E8。也就是说,那 27 条「报文」在总线上并不会以该 ID 出现;把它们当普通帧去过滤,结果必然是永远收不到。正确用法是先按 0x7E0 发诊断请求,再按 DBC 里对应伪 ID 的定义去解 0x7E8 回来的载荷。

    另外两个兼容性问题也要提前处理:部分伪报文声明的载荷长度超过 8 字节(其中包含 96 字节的条目),而源文件带有 // 注释——严格的 DBC 解析器可能需要预处理才能读入。

    三代车型的 27 项能力分档

    项目面向 KTM、Husqvarna 与 GasGas 三个品牌的摩托车,车型矩阵把能力分成「骑行模式」与「诊断」两大组,横跨 TBI(2024 年起)、TPI(2020–2023)、TPI(2018–2019)三代。这份 DBC 明确以 KTM TBI 的 ECU 命名,来源并未为每个定义确立具体车型、排量或固件版本。

    能力 TBI(2024+) TPI(2020–2023) TPI(2018–2019)
    按键切换地图 支持 不支持 不支持
    按键清除 ECU 故障 支持 支持 支持
    RaceChrono 遥测 支持 支持 支持
    显示当前地图 支持 支持 不支持
    按模式统计摩托小时(油门、转速) 支持 不支持 不支持
    动力阀开度百分比 支持 不支持 不支持
    大气压力(MAP,大气) 支持 支持 不支持
    TPS 电压与开启角度 支持 不支持 不支持
    TPS 开启百分比 不支持 支持 支持
    运输锁状态 / 翻车传感器 / 机油泵回路 支持 不支持 不支持

    把这张表读成决策依据,可以归纳出三条:第一,按键切换地图是 TBI 独有能力,两代 TPI 都做不到;第二,TBI 独有项共 8 项(按键切地图、按模式小时计、动力阀开度、TPS 电压、TPS 角度、运输锁、翻车传感器、机油泵回路),这些是 TBI 平台新增诊断能力的全部;第三,TPI 2018–2019 相比 2020–2023 只少了显示当前地图与大气压力两项。

    还有一处反向差异值得注意:TPS 的表示方式在三代之间不兼容——TBI 给电压与角度,两代 TPI 只给百分比。做跨代统一解析时,TPS 必须按代分别处理。

    三档之外,按键清除故障、冷机指示、过热指示、保养间隔指示、故障灯指示、RaceChrono 遥测、总摩托小时、发动机转速、水温、进气温度、进气压力、点火提前角、电池电压、读取当前与存储故障、清除故障这些项目在三代上全部支持,可以视为这套装置的能力基线。

    把分档结果与项目命名放在一起看,能得出一条实用的选型判断:这套装置以 KTM TBI 命名,而矩阵显示按键切换地图仅在 TBI(2024 年起)这一档可用,两代 TPI 均不支持。因此面对 TPI 车型时,可用能力退化到上述基线加上显示当前地图(仅 2020–2023)、大气压力(仅 2020–2023)与 TPS 百分比,不能照搬 TBI 的功能清单。

    常见问题

    31 条 BO_ 里有多少是真实的总线报文?

    只有 4 条,即 0x6DA、0x6DB、0x4C0 与 0x4C1,属于 CAN 广播或地图按键 / 命令流量。其余 27 条按文件头的声明,是用 UDS 的 DID、IOID、RID 值充当伪 CAN ID 来描述响应载荷,总线上并不会以这些 ID 出现。

    UDS 请求与响应用的是什么 CAN ID?

    请求为 0x7E0、响应为 0x7E8。那 27 条伪 ID 报文描述的正是响应里的数据结构,因此正确流程是先向 0x7E0 发起诊断请求,再按 DBC 中对应伪 ID 的定义解析 0x7E8 返回的内容,而不是直接按伪 ID 去过滤总线。

    TPI 2018–2019 相比 2020–2023 少了什么?

    在 27 项能力矩阵里只少两项:显示当前地图与大气压力(MAP,大气)。其余项目中,按键清除故障、冷机与过热指示、保养间隔、故障灯、RaceChrono 遥测、总小时、转速、水温、进气温度、进气压力、点火提前角、电池电压、TPS 百分比、故障读取与清除等在这两代上均为支持。

    为什么这份 DBC 在严格的解析器里可能报错?

    有两个原因。一是部分伪报文声明的载荷长度超过 8 字节,其中包含 96 字节的条目,超出经典 CAN 单帧能力;二是源文件带有 // 注释。因此严格的 DBC 解析器可能需要先做预处理(剥离注释、处理超长载荷)才能读入。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/psamoilov-ktm-tbi-mapswitch/SOURCE.md(31 条 BO_ 与 36 条 SG_、4 条真实帧与 27 条伪 ID、UDS 0x7E0/0x7E8、超长载荷与注释问题、权利状态)
    • 项目 01 —— public-can-dbc-datasets/additional/psamoilov-ktm-tbi-mapswitch/models.md(TBI 2024+ 与两代 TPI 的 27 项能力矩阵)

    免责声明

    本文内容整理自公开开源项目,属社区逆向工程产物,不代表 KTM、Husqvarna 或 GasGas 的官方数据。来源未为每个定义确立具体车型、排量或固件版本,信号与车型适配未经独立抓包验证。检查的目录树中未找到仓库许可证或逐文件的再分发授权,相关材料应作为私有离线研究副本,在权利确认前不得再分发或集成。

    更新记录

    • 2026-10-14 初稿

  • Honda CL250 诊断档案:5 个 DID 与 UDS 轮询

    结论:这份 Honda CL250(摩托车)档案的一个关键事实是:源文档目前没有已知的 CL250 广播报文——它的 cl250.dbc 是零报文、零信号的骨架。可用的数据来自主动 UDS 轮询 5 个 DID:转速、车速、节气门绝对位置、冷却液温度与电池电压,经 ISO 15765-2 单帧传输,主寻址是 29 位 0x18DA10F1(ECU 地址 0x10、测试仪 0xF1),回退到 11 位 0x7E0/0x7E8。工程约束也被写得很细:单请求在飞、基础超时 100 ms、响应挂起(NRC 0x78)翻倍超时、连续 5 次超时跳过该 DID 5 秒。下述内容仅限源文档记录的这一套定义。

    车辆与适用范围

    源文档来自一个摩托车车载平台项目,它把 CL250 的 ECU 定义与一张项目自建 CAN 分开管理。定义文件说明每个数值都从一份旧固件项目提取,而该旧固件自述「已在真实摩托车上验证过 CAN/UDS 通路」;但来源说明同时指出,那份被引用的仓库在核对时已无法公开访问,没有原始抓包被独立检查过,且部分轮询周期与 11 位回退寻址在源文档里明确标注为未验证。

    项 内容
    车型 Honda CL250(摩托车),ECU 记为 CL250_ECU
    年款 / 市场版本 源文档未给出年款与市场版本
    ECU / 改装状态 原厂 ECU;读取侧是一个测试仪节点(rt-core 或连接节点),只读轮询
    采集跨度 源文档未给出日志数;数值来源为一份旧固件项目的提取
    适用范围 仅限本套定义;被引用的旧固件仓库核对时不可公开访问,原始抓包未独立检查

    总线与寻址

    源文档把总线参数标为「已验证」的是经典 CAN 500 kbit/s;主寻址与回退寻址分开列出,并明确回退寻址「ECU 实际应答哪一个未被记录」。此外还列了两个只监视(watch-only)的功能地址,用于探测是否存在第二个测试仪。

    项 内容
    物理层 双绞线 CAN;经典 CAN(classic_can)
    链路层 / 比特率 500 kbit/s(源文档标 verified)
    主寻址 29 位固定寻址:请求 0x18DA10F1、响应 0x18DAF110;ECU 地址 0x10、测试仪 0xF1
    回退寻址 11 位:请求 0x7E0、响应 0x7E8;标为未验证(未记录 ECU 应答哪个)
    只监视地址 功能地址 0x7DF 与 0x18DB33F1,只看不发
    传输层 ISO 15765-2;帧 DLC=8;补齐字节 0xAA;旧固件只处理单帧

    已解码信号

    下表登记 5 个 DID 的解码,以及关键的服务与会话定义。DID 的公式与「已验证」标记按源文档原样保留;轮询周期一行给出旧固件值与平台建议值,并保留「平台值为暂定」的标注。

    信号 / 项目 位置(DID / 命令) 解码 / 说明 证据 / 置信度
    转速 ENGINE_SPEED DID 0xF40C(OBD PID 0x0C) (A×256 + B) / 4 → rpm,量程 0–16383.75 源文档标 verified;旧固件轮询 50 ms,平台建议 110 ms(暂定)
    车速 VEHICLE_SPEED DID 0xF40D(PID 0x0D) A → km/h,量程 0–255 标 verified;优先级 high;平台建议 110 ms(暂定),新鲜度 300 ms
    节气门绝对位置 THROTTLE_POS DID 0xF411(PID 0x11) A × 100 / 255 → %,量程 0–100 标 verified;平台建议 200 ms(暂定)
    冷却液温度 COOLANT_TEMP DID 0xF405(PID 0x05) A − 40 → °C,量程 −40–215 标 verified;平台建议 800 ms
    电池电压 BATTERY_VOLTAGE DID 0xF442(PID 0x42) (A×256 + B) / 1000 → V,量程 0–65.535 标 verified;旧固件的 A/10 启发式未沿用
    诊断会话 请求 0x10 0x03 → 正响应 0x50 扩展会话;未确认前每 2000 ms 重试 标 verified
    TesterPresent 0x3E 0x80 每 1000 ms 无条件发送(抑制正响应) 标 verified
    允许的服务白名单 0x10/0x3E/0x22/0x19/0x01/0x09 只读与会话类;禁止 0x11/0x14/0x27/0x2E/0x2F/0x31/0x34/0x36/0x37,并禁止 0x10 子功能 0x02 平台策略(D-020)
    功能地址监视 0x7DF、0x18DB33F1 只看不发;看到帧即说明存在第二个测试仪 标未验证(标准值,非取自旧固件)
    项目自建总线转发 dbc/platform.dbc 9 条报文、52 条信号;把轮询到的值再发布出去,不是 OEM Honda 库 来源说明

    读取方法与注意事项

    第一是时序预算。源文档记录:同时只有一个请求在飞(IDLE → WAITING → 完成/超时 → IDLE);基础超时 100 ms;收到 NRC 0x78(响应挂起)时重置并把超时翻倍、上限 2000 ms,且请求仍留在等待态;其它 NRC 则把请求判为完成。连续 5 次超时的 DID 会被跳过 5000 ms。ECU 只要在最近 3000 ms 内有过正响应或任何 NRC,就视为「在线」。

    第二是优先级。DID 被分成 high / normal 两类,在同时到期的请求里先服务所有 high(本例中车速为 high,因为它喂给上游的航向估计),列表顺序只作同类内的平局判定。源文档强调优先级只改顺序、不改内容,且每个到期 DID 仍须在其新鲜度窗口内被服务。

    第三是 ISO-TP 首帧陷阱。旧固件只处理单帧(PCI 高半字节 0x0);若收到首帧(PCI 0x1X),其 data[1] 是长度字段的一部分、不是 SID,按 SID 解析会破坏状态。旧固件直接丢弃非单帧帧;由于当前所有 DID 都能放进单帧,这只防未来响应变长。源文档据此写明:完整的 ISO-TP 多帧(首帧 + 流控 + 连续帧)需在新实现里从头做。

    第四是总线恢复。进入总线关闭后按指数退避重试:起始 1000 ms、每次翻倍、上限 30000 ms。

    证据等级与边界

    可视为「文档级已验证」的是 5 个 DID 的公式与主寻址,以及会话/超时/退避这些时序常量——它们都带证据引用。属于明确未验证的是:11 位回退寻址(未记录 ECU 应答哪个)、功能地址监视(标准值,非取自旧固件)、以及平台的轮询周期(源文档标注为暂定,与旧固件周期不同)。

    两处不能外推。第一,公式与 DID 只针对 CL250 这一辆车的 ECU 定义;换到其它 Honda 车型需要重新核对。第二,来源说明指出被引用的旧固件仓库在核对时已无法公开访问,原始抓包未被独立检查,因此「已在该车验证」属于源文档的转述,不是本项目的独立复现。

    关于「安全访问」类问题:源文档把 0x27(SecurityAccess)列为禁止服务,且未提供任何绕过方法,不建议尝试;本文只整理公开文档登记的只读轮询,不涉及写 ECU 或绕过安全机制。

    常见问题

    CL250 的报文能不能直接从总线上监听?

    源文档表示目前没有已知的 CL250 广播报文,cl250.dbc 是零报文、零信号的骨架;可用的数据来自主动 UDS 轮询 5 个 DID。

    轮询哪 5 个值?周期是多少?

    转速(0xF40C)、车速(0xF40D)、节气门绝对位置(0xF411)、冷却液温度(0xF405)、电池电压(0xF442)。旧固件周期为转速 50 ms、其余 800 ms;平台建议值为 110/110/200/800/800 ms,并标注为暂定。

    超时和响应挂起怎么处理?

    基础超时 100 ms;收到 NRC 0x78 时重置并把超时翻倍、上限 2000 ms,请求保持等待;其它 NRC 判为完成;连续 5 次超时的 DID 跳过 5000 ms。

    用 11 位还是 29 位地址?

    主寻址是 29 位 0x18DA10F1(响应 0x18DAF110);11 位 0x7E0/0x7E8 是回退,源文档标注为未验证——未记录 ECU 实际应答哪一个。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/moto-platform-cl250/docs/legacy-telemetry-notes.md(主来源:UDS 状态机、NRC 表、总线恢复与 ISO-TP 陷阱)。
    • 项目 01 —— public-can-dbc-datasets/additional/moto-platform-cl250/uds/vehicle_cl250.yaml(DID 定义、寻址、会话与轮询时序)。
    • 项目 01 —— public-can-dbc-datasets/additional/moto-platform-cl250/README.md(项目结构、平台总线与 CL250 骨架的区分)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Honda 车型接口:能力参数、雷达静默与恢复边界

    结论:Honda 车型接口把「能力参数」和「能力兑现」分得很清楚:openpilotLongitudinalControl、ControlsReady 与 tester-present 候选都只是软件侧的请求或标记,不是 ECU 行为的回执。雷达静默依赖 disable_ecu(),而它对通信控制请求传入空预期响应前缀、随后无条件打印「ecu disabled」并返回 True,因此至多证明会话得到匹配应答且后续查询没抛异常,不能证明 ECU 已停止发送。没有闭环证据时应保持 noOutput 或只读。

    关键函数与组件

    基线是本地 source/ 归档提交 c8fb906,只分析 Honda interface.py、通用诊断函数及 card/pandad 交接;不代表任何具体年款的线束、ECU 响应或原车 AEB 行为已验证。

    入口 职责
    CarInterfaceBase.get_params() 从平台规格建立基础 CarParams,再交给 Honda _get_params() 补齐能力与参数。
    CarInterface._get_params() 选择 Bosch/Nidec 安全模式、纵向策略、指纹能力、调校和安全参数。
    get_pid_accel_limits() Bosch 给定静态加速度范围;Nidec 的最大值靠近巡航设定速度时下降。
    init() / deinit() 有雷达 Bosch 自控纵向的 UDS 通信控制请求与恢复请求。
    disable_ecu() 扩展会话重试、通信控制发送及布尔结果;注释明确警告禁用原车 AEB。
    IsoTpParallelQuery.get_data() 按预期响应前缀收集结果;空前缀不会验证通信控制的具体正响应码。

    能力与安全配置

    get_params() 先装载车型平台的质量、轴距、转向比和静态 flags,再调用 Honda _get_params()。Bosch 设置 hondaBosch、radarUnavailable=True;alphaLongitudinalAvailable 对 Bosch CAN FD 为假,openpilotLongitudinalControl 还取决于启动时传入的 alpha_long。它们是软件能力/选择位,不等于雷达实际静默。Bosch CAN FD 且 PT 总线编号至少 4 时,安全配置列表前插 noOutput,但并非所有 CAN FD 都无输出。

    Nidec 选择 hondaNidec,同时设置 openpilotLongitudinalControl=True 和 pcmCruise=True,因此不能用 pcmCruise 单独推断执行权由原车 ACC 完全负责。指纹分支检测特定 CR-V BSM 标志、扩展 HUD、混动标志、自动/CVT/手动变速箱以及备用制动帧;EPS 固件版本含逗号时设 dashcamOnly。若 card 判定控制器不可用、用户关闭开关或 dashcamOnly,它会把整组安全配置替换为 noOutput 并标记 passive。

    能力位/标记 含义与边界
    openpilotLongitudinalControl 取决于启动时 alpha_long,是软件选择位,不等于雷达已静默。
    pcmCruise Nidec 同时置真,不能单独推断执行权归属。
    safetyParam 对备用制动、Nidec SCM 变体、Bosch 自控纵向、radarless 和 CAN FD 按位编码;固件还需依自身编译门与白名单解释这些位。
    ControlsReady card 在初始化门满足时立即写,不验证雷达静默结果。

    特别地,Bosch 自控纵向在固件里受 ALLOW_DEBUG 条件编译约束,Python 参数置位本身不足以证明固件允许该模式。此外,多数车型设置 PID 横向参数,部分车型走通用扭矩调校;三处分支直接改写 CarControllerParams.BOSCH_GAS_LOOKUP_V 类属性,不是写入本次 ret 或控制器实例,且函数内没有恢复默认值——同一进程先构建某一车型参数、再构建另一车型时,后者可能继承前者的查表值。

    禁用、保活与恢复链

    只有 BOSCH、非 BOSCH_RADARLESS 且 openpilotLongitudinalControl 时,CarInterface.init() 才调用 disable_ecu(),目标是固定的诊断目标地址与 PT 总线。它先尝试 UDS 扩展会话并要求匹配应答;随后发通信控制请求,子功能带 suppress-response 位。disable_ecu() 对后一步传入空的预期响应前缀并调用 get_data(0),然后无条件打印「ecu disabled」并返回 True。所以它至多证明前一步会话得到匹配应答且后一步查询没有抛出异常,不能证明 ECU 已停止发送;Honda init() 又没有返回该布尔值。

    card 首次满足初始化门时调用 CI.init(),紧接着写 ControlsReady=True,没有验证雷达静默结果。pandad 在 FirmwareQueryDone 和 ControlsReady 都为真后读取参数、设置安全模式;这两项参数并非 ECU 行为回执。保持发送候选、MCU 接受、ECU 收到以及 ECU 持续静默是四个不同事实。

    CarInterface.deinit() 用通信控制「启用 RX/TX」请求复用 init() 路径,仍不检查恢复应答。当前主 card 运行链只见 init() 调用,未见对 Honda deinit() 的调用;进程退出或异常时不能由这个函数的存在推断原车雷达/AEB 已恢复。恢复行为是否由 ECU 会话超时、断电或其他机制完成,必须在目标车型台架和受控场地验证。

    插件与硬件验收

    将「雷达静默」设计成受信任诊断服务持有的事务能力:记录目标 ECU、物理总线、请求、正/负响应、发送持续性、实际雷达报文消失与恢复证据,并把原车 AEB/FCW 影响作为显式安全决策。没有闭环证据时保持 noOutput 或只读,不能让车型插件以 openpilotLongitudinalControl、ControlsReady 或 tester-present 候选代替验收。多车型参数生成必须隔离/冻结 BOSCH_GAS_LOOKUP_V 等调校状态;至少测试 Civic Bosch、Odyssey MMR、RDX MMR 与普通 Bosch 的不同构建顺序。

    常见问题

    disable_ecu() 返回 True 就代表雷达被禁用了吗?

    不代表。disable_ecu() 对通信控制请求传入空的预期响应前缀并调用 get_data(0),然后无条件打印「ecu disabled」并返回 True。源码说明它至多证明前一步扩展会话得到匹配应答且后一步查询没有抛出异常,不能证明 ECU 已停止发送;Honda init() 也没有返回该布尔值。

    pcmCruise 为真表示减速完全由原车负责吗?

    不能这样推断。Nidec 选择 hondaNidec 时同时设置 openpilotLongitudinalControl=True 和 pcmCruise=True,源码因此明确指出不能用 pcmCruise 单独推断执行权由原车 ACC 完全负责。

    BOSCH_GAS_LOOKUP_V 为什么会有跨车型风险?

    因为部分调校分支直接改写 CarControllerParams.BOSCH_GAS_LOOKUP_V 类属性,不是写入本次 ret 或控制器实例,且函数内没有恢复默认值。源码可推断:同一 Python 进程先构建某一车型参数、再构建另一车型时,后者可能继承前者的查表值。这需用 Civic Bosch、Odyssey MMR、RDX MMR 等不同构建顺序验证。

    进程退出后原车雷达/AEB 会自动恢复吗?

    不能由源码推断。deinit() 用通信控制「启用 RX/TX」请求复用 init() 路径、仍不检查恢复应答,而当前主 card 运行链只见 init() 调用、未见 Honda deinit() 调用。恢复行为是否由 ECU 会话超时、断电或其他机制完成,必须在目标车型台架和受控场地验证。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HONDA_INTERFACE_CAPABILITY_RADAR_LIFECYCLE_DEEP_DIVE.md(取用了 Honda 接口函数表、能力与安全配置、禁用/保活/恢复链、插件与硬件验收要求)。
    • 项目 02 —— openpilot-research/HONDA_CARSTATE_SPEED_BRAKE_CRUISE_INPUT_DEEP_DIVE.md(仅用于确认 Honda 输入状态专题的接续关系,未取用其未公开内容)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • 菲亚特 Grande Punto:29 位 UDS 与 105 个 DID 的读取边界

    结论:在一辆南非市场的菲亚特 Grande Punto(平台 199)1.4 8V(发动机 350A1000,Magneti Marelli IAW 5SF9 发动机 ECU)上,诊断走 29 位标识符、500 kbps 的 C-CAN,应用层是 UDS(ISO 14229),传输层是 ISO 15765-2,采用常规固定寻址(请求 18DAxxF1、应答 18DAF1xx)。这台车最关键的一条工程特性是:发动机 ECU 只接受不填充的帧,数据长度必须等于真实长度,这正是自动协议搜索与多数通用 OBD 应用连不上的原因;标准 OBD-II(模式 01 至 0A)也不应答,属非 EOBD 合规。边界:全部结论出自这一辆车与这份只读研究,不能套到其他校准或车型。

    本文整理自该项目的协议文档与示例结果。文档把每条记录分为「Observed(本车读出)」与「Published(取自公开来源、未在本车确认)」,本文保留这一区分。

    车辆与适用范围

    数据来自一位研究者的这一辆 Grande Punto,用一款 ELM327 兼容蓝牙适配器加一台 Linux 主机接入。工作方式偏保守:先适配器自身,再被动监听,然后标准请求,最后才是有寻址的厂家请求;并且全程只读,不发送清除、写入、执行器测试、安全访问或编程会话。

    项 内容
    车型 菲亚特 Grande Punto(平台 199)1.4 8V,发动机 350A1000,南非市场
    年款 / 市场版本 源文档未给出具体年款;市场为南非
    ECU / 改装状态 发动机 ECU:Magneti Marelli IAW 5SF9,名称 5SF9AG,硬件 IAW5SFHW405,软件 881AW23E,Fiat 件号 51926690
    采集跨度 若干次只读会话;一次怠速分析含 6 段共 5995 帧
    适用范围 仅这一辆车与这一套校准;不得假设其他校准或车型相同

    总线与寻址

    物理层是 OBD 引脚 6 / 14 上的 C-CAN,500 kbps,29 位标识符;传输层为 ISO 15765-2 常规固定寻址(请求 18DA + 目标 + F1,应答 18DAF1 + 目标)。本车一大特性是不能填充,数据长度须等于真实长度;流控帧为三字节 30 00 00,须在首帧后数毫秒内跟上。

    项 内容
    物理层 C-CAN,OBD 引脚 6 / 14,500 kbps
    链路层 29 位标识符;ISO 15765-2(ISO-TP)常规固定寻址
    寻址 请求 18DA + 目标 + F1;应答 18DAF1 + 目标
    帧填充 发动机 ECU 不接受填充,数据长度须等于真实长度
    流控 30 00 00 三字节,须在首帧后数毫秒内
    应用协议 UDS(ISO 14229);标准 OBD-II 模式 01 至 0A 不应答

    已解码信号

    下表混合数据标识符(DID)与广播帧字段两类。证据一列沿用文档口径:「本车读出」为在本车实测,「公开来源」为取自 Fiat 500 等同平台资料、未在本车独立确认。文档还提示:公开定义里发动机转速位偏移比本车实际晚一个字节,公开偏移应视为起点。

    信号 位置(DID / 帧) 解码 证据
    发动机转速 DID 1000 原始值 ÷ 4,转/分 本车读出;与广播 0618A001 交叉核对
    冷却液温度 DID 1003 原始值 − 40,摄氏度 跟随广播 0A18A001 字节 3;偏移为假设
    电池电压 DID 1004 原始值 ÷ 10,伏 本车读出;与适配器电压表一致
    运行计数 DID 1008 运行时约每分钟 +1,可能是分钟计 本车读出
    启动后计时 DID 1009 约每 15 秒 +1,单位未知 本车读出(刚启动后读数为 1)
    目标怠速 DID 186B 原始值 ÷ 4,转/分(700;开空调 850) 本车读出;转速 1000 随后一拍跟随
    大气压 DID 1956 毫巴 可能(静止且数值符合海拔)
    进气歧管压力 DID 181F 毫巴 可能(随负荷变化)
    电池电压(第二路) DID 197D、197E 原始值 ÷ 10,伏 本车读出;与 1004 一致
    氧传感器电压 DID 1898、189A 毫伏(在稀 / 浓之间摆动) 可能
    发动机转速(广播) 帧 0618A001 字节 2-3(大端) 1 转/分/位;字节 7 为油门踏板 转速与 1000 一致;踏板为公开来源
    冷却液温度(广播) 帧 0A18A001 字节 3 原始值 − 40,摄氏度 跟随 1003;比例为公开来源
    节气门位置(广播) 帧 0628A001 字节 4 怠速时 4 至 7 个计数 公开来源
    备件号 DID F187 文本 51926690 本车读出

    读取方法与注意事项

    先做被动监听。先静默监听确认总线活着,再用最简请求(TesterPresent)扫地址。这台车上,3E 00 得到干净的 7E 00,证明它讲 UDS;而 1A 80 得到 7F 1A 11(服务不支持),说明它不讲 KWP2000。否定应答也是成功,因为它证明寻址与帧格式是对的。

    不填充与流控交给适配器。关键一步是关闭格式化(ATCAF0)并启用可变数据长度(ATV1),由自己写 ISO-TP 长度字节。长应答以首帧发出后需流控;经蓝牙往返太慢时发动机 ECU 会放弃,故让适配器自行发送三字节流控。

    读取成本要知道。一次遍历 105 个标识符约需 14.4 秒,因此比这更快的信号都会被欠采样;模块地址扫描(256 个)约 54 秒,整个 16 位空间约需 3.6 小时。

    只读边界。文档强调这是只读研究:写入、清除、例行程序、安全访问与复位服务从未发送。本文同样不涉及安全访问绕过;源文档未提供此类方法,也不建议尝试。

    证据等级与边界

    文档用「Observed」标记本车读出,用「Published」标记取自 Fiat 500 等同平台资料、未在本车独立确认的内容。因此表中带「公开来源」「可能」「假设」字样的条目尚未在本车成立。

    识别侧证据较硬:F187 备件号、F192 供应商硬件号、F194 供应商软件号、F196 ECU 名称都能读出;发动机 ECU 的 VIN 字段(F190)为空,VIN 由地址 40 的车身电脑返回。应答模块只有四个:10 发动机、28 ABS、30 电动助力转向、40 车身电脑,其余全静默。

    来源说明把范围写得很清楚:只有这一辆南非市场的 Grande Punto 1.4 8V,不要假设其他校准或车型布局相同;这是「诊断 / 信号研究集合,而非 DBC」。据此,本文的 DID 含义、比例与广播偏移不能外推到其他 Grande Punto 或其他 Fiat 车型。

    常见问题

    为什么通用 OBD-II 读不到这台车?

    因为这台发动机 ECU 非 EOBD 合规,标准 OBD-II 模式 01 至 0A 在任何协议上都不应答;加上它只接受不填充的帧,自动协议搜索与多数通用应用都会失败。作者改用 29 位寻址加不填充帧后才得到首个应答(还是否定的 7F 1A 11)。

    为什么这台车要求帧不填充?

    文档实测:发动机 ECU 只接受数据长度等于真实长度的帧,填充帧得不到应答。ISO 15765 允许填充,多数 ECU 两种都收,但这台不收——文档指出,正是这一个细节让自动检测与通用应用全部失败。

    用服务 22 读 DID 需要先进入扩展会话吗?

    不需要。文档记录 22 xxxx(ReadDataByIdentifier)在默认会话即可工作,且进入扩展会话(10 03)并未解锁测试范围内的额外标识符。

    为什么用掩码 FF 读故障码会返回 27 条?

    因为掩码 FF 返回的是 ECU 能够 设置的记录、状态为 40(本周期未完成测试),那是监控项清单而非故障清单。文档建议用具体掩码:08 读已确认、04 读待定、01 读当前正在发生。

    这些 DID 能套到别的 Grande Punto 吗?

    不能。来源说明写明只有这一辆南非市场的 1.4 8V 车,且这是一个研究集合而非 DBC;不同校准或车型的布局可能不同,需逐车复核。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/ryancoxrbc-fiat-grande-punto/docs/protocol.md(本项目车型档案主来源,取用了物理层 / 传输层、DID 表与广播帧表)。
    • 项目 01 —— public-can-dbc-datasets/additional/ryancoxrbc-fiat-grande-punto/docs/example-results.md(取用了怠速捕获统计与读取耗时)。
    • 项目 01 —— public-can-dbc-datasets/additional/ryancoxrbc-fiat-grande-punto/SOURCE.md(取用了「仅此一辆车、研究集合而非 DBC」的边界说明)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • BMW E46 PT-CAN 数据档案:MS42/MS43 的 500 kbps 报文表

    结论:BMW E46 的 PT-CAN 是一张没有加密、没有网关隔离的广播总线:500 kbps、11 位 ID、DLC=8,DME、DSC、IKE、转向角传感器和(选装)变速箱都在这张网上直接广播,被动监听即可解码转速、水温、车速、四轮速、转向角、制动压力、挡位、里程与油量等信号。它的典型难点不在「能不能抓」,而在同一份 ID 在 MS42(M52TU)与 MS43(M54)上字节位置不同:源文档明确标注 MS42 的字节位置是从 MS43 文档抄来的、仍需真实抓包验证。下述结论仅限源文档记录的这一套 DME+DSC+IKE 组合。

    车辆与适用范围

    源文档是一份开源车载仪表项目为 E46 机箱写的 CAN 参考,信号表的权威来源是公开的 MS4X 维基,项目自述其解码表「逐字节镜像维基表格」。项目本身处于早期(README 自述 Early),只覆盖 E46 的 PT-CAN 一张网。

    项 内容
    车型 BMW E46,覆盖 M52TU(MS42)与 M54(MS43)两种 DME
    年款 / 市场版本 源文档未给出具体年款与市场版本,只按 DME 区分 M52TU / M54
    ECU / 改装状态 DME(MS42/MS43)、MK60 / DSC III ABS、IKE 仪表、转向角传感器、可选 EGS 自动变速箱;使用 SLCAN 适配器被动监听,不改线束
    采集跨度 源文档未给出日志数或帧数;DBC 侧记载 MS42 文件 11 条报文、102 条信号,MS43 文件 11 条报文、108 条信号
    适用范围 仅限文档所记录的 MS42/MS43 + DSC + IKE 组合;具体年款、动力总成、ABS 版本与配置须自行核对

    总线与寻址

    源文档明示 PT-CAN 运行在 500 kbps、11 位 ID、DLC=8。多字节整数都注明端序;位位置写成 B<字节>.<位>,位 0 是 LSB;百分比缩放的规范系数是 BMW 的 0.390625 = 100/256。有一点很关键:项目只做广播帧的监听与解码,明确不做诊断协议(无 DS2、无 UDS、无 EDIABAS)。

    项 内容
    物理层 双绞线 CAN,PT-CAN(动力总成 CAN)
    链路层 / 比特率 500 kbps(源文档明示)
    寻址方式 11 位 ID,DLC=8
    CAN FD 否;源文档按经典 CAN(8 字节载荷)处理
    端序约定 绝大多数报文为 Intel/小端;LWS1(0x1F5,转向角)为 Motorola/大端
    不做的事 不含诊断协议;电池电压不在 PT-CAN 广播,只能走 DS2 诊断

    已解码信号

    下表从源文档的信号表中抽取代表性条目。MS43 独有或与 MS42 位置不同的信号单独标注;源文档标注「未验证」「无外部旁证」的条目按原样保留。

    信号 位置(ID / 字节 / 位) 解码 证据
    转速 N_ENG 0x316 DME1,B2-B3 小端 × 0.15625 rpm MS4X 维基 0x316 页
    指示扭矩 TQI_CAN 0x316,B4 × 0.390625 % MS4X 维基 0x316 页
    冷却液温度 TEMP_ENG 0x329 DME2,B1 × 0.75 − 48 → °C MS4X 维基 0x329 页
    油门踏板 TPS_CAN 0x329,B5 × 0.390625 % MS4X 维基 0x329 页
    车速 VSS 0x153 ASC1,13 位(B1.3-7 + B2) ((MSB×256+LSB − 0x160) × 0.0625) km/h 维基公式;源文档指出维基公式与「最小值 0x160」不自洽,解码器补了偏移并钳位到 ≥0
    四轮车速 0x1F0 ASC2,B0-B7 小端(每 2 字节一轮) (raw − 44) / 15.875 km/h MS4X 维基 0x1F0 页;raw 最小 0x002C=44 对应 0
    转向盘转角 ANG_PSTE 0x1F5 LWS1,B0-B1 大端 有符号 × 0.04394° 维基页;源文档指出维基把量表四舍五入,真实系数约 0.04395,解码器仍用维基系数
    转角角速度 VEL_ANG_PSTE 0x1F5,B2-B3 大端 有符号 × 0.04394 °/s MS4X 维基 0x1F5 页
    制动压力 P_BRAKE 0x1F8 ASC4,B2 × 1 bar(0–255) MS4X 维基 0x1F8 页
    纵/横向加速度 AX_REF / AY_REF 0x1F3 ASC3,10 位有符号原始值 维基未给缩放;界面按 10 位有符号原始值呈现 MS4X 维基 0x1F3 页(无缩放公式)
    挡位 GEAR_INFO 0x43F EGS1,B0.0-2 3 位枚举(0=N,1-6 前进挡,7=R) MS4X 维基 0x43F 页
    里程 KM_CTR_CAN 0x613 ICL2,B0-B1 小端 × 10 → km MS4X 维基 0x613 页
    油量 FTL_CAN 0x613,B2.0-6 7 位原始值(仪表映射到刻度) MS4X 维基 0x613 页
    机油温度 TOIL_CAN 0x545 DME4,B4(MS43 独有) raw − 48 → °C MS4X 维基 0x545 页;MS42 不广播此字节
    油面高度(MSS54HP) 0x545,B6(MS43 独有) (raw − 158) / 10 → L MS4X 维基 0x545 页

    读取方法与注意事项

    第一是端序陷阱:源文档特别提醒 Intel/小端的 start bit 是 LSB,而 Motorola/大端的 start bit 是 MSB,两者在同一个字节里所指的位完全不同。E46 上除 LWS1 转向角外都是 Intel,LWS1 是唯一的 Motorola 报文,混用会解出错误数值。

    第二是 MS42 / MS43 的字节错位:源文档用一整节列出 DME 发送帧里两种 DME 把信号放在不同位置的条目。例如 TQI_MAF_CAN 在 MS43 位于 DME1 的 B7、在 MS42 位于 B6;机油温度、换挡提示、机油压力低、胎压、机油液位等一串信号在 MS42 上根本不广播。源文档据此为 MS42 做了一个去掉 MS43 专有信号、并重定义 TQI_MAF_CAN 与 ERR_AMT_CAN 字节位置的配置。

    第三是维基公式的已知瑕疵。车速那条,维基同时给出「公式 = ((MSB×256)+LSB) × 0.0625」和「最小值 0x160(0 km/h)」,两者只有在先减偏移再缩放时才自洽;解码器选择减去 0x160 并钳位到 ≥0,让静止车读 0。转向角那条,维基把量表取整到 5 位有效数字(0.04394),真实系数约为 0.04395,量程末端会有约 0.2° 偏差。

    第四是取值语义:源文档规定解码器只在「该帧本就不携带该信号」时(多路复用场景)返回空值,绝不把「数值未知」编码成空值——那是仪表该处理的事,不是解码器的职责。

    证据等级与边界

    可视为外部旁证的是各条 ID 对应的维基页面,项目自述解码表与维基表格逐字节一致;这属于公开文档级证据,不等同于本项目自己的实车复现。属于明确不确定性的是 MS42:维基 MS42 页自己写了「数值抄自 MS43 页,需验证」,因此 MS42 专有的字节位置在真实抓包确认前应视为暂定。

    不能外推的地方有两处。第一,可选装件会改变报文存在性:EGS 自动变速箱、SMG 变速箱、MSS54 相关信号只在对应配置上出现,源文档明确把 0x338 DME3、0x43D AMT1、0x445 TXU1、0x610 ICL1 列为「未解码」,理由分别是赛道化选装、缺真实 SMG 抓包、维基页为空、以及对 VIN 远程帧只做被动监听。

    第二,本文所有条目都绑定 E46 PT-CAN 这一张网与文档所列 ECU 组合,不能套到其他宝马机箱或其他总线(例如诊断总线)。电池电压这条尤其要记住:源文档写明它不在 PT-CAN 由任何已记录的 DME 广播,只能通过 DS2 诊断获得,所以「在广播流里找电池电压」在这台车上找不到。

    常见问题

    E46 的 OBD 口能直接抓到这些信号吗?

    源文档记录的是 PT-CAN 广播帧的监听与解码,总线为 500 kbps、11 位 ID。它明确不做诊断协议(无 DS2、无 UDS、无 EDIABAS),也不保证从标准诊断适配器(如只透传 ISO-TP 请求/响应的电缆)能拿到广播帧;实际取数用 SLCAN 适配器被动监听。

    为什么同一条 ID 在 MS42 和 MS43 上解码结果不同?

    因为源文档列出了一串信号在两种 DME 上位于不同字节:例如 TQI_MAF_CAN 在 MS43 是 DME1 的 B7、在 MS42 是 B6,机油温度等信号 MS42 直接不广播。项目为此为 MS42 单独定义了一套配置。

    车速解码为什么要先减 0x160?

    因为源文档指出维基的公式与「最小值 0x160 对应 0 km/h」不自洽,只有在缩放前减去该偏移才能让静止车读 0;解码器据此补了偏移并钳位到 ≥0。

    电池电压能从总线上读到吗?

    不能。源文档写明电池电压不在 PT-CAN 由已记录的 DME 广播,只能通过 DS2 诊断获得。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/emdzej-dashx-e46/docs/bmw-e46-can-ids.md(主来源:E46 PT-CAN ID 与逐字节信号表)。
    • 项目 01 —— public-can-dbc-datasets/additional/emdzej-dashx-e46/docs/vehicle-overlays.md(DBC + overlay 表达方式与端序/复用说明)。
    • 项目 01 —— public-can-dbc-datasets/additional/emdzej-dashx-e46/SOURCE.md(快照范围、DBC 信号条数与适用范围提示)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • 实时车辆诊断 CLI:ECU 地址、VIN、固件与通信控制边界

    结论:这四个实时诊断 CLI 不是只读日志分析器:它们都经 sendcan 向车辆发送诊断帧,其中 disable_ecu.py 会请求改变 ECU 通信状态。判断结果是「脚本打印」还是「目标 ECU 真的接受」,是两条不同层级的问题——发布成功只表示请求进入了发送链,能否真正上总线还取决于 pandad 与 panda 固件状态。多个工具还会读写 Params、切换 OBD 复用,且没有 finally 恢复。固定快照基线为 c8fb906,本文未执行脚本、连接车辆或发送 CAN。

    共同调用链

    四个 CLI 都调用 can_comm_callbacks():从 can 读取 CanData,把请求封装为 sendcan Event。后者被 can_send_thread() 接收并交给 panda;能否真正上总线还取决于 pandad 与 panda 固件状态。不能把「脚本打印结果」或「发布成功」直接等同于目标 ECU 接收成功。

    入口 请求与输出 本机状态变化
    ecu_addrs.py 默认 bus 1、超时 1 秒;生成 256 个 11-bit 和 256 个 29-bit 候选地址,批量发送 tester-present;仅打印响应地址及可选子地址。 删除 FirmwareQueryDone,IsOffroad 写真、等 0.2 秒再写假;依 --no-obd 切换 OBD 复用。
    vin.py 默认 bus 1、单次超时 0.1 秒、最多 5 轮;尝试该总线允许的 UDS / OBD 或品牌特例,打印响应地址、bus 和 VIN。 脚本本身不写 Params、不切 OBD 复用;仍向 sendcan 发诊断请求。
    fw_versions.py 先查 bus 0/1 的 VIN,再查品牌固件,输出原始版本字节及可能车型;--brand 只缩小固件查询范围。 同样删除 / 改写 Params;VIN 前先请求 OBD 复用,固件请求期间可逐请求切换。
    disable_ecu.py 固定在 bus 1 向 Honda Bosch 雷达地址请求扩展会话,再发送通信控制请求;打印布尔值。 不写 Params、不切 OBD 复用;会尝试改变目标 ECU 的收发状态,且没有恢复调用。

    OBD 复用与状态位

    obd_callback() 在目标模式与 Params 当前值不同时,删除 ObdMultiplexingChanged、写 ObdMultiplexingEnabled,然后无独立期限地阻塞等待确认;pandad 的 updateMultiplexingMode() 在实际切换后写确认。ECU 地址与固件脚本没有恢复先前 Params / OBD 状态的路径。

    FirmwareQueryDone 被删除后,pandad 的 fetchCarParams() 会拒绝继续取得车辆参数,直到其他流程重新置位;常规 Car.__init__() 会在车型识别后置位。IsOffroad 的真 / 假写入是脚本行为,不能据此断言 pandad 已同步切换安全模式——其安全模式配置使用 deviceState.started。

    工具 是否读写 Params 是否切 OBD 复用 是否恢复原状态
    ecu_addrs.py 删除 FirmwareQueryDone,改写 IsOffroad 是(--no-obd 控制) 否(无 finally)
    vin.py 否 否 不适用
    fw_versions.py 删除 / 改写同 ECU 地址脚本 是(VIN 前与固件期间) 否
    disable_ecu.py 否 否 否(改 ECU 收发状态且无恢复调用)

    失效与证据边界

    1. --scan 当前不可用。 脚本把 256 组三种地址形状放进 extra={"any": {"debug": extra}},但固件查询按品牌执行 FW_QUERY_CONFIGS[brand];当前归档没有 any 品牌配置。因此 VIN 查询和 Params / OBD 副作用已经发生后,固件地址构建阶段抛 KeyError('any');--brand 也不会消除此额外键。
    2. ECU 清单不是全量证明。 get_all_ecu_addrs() 把 TX 候选集合直接当 RX 白名单;29-bit 响应通常采用交换后的地址,可能被过滤。get_ecu_addrs() 捕获异常后返回已收集的部分集合,timeout 也不能限制阻塞式接收的整个墙钟时间。
    3. VIN 既不验证身份,也不保证隐藏。 get_vin() 对命中地址的结果做少量去填充后直接解码返回,CLI 原文打印 VIN。失败时返回 (-1, -1, "00000000000000000"),不等同于「车辆没有 VIN」;源码另有 is_valid_vin(),此 CLI 没有调用它。
    4. 固件列表可以是部分结果。 固件查询按请求配置与子地址分组,单个请求异常记录后继续;返回版本可能缺 ECU 或缺品牌。候选车型匹配给的是候选集合,不是执行许可。原始固件字节与 VIN 可能包含可识别车辆的信息。
    5. 手动禁用雷达不确认禁用成功。 通用 disable_ecu() 最多重试 10 次,先要求扩展会话的有效应答,再调用 get_data(0) 发送通信控制请求并丢弃返回字典;零超时和空的期望响应前缀不能提供可靠的正响应证据。帮助函数注释明确警告会禁用原车 AEB,脚本没有配套恢复路径。

    面向硬件与插件化的接口约束

    以下是设计建议,并非当前实现:将前三类查询工具改为只提交有界诊断任务的证据插件,sendcan 与 OBD 复用由唯一诊断代理持有。代理校验点火 / 车速、bus、地址、服务、速率和总时长,记录每次请求与局部响应;--scan 需先修复配置建模,再在隔离台架验证总线负载。通信控制应归入单独的高危能力,需要目标 ECU / 版本白名单、原车 AEB 影响评估、正响应和总线状态回读、持续保活及恢复方案。身份插件只返回带来源和时间戳的 VIN / 固件证据,不提供控制权限;执行权限仍由独立 MCU / panda safety 和车型适配门决定,不能由插件加载或候选车型自动授予。

    常见问题

    这些 CLI 会向车辆发 CAN 吗?

    会。四个工具都经 sendcan 向车辆发送诊断帧,其中 disable_ecu.py 会请求改变目标 ECU 的通信状态。它们不是只读日志分析器;「脚本打印结果」不等同于目标 ECU 接收成功。

    运行这些脚本会留下什么状态?

    ECU 地址与固件脚本会删除 FirmwareQueryDone,把 IsOffroad 写真、等 0.2 秒再写假,并切换 OBD 复用,且没有恢复先前 Params / OBD 状态的 finally。FirmwareQueryDone 被删后,pandad 会拒绝继续取得车辆参数直到重新置位。

    –scan 现在能用吗?

    不能。脚本把地址形状放进 extra={"any": ...},但固件查询按品牌执行 FW_QUERY_CONFIGS[brand],当前归档没有 any 品牌配置,固件地址构建阶段会抛 KeyError('any');--brand 也不会消除该额外键。VIN 查询和 Params / OBD 副作用已经发生。

    打印 disabled: True 就说明雷达被禁用了?

    不能这样认为。通用 disable_ecu() 丢弃查询结果,零超时与空期望响应前缀无法提供可靠的正响应证据;即使底层打印成功,也不等于已证实 ECU 停发、AEB 状态或会话保持。帮助函数注释明确警告会禁用原车 AEB。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/CAR_LIVE_DIAGNOSTIC_CLI_CONTRACT_DEEP_DIVE.md(取用了四个 CLI 的请求与副作用、失效边界与插件化接口约束分析)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11