标签: CAN总线

  • Ram ProMaster 2022 三总线地图:125 kbit/s 实测与 16 个 UDS 端点

    结论:2022 Ram ProMaster 的被动 CAN 工作必须按三条独立总线规划:C-CAN(OBD 引脚 6/14,500 kbit/s)、B-CAN / CAN IHS(DLC 引脚 3/11,125 kbit/s 实测)和 CAN CH(DLC 引脚 12/13,500 kbit/s 实测)。这批记录里登记的 UDS 端点共 16 个,全部走 29-bit ISO-TP normal-fixed 寻址。真正决定能不能落地的不是「能读多少帧」,而是三条边界:OEM 文档里的 CAN-B 50K 说法不能用来配波特率;B-CAN 上 0x760 的被动里程只被认可为中控模块的本地副本;0x1F4 字节 4 高位已被完整复核驳回,不能当当前挡位。

    三条总线的速率、引脚与证据来源

    三条总线里只有 C-CAN 的 500 kbit/s 同时有 OEM 文档和实测两个来源,另外两条的通信参数都来自本机实测。B-CAN 是最容易被带偏的一条:该车型的 COMMUNICATION / CAN BUS DESCRIPTION 明确把 CAN-C 写成 500K、CAN-B 写成 50K,但这份文档用的是 C-1 到 C-8 与 BH 这套分支命名,与 DLC 图的 CAN C/CH/IHS 命名体系并不对齐。2026-07-20 在引脚 3/11 上的被动捕获给出 125 kbit/s 且零 RX 错误,因此以实测为准,文档里的 50K 只保留为线索。

    总线 速率 引脚 接入方式 证据边界
    C-CAN / HS-CAN 500 kbit/s OBD 6/14 经 SGW 旁通的内部 C-CAN tap,Board A CAN1 角色 动力总成与诊断;法规要求的 OBD-II Mode 01 PID 不经此旁通
    B-CAN / CAN IHS 125 kbit/s(实测) DLC 3/11 标签转接线的 B-CAN 支路,Board A CAN2 角色 舒适与车身;派生配置的 8 个目标里 4 个已应答,另外 4 个仍超时
    CAN CH(第二条高速总线) 500 kbit/s(实测) DLC 12/13 灰色 12/13 适配器,Board B CAN1 角色 被动捕获零收发错误,同时完成 ABS、EPS、HALF、ORC 的身份读取

    永久安装用两块双通道适配器承载三个角色(gs_usb,USB VID:PID 1d50:606f):C-CAN 与 B-CAN 分别落在第一块的 dev_id 0(CAN1)和 1(CAN2),CAN CH 在第二块的 dev_id 0,剩下那一路保持 down。四块板载红色终结跳线全部拆除,因为三个 tap 接入的是车内已经终结的网络;虽然适配器支持 CAN FD,暴露出来的三条总线一律配成 classical CAN、FD off。角色由 USB 序列号加 dev_id 解析,Linux 的 canN 编号只是枚举顺序,不作为身份依据。

    16 个 UDS 端点的总线分布与行为差异

    下表是已登记的端点。它们的 DID 命名空间按 ECU 隔离——雷达的某个 DID 和其他模块的同名 DID 没有任何关系,所以不要把这些行合并成一张「整车 DID 表」。

    键 模块 总线 TX → RX 已记录的行为
    radar_acc Bosch ACC 雷达 C-CAN 18DA2AF1 → 18DAF12A 扫描途中切断点火仍会 ACK;车速只能走内部 DID,OBD PID 不可用
    pcm 动力总成模块(3.6L) C-CAN 18DA10F1 → 18DAF110 固定 DLC 8 零填充是已知可用配方;遗留会话请求已两次验证
    rf_hub RF Hub(TPMS / RKE) C-CAN 18DAC7F1 → 18DAF1C7 点火 OFF 仍应答,属 KL30 常电,是驻车取电压的入口
    tcm ZF 948TE 变速箱 C-CAN 18DA18F1 → 18DAF118 读取 211B–2132、2136–213E 与 026B 均为正向
    shifter 电子换挡器 C-CAN 18DA1FF1 → 18DAF11F 身份已读取,可用于模块级区分
    bcm_ccan 车身控制模块 C-CAN 端点 C-CAN 18DA40F1 → 18DAF140 执行类请求受电源模式门控,钥匙 OFF 常见否定响应
    cluster 组合仪表 IPC C-CAN 18DA60F1 → 18DAF160 已把若干仪表符号逐项绑定到具体 DID
    telematics 远程通信盒模块 C-CAN 18DAC6F1 → 18DAF1C6 唯一一个车上后台诊断客户端从不查询的已注册模块
    ics_bcan 中控面板 B-CAN 18DA85F1 → 18DAF185 里程 DID 2001 以 0.200 Hz 轮询,收到 302/302 正向应答
    uconnect_bcan 主机 / 显示屏 B-CAN 18DA87F1 → 18DAF187 身份与阶段性故障码家族匹配
    climate_bcan 自动空调模块 B-CAN 18DA98F1 → 18DAF198 所选变体未通过校验,其仪表标签不可直接套用
    emcm2_bcan 中控菜单 / 音量按键 B-CAN 18DAD9F1 → 18DAF1D9 设备子类型匹配加上 OEM CAN-IHS 角色
    abs_canch ABS / ESC CAN CH 18DA28F1 → 18DAF128 历史偶发故障码,最后一次测试通过
    eps_canch 电动助力转向 CAN CH 18DA30F1 → 18DAF130 无故障报告
    half_canch 前视摄像头辅助模块 CAN CH 18DA31F1 → 18DAF131 同一身份还可通过网关在 C-CAN 侧被动读到
    orc_canch 乘员约束控制器 CAN CH 18DAC0F1 → 18DAF1C0 无故障报告

    网关路由是这张表的隐藏前提:在 C-CAN 上发给 CAN CH 目标的物理请求会被网关逐帧转发,中位延迟 0.31 ms(51 次交互,落在 0.23–2.78 ms 区间),网关还会在 CAN CH 侧替换成自己的流控帧;ECU 应答被复制回 C-CAN 时目标字节被改写为 F2,所以 C-CAN 上看到的 18DAF2xx 是网关副本,不是第二个诊断仪。另有一条与时统高度相关的事实:车上存在一个后台诊断客户端,会在外部 F1 流量静默 92 秒以上后才启动只读扫描,一旦外部轮询恢复便在 1 至 2 秒内终止;做被动相关性分析时必须把这些窗口单独标出来。

    C-CAN 广播帧:可以直接进遥测的那部分

    下面这张表只收已经 allowlist 进遥测的信号。入选判据是「是否与同类 DID 做过定量化对照」,而不是看上去是否合理——这也是为什么同属 0x100 的扭矩字节还停在候选名单里。

    ID 字节 / 位 解码式 含义 验证强度
    0x2EF 帧存在性 无 点火 ON 门控 已验证;帧计数门控曾失败,存在性门控有效
    0x41A byte0 4.0 + raw × 0.05 V 系统电压 已验证,含驻车唤醒场景
    0x41D byte2 raw × 4 kPa 机油压力 与内部 DID 逐字节镜像,怠速 733/733 样本 R² 0.9998047
    0x2ED byte0 raw − 40 °C 冷却液温度 怠速 R² 接近 1.0,负载工况 1,351/1,356 样本
    0x0FC bytes0–1 BE u16 屏蔽低两位后除以 4 rpm 发动机转速 负载工况 1,351/1,356 样本 R² 0.9999794
    0x0F0 bytes3–4 高 11 位 右移 5 位后减 500 Nm 变速箱请求扭矩上限 236 样本 R² 0.99999986
    0x1F7 打包 17 位:byte0 bit0 加 bytes1–2 raw / 32 rpm 变速箱输出轴转速 低于 16 位边界 R² 0.99999578
    0x1F7 byte3 有符号 i8 0.375 × raw + 57 °C 变速箱油温 多次 RMSE 低于 0.89 °C,另含一次预热反例
    0x1F7 bytes4–5 BE u16 raw / 2 rpm 涡轮 / 输入轴转速 盲区复原 2,014 样本 R² 0.99996705
    0x101 byte0 bit0、byte1 左移 3 位、byte2 高 5 位 raw / 16 km/h 瞬时车速 由变速箱侧证据裁定为 /16,否决早期的 /32 候选
    0x0EE bytes0–1 BE u16 raw / 128 km/h 独立高分辨率车速 169 样本 R² 0.9990360
    0x5A0 byte3 / byte2 mph 与四舍五入后的 km/h ACC 设定车速 两字节在 1 km/h 内一致才允许发布
    0x0E0 byte0 raw mph 限速标志识别值 DLC 4、10 Hz,读数为 0 时不发布

    一处值得单独说明的工程约定:2026-07-19 的离线分析确认 0x101 的 bytes0–2 是瞬时车速,而不是旧笔记里写的里程累加器。两条日志分别给出 539,982 帧(约 99.998 Hz,原始值域 0–2153)和 224,137 帧,帧内 CRC-8/SAE-J1850 在 224,137 帧上全部匹配。0x0EE 独立跟踪同一物理量,回归关系约为 0x0EE_raw ≈ 8.0099 × speed_raw − 11.6,移动样本相关系数 0.9999919。两者 integrals 在另一条记录的差值为 0.007 km,证明的是彼此关系,不是物理量纲。

    被驳回的候选与还没闭环的边界

    这批记录的价值有一半来自「已经否掉什么」。下面四项在别的项目里很容易被当成常识采用,但在这里都有明确的驳回或降级理由。

    候选 结论 决定性证据
    0x1F4 byte4 高位 = 当前挡位 驳回 完整复核扫过 4,187,827 帧得到 42,574 对有效轴速比样本;开发段里 21,725 对取值为 7、6,548 对取值为 8,但两组中位数都是 0.699,而 OEM 八挡为 0.580
    B-CAN 0x760 = 整车里程 仅认可为中控本地副本 对 302 次内部里程应答,冻结公式为「十分之一公里值等于 10 倍被动原始值」;174 次邻近匹配 p95 误差 0 计数,但与仪表仍有约 11.6 mi 差
    0x417 bytes2–3 = 变速箱油温 驳回 两次独立盲驾都不支持该假设,最佳 R² 仅 0.44824 且斜率为负
    0x100 bytes0–1 = 实际扭矩 保留候选 2,014 样本盲区分段里 overrun 段 R² 仅 0.63031,不能当作实际扭矩发布

    里程那条还要多说一句:2026-08-30 的三总线行驶记录里,中控计数器在首个 25 分钟窗口增加 23.0 km(14.291537 mi),独立车速积分为 14.365140 mi,相差 0.512%;跨钥匙周期的第二次比对里,中控增加 116.817 mi、积分增加 116.511358 mi,相差 0.262%。这两组数字证明的是相对刻度,不是绝对基线。

    正面闭环的案例也有一个,就是机油寿命。在驻车、点火 ON、发动机 OFF 的条件下,向 PCM 发出一条固定 DLC 8 零填充请求 03 22 21 85 00 00 00 00,物理地址为 18DA10F1 → 18DAF110,收到正向应答 62 21 85 52,无符号字节换算后为 82%。这次读取没有会话切换、没有 TesterPresent、没有流控帧,C-CAN 发送计数仅从 127233 增加到 127234,三条总线的收发错误计数保持为零。存在 limits 的工程约定是:参数超出 0 到 100 时置为不可用,而不是裁剪成百分比。

    常见问题

    OEM 文档写明 CAN-B 是 50 kbit/s,为什么实际按 125 kbit/s 配置?

    因为那份文档使用的是另一套分支命名(C-1 到 C-8 与 BH),与诊断口的 CAN C/CH/IHS 命名体系并不对齐,其 50K 描述更可能指向另一条内部支路。2026-07-20 的被动捕获在引脚 3/11 上测得 125 kbit/s 且零 RX 错误,2026-07-25 的灰色适配器捕获又独立在引脚 12/13 上确认 500 kbit/s,两者都以实测作为配置依据。

    B-CAN 上的 0x760 里程值能不能替代仪表里程?

    不能。它与中控内部计数器的关系式已经冻结并复制过:十分之一公里值等于 10 倍被动原始值,174 次邻近匹配的 p95 误差为 0 计数、平均绝对误差 0.1724 计数;相对刻度也经两次独立检验,分别为 0.512% 与 0.262%。但它与仪表的绝对读数仍相差约 11.6 mi,因此只能当中控本地副本使用,不能据此摘掉仪表上的星标。

    为什么读取 PCM 机油寿命不需要切换诊断会话?

    2026-10-03 的实车验证显示,在驻车、点火 ON、发动机 OFF 条件下发出一条零填充请求,就拿到了正向应答 62 21 85 52。但这不能推广成「默认会话支持 22 读取」的普遍结论:继承会话没有被正面识别,且同一 PCM 的其他 DID 曾明确要求遗留会话。工程上的处理是沿无会话切换的配方发一次,被拒绝就上报需要会话并就此停止。

    0x1F4 的字节 4 高位能不能直接当成当前挡位?

    不能。2026-09-22 的两秒样本曾把它对上七挡比值 0.699,但完整复核扫过 4,187,827 帧、取到 42,574 对有效样本后,出现了大量比值稳定在 2.842、1.909、1.382 而该位仍为 7 的情形;开发段里取值为 8 的 6,548 对,中位数同样是 0.699 而不是八挡的 0.580。这些都是稳定工况下的反例,不是换挡瞬态。

    C-CAN 上出现 18DAF2xx 帧意味着什么?

    意味着那是网关把 CAN CH 上某个 ECU 的应答复制回 C-CAN 的副本,目标字节从 F1 改写为 F2,并不是第二个诊断仪在发话。转发延迟中位 0.31 ms,51 次交互落在 0.23–2.78 ms 区间,网关还会在 CAN CH 侧替换自己的流控帧。做被动归因时不要把它算成外部工具的流量。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/docs/bus-map.md(三条总线的速率、引脚与证据,16 个 UDS 端点,以及三条总线的广播帧表)
    • 项目 01 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-07-19_ccan_drive_signal_analysis.md(0x101 与 0x0EE 车速字段的定位与两条日志的样本量)
    • 项目 01 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-08-30_three_bus_drive_odometer_validation.md(中控里程与被动 0x760 的冻结公式及跨钥匙周期复制)
    • 项目 01 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-09-22_gear_and_oil_life_offline.md(挡位候选驳回的完整复核数据与机油寿命闭环)

    免责声明

    本文所有波特率、引脚、CAN ID、字节位定义与转换系数均来自一台 2022 款 Ram ProMaster 的公开逆向记录,未经独立实车复现;不同年款、市场区域与 ECU 软件版本可能存在差异,标注为「已验证」的结论仅指在该车当时的捕获条件下成立。本文不构成对任何车辆执行主动诊断、刷写或执行器操作的授权,涉及安全相关用途请以实际测量与制造商资料为准。

    更新记录

    • 2026-10-15 初稿

  • MX-5 ND2 的 CAN 状态表:221 个开放字段与三级证据标签

    结论:这份 Mazda MX-5 ND2 的 HS-CAN 档案,价值不在仪表盘能画几个数,而在于它把总线上的每一个可用位域分成三层:已确认信号、带 _maybe 或 _related 后缀的开放字段,以及已经证伪的负结果。截至 2026-09-30:参考日志里 1,977 个会变化的位中,未被 DBC 信号覆盖的从 1,311 位降到 1,124 位;跨全部日志仍有 221 个字段在半数以上日志里变化却没对上物理含义。同期修掉的最严重问题不是某个信号定义,而是分析工具本身的缺陷:50 份日志重算后,离合器百分比公式被修正为严格的 0.5 倍原始值。

    硬件链路与双份 DBC

    这台车的采集链路很朴素:OBD 口的高速 CAN(引脚 6 为 CAN_H、14 为 CAN_L,4/5 为地,16 为常电 12 V)经一根自制 Cat5e 短接线接到 CANable 2.0 方案的 USB 适配器,再由树莓派按 KeyState 信号自动启停 candump 日志。总线为 500 kbit/s,通道只有 can0;适配器上的 R120 终结跳线必须拨到 OFF,因为它只是挂在总线上的一个分支,不是总线端点。

    项目 取值 这么定的原因
    USB 适配器 CANable 2.0 方案,工作模式 USB ID 1d50:606f,烧录模式 0483:df11 两种固件可从 USB ID 区分;误入烧录模式需断电数秒重插
    总线与速率 高速 CAN 单通道 can0,500 kbit/s ND2 的 OBD 口只暴露这一条高速总线
    终结跳线 R120 OFF 车辆总线两端已终结,第三颗 120 欧电阻会拉偏显性电平
    主用 DBC 持续维护的 MX5ND 高速总线扩展版 所有修正与新增都落在这一份
    上游原始 DBC 保持原样不做改动 来自社区 6th-Gen Mazda 项目,许可为 CC BY 4.0,留作对照基准
    运行环境 树莓派只读根文件系统加内存叠加层 只有挂日志的 U 盘可写,系统改动需要两次重启

    命名约定本身就是这套档案的核心契约:没有后缀的信号表示已在多份日志上定量确认;_maybe 表示释义或刻度尚未锁定,只允许原始值透传;_related 表示它与某个已知量同源但不是同一物理量,不能当成简单镜像。此外还有一批信号被显式标记成「名字看起来正常但实际不可用」,例如社区 DBC 里两个修正过的加速度通道,工程上一律改用车身控制模块的同名加速度通道。

    已锁定的场位:可以直接引用的定义

    下表摘自状态表与开放字段表的确认部分,包含 2026-09-26 实车测试新增的条目。每一条都带具体的判定依据,而不是「看起来合理」。

    信号 位置 公式 / 单位 判定依据
    离合器行程 已有 DBC 通道 百分比等于 0.5 倍原始值 2026-09-29 重算后 R² 达 1.000,旧的 0.4665 倍加 0.56 被判定为分析工具假象
    实际发动机百分比扭矩 0x167 byte4 3.0242 倍原始值减 177.849,残差 4.07 个百分点 与标准 PID 0x62 两次行驶对照,2026-09-29 再校准 +2.6%
    制动压力 已有 DBC 通道 斜率 0.0012413、偏移 +32.7986 与真实 OBD 参考通道 R² 0.986,2026-09-29 再校准 +2.4%
    倒挡 0x445 bit 7 布尔量 倒车时横摆率符号反向,吻合度 99.7%,样本 1,195
    牵引力控制介入 0x211 bit 40 布尔量 5 份日志 6 段弯心出弯工况,同时伴随发动机扭矩下降
    强减速标志 0x211 bit 43 布尔量 6 份日志 16 段,触发区间 0.46 至 0.84 g,中位数 0.60 g;两次实车全力制动已确认
    ABS 介入 0x211 bit 42 布尔量 35 分钟日志中占 0.052%,恰好落在两段真实调制区间;同日返程对照组为 0.000%
    DSC 指示灯 0x415 2|2 3 表示闪烁 介入时的值与自检灯阶段的值不同;旧定义长期读作关闭,已不作为状态依据
    冷机指示 0x4F7 5|2 3 表示冷机 21 次记录全部在冷却液正好 55.0 °C 时切换
    车身模块供电电压 0x43F 19|10 0.016 V 每 LSB R² 0.998,且恒定低于直流变换器通道 0.68 V
    燃油消耗计数器 0x420 byte2 每升 4,834 个计数 两次加满共加油 34.4 升;与空气质量流量及空燃比的速率相关性达 0.99 至 0.999
    行驶距离计数器 0x420 byte1 每步 0.1992 米 对着里程表增量标定,覆盖 5 份日志;早期 0.209 是车速高估带偏的结果
    剩余保养里程 0x3D1 47|14 公里,原始值等于 173764 减里程公里数 34 份日志 R² 达 1.000000,取代了原先取值混乱的同名字段
    转向角速度幅值 0x082 byte5–7 12 位,约 0.5 度每秒每 LSB,符号在 byte7 bit0 28 份日志中对角度求导,相关性达 0.988 至 0.998
    方向盘绝对角度(EPAS) 0x86 0.1 倍原始值减 1600 度 剔除无效帧后 R² 达 0.9997 至 0.99995,残差 0.65 至 0.94 度
    交通标志限速 0x35F 4|7 km/h 取值 30 到 120,与实际行驶速度吻合,0 表示无限速
    平均油耗 0x4F3 byte4–5 大端 0.01 升每百公里,60 秒更新一次 加油复位时刻对齐,后续与计数器、距离推算相差 2.6 毫升

    最后一行值得单独说明:瞬时油耗在高速 CAN 上并没有找到独立的广播通道,实践中可以用燃油消耗计数器除以行驶距离计数器自行计算;这也是这套档案一贯的写法——公开发的是方法,而不是整车轨迹数据。相比之下,机油温度与爆震退角这两个关键量完全不在广播里:机油温度对应厂商私有的模式 22 自定义数据标识 0x1310,公式是首字节乘 256 加次字节、再除 100 减 40,标准 PID 0x5C 在这台车上不被支持,因此每 10 秒主动轮询一次;爆震退角对应同样是厂商私有的标识 0x03EC,公式是有符号 16 位整数除 512,两次独立对照分别为 73% 和 81% 逐位相同。

    仍然开放的字段:221 个未知字段的分类

    开放字段表把「还没有名字」的东西也做了归类。参考日志里 1,977 个会变化的位中,未被 DBC 覆盖的从 1,311 位降到 1,124 位;跨全部日志统计,至少在半数日志中会变化的开放字段共 221 个:32 个测量场(419 位)、42 个状态场、128 个标志位、10 个计数器、9 个校验或噪声。剩余测量位大多集中在前视摄像头报文(0x242 至 0x246)与信息娱乐报文(0x3D2、0x4FE)里。完整报文聚类还给出另一个量级:151 条报文中有 74 条带动态未分配字段,其中 36 条完全未知。

    字段 观察到的行为 假设 定向实验
    0x200 byte4–5(偏移二进制) 载荷域,与踏板、扭矩的相关性达 0.72 至 0.94 驾驶员需求扭矩或指示扭矩 用牵引力控制请求量做牛米锚点
    0x200 byte2–3 多数取负 40 至正 10,能量回收时更低,冷机可到负 49 附件损失扭矩 怠速下逐项开关空调与后窗加热
    0x20A byte2–3 疑似有符号;清理后重扫,燃料切断在 15 份日志中相关性中位数 0.71,目标空燃比 7 份为 0.69 混合气或滑行状态 追加标准 PID 对照
    0x4DA byte0/1/2/4 起步取 50,滑行时下降,加载荷后缓慢上升 催化器温度或氧存储模型 同时记录催化器温度 PID
    0x4FA byte2–3 清理后重扫:扭矩 11 份日志相关性中位数 0.65,节气门 6 份 载荷或暖机自适应 暂缺
    0x21F byte4–5 清理后重扫:进气歧管压力 6 份日志相关性中位数 0.70 歧管压力或载荷量 暂缺
    0x4D4 byte0–5 点火后归零,几分钟后出现;byte0 在高速公路上升,byte1 在堵车时增长 驾驶评分或经济监视器 按时刻拍照记录显示屏
    0x09B bit 2 每 50 到 100 秒出现约 10 秒;怠速期间电流通道下降约 100 个计数 大功率用电设备,疑为散热风扇 听或观察风扇并记录时刻
    0x4DF byte0、byte5 冷启动时紧贴合进气温度,相关性 0.980 与 0.994,但斜率分别为 1.44 和 2.24 K 每计数 变换器或电容温度,也可能是随温限值 红外测温仪对比

    字节扫描工具本身也经历过一次去伪:早期版本把单个初始化帧造成的常值(例如 0x596)和锚点起始段的自检灯突变误判成候选,清理后候选对从 105 降到 58。工具保留了两处已知局限:排名把 R² 四舍五入到两位,导致「胜出的布局」常常只是一段近似区间;缺少分辨率细化能力时,较短且拟合相差不大的子域可能取胜,工具会对这种情况打印更长的备选提示。目前仍列为中等候选的开放字段是 0x20A byte2–3、0x4FA byte2–3、0x200 byte6–7 与 0x21F byte4–5。

    负结果与方法陷阱

    这套档案最值得借鉴的一点是它把「找不到」也写成了结论,并附上对照组强度。下面几条在别的 ND2 项目里很容易被重复劳动。

    结论 证据 后果
    垂直加速度、侧倾角速率与俯仰角速率不在高速 CAN 上 25 组「CAN 加手机」平行记录,正对照组横摆率相关性达 0.95;夜间启动也未见照度调节电机的位置斜坡 只能转向 UDS 会话或中速总线去取
    车上没有可用的日历时钟通道 600 多个未知字段做过计数行为筛查,最佳结果是 0x4FE 上的一个 3.33 Hz 点火计时脉冲,周期在 3 份日志上的变异系数仅 0.000025,但每次点火归零 无实时钟期间的日志只能靠文件名加偏移量纠时,后期加装了 DS3231 时钟模块
    高频轮询会挤掉同总线上的第三方适配器 约 170 次每秒的请求压力下,对方 19% 至 29% 的请求先读到我们的应答,5% 至 18% 完全无应答,应用侧请求率跌到 0 检测到 0x7DF 或 0x7E0 上有外来请求时,把自身轮询限流到 5 轮每秒
    把某个字段当成挡位会出错 原先用 MT_Gear_Actual 取 7 表示倒挡,实际那是点火后约两秒的初始化值,倒车时该字段为 0 挡位判定改用 0x445 bit 7
    分析工具差错会让比例尺系统性偏小 重采样函数在拟合时对稀疏参考做了线性插值,压低了 R² 与斜率 离合器、制动压力、扭矩、电池电压的比例尺全部重新折算

    还有一处工程细节值得注意:胎压是这套档案里唯一不做周期性广播的量,必须靠主动 UDS 请求获取(请求头 0x720,模式 22,应答落在 0x728,DBC 里按 PID 做多路复用),轮询周期刻意设为 120 秒以压低总线占用。轮位映射直到 2026-09-26 才完整收口:轮胎 1 为左前、轮胎 2 为右前,轮胎 3 与 4 分别为左后、右后。

    常见问题

    为什么这份档案里还有 221 个字段没有名字?

    因为作者把「未解释但会变化」的字段也当作成果登记,而不是静默丢掉。统计口径是至少在半数日志里发生变化的开放字段,共 221 个,其中包含 32 个测量场(419 位)、42 个状态场、128 个标志位、10 个计数器和 9 个校验或噪声字段;剩余测量位集中在前视摄像头与信息娱乐报文里。

    总线上的车速为什么比 GPS 高约 2.9%?

    这是这台车本身的特性,不是解码错误:70 份带手机 GPS 的日志做比值得到 0.971,即总线车速偏高约 2.9%。它会影响加速、制动、极速与滑行阻力拟合中的绝对数值,因此状态表里专门留了一条提示:性能模型使用绝对值时要扣掉这个偏差。

    为什么要给部分信号加 _maybe 后缀而不是直接用?

    后缀是这套档案的证据等级标签。_maybe 表示释义或刻度尚未锁定,只能做原始值透传,不能换算成物理量;_related 表示与某个已知量同源但不是同一物理量的镜像。历史上确有反例:某个 15 位扩展场曾被引申为非线性,后来发现是取错位导致的。

    第三方 OBD 适配器为什么会被本项目的轮询挤掉?

    因为快轮询组在 0x7E0 上以约 170 次每秒发请求,与手机端适配器共用同一个报文头,导致对方 19% 至 29% 的请求先读到我们的应答、5% 至 18% 完全得不到应答,应用侧请求率从约 19 次每秒掉到 0。修复办法是检测到外来请求时把自身轮询限流到 5 轮每秒。

    高速 CAN 上有没有可以直接对时的日历时钟通道?

    没有。600 多个未知字段做过专门的计数行为筛查,最佳候选是 0x4FE 上的一个 3.33 Hz 点火计时脉冲,周期在 3 份独立日志上的变异系数只有 0.000025,但它每次点火都会归零;另一个看起来像的量被证明是累计工作时间,熄火即停。因此无实时钟期间的日志只能靠文件名加偏移量纠时,后续加装了 DS3231 时钟模块。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/docs/status/can-bus.md(硬件链路、双份 DBC 策略、可解码信号分组、开放点与纠时机制)
    • 项目 01 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/docs/status/can-open-fields.md(已确认信号表、实车测试新增项、开放字段分类与报文聚类数量)
    • 项目 01 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/README.md(仓库定位、许可证与刻意不公开的内容说明)

    免责声明

    本文所述的 CAN ID、字节位定义、缩放系数与验证状态均来自一台 Mazda MX-5 ND2 车主自行记录的公开档案,属社区逆向工程产物,不代表车辆制造商的官方数据,也未经独立实车复现。不同年款、市场区域与 ECU 软件版本可能存在差异;标注为开放或假设的内容不得用于计量、安全判定或控制用途。本文不构成主动诊断、刷写或执行器操作的授权。

    更新记录

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

  • Indian Springfield 2017 的解码计划:八个未解字节与请求墙

    结论:这份解码计划的证据底是 42,365 帧,来自 2026-08-15 一个下午的四份抓包;总线上 30 个 PGN 分四组——已发货 20、传输层 4、已理解但故意不发 1、真未知 5。收尾状态可以一句话说完:剩下「八个单字节、四个毫无变化的 PGN,以及一切需要主动请求的东西」。它没有 DBC,靠的是硬件只听模式加受控动作。

    总账:42,365 帧是变化数,不是发送数

    这是读这份计划前必须先接受的一条限制。固件只在某个 ID 的载荷与上一帧不同时才发布该帧(updateTable() 仅靠 memcmp 置脏标志),抓包工具记录的正是这条流。所以文件里每个「帧数」都是变化次数,不是发送次数。由此有三件事不成立,而每一件看起来都很像成立:

    • 推导不出报文速率。PGN 65381 在四次骑行里的 299 条记录说明它变了 299 次,不说明它慢。
    • 分不开周期性与事件驱动。两者在去重之后长得一模一样。
    • 滞后与相关是在不规则采样上算的。油门那条结论扛住了这一点——它有标准和手册双重印证——但这样找到的临界相关比看上去要弱。

    不过「跨 N 条记录恒定」仍然是有效陈述:它在每一次看到该报文变化时都确实保持了那个值,只是它不是关于 N 次发送的陈述。

    谁在总线上:地址声明比流量猜测可靠

    每个模块都在 PGN 60928 上用 64 位 J1939 NAME 宣布自己是谁:制造商、功能、实例。这些声明自 2026-08-15 起就在抓包里了,但模块地图此前有整整三周是靠流量猜的。这张表可信,是因为有两条自己会互相检验:SA 0 声明 Engine 并发送发动机数据;SA 23 声明仪表并发送里程、小计和外温。两次「说是什么」与「做什么」的独立吻合,才让功能 30 对 SA 39 也说得通。

    SA 声明次数 制造商代码 功能 原本靠流量猜的
    0 4 51 Engine(发动机) ECU ✓
    11 4 7 不在标准表里 ABS
    23 4 340 Instrument cluster(组合仪表) 组合仪表 ✓
    39 4 449 Management computer(管理计算机) 「VCU、车身」✓ 大意对
    136 8 146 Instrument cluster(组合仪表) 「声明了地址然后一句话不说」

    SA 136 是这一节的发现:它声明了与仪表相同的功能(19)却来自另一个制造商(146 对仪表的 340),而且从没发过别的任何东西。它还比谁都声明得勤——四次骑行共八次,其它模块每份抓包只有一次。一个通电、比谁都执着地自报家门、然后毫无贡献的模块不是坏模块,它更像是「显示类已装设备,而这辆车不给它活干」。

    另外 SA 11 的 NAME 解码不出来,这件事本身就值一行:它给出功能 194、车辆系统 78、行业组 7。行业组是三位,7 未使用;车辆系统 78 超出任何组的范围。反转字节序得到功能 255「not available」,这至少是一种合法的「拒绝声明」——但只反转这一个模块而不反转另外四个,是假设不是发现。记为异常,不解释掉。

    仍开放的字节:八个单字节与四个沉默 PGN

    下表汇自「仍开放」一节与逐字节清单,零基字节编号与代码一致。「标准怎么说」一列引用标准,标准从 1 计数,少数较老的注释也照此。

    PGN SA byte 取值 / 范围 已知 怎么验
    65382 0 0 255 个取值 / 4,721 帧 一个活的发动机量,负荷、点火提前角与喷油脉宽是候选。这是总线上最忙的未查字节,也是探针最后还在追的东西 开着巡航定速跑:稳住油门、改变负荷,看它跟负荷还是跟手
    65265 0 3,bit 0-1 取 0 和 1 开放线索,2026-10-04。位于标准给 SPN 595「巡航激活」的位置,且在八月抓包里会动 在下一次用到巡航的骑行里,把该值与派生出的 hold 一起记下来比对
    61444 0 7 75 / 103 到 185 标准里发动机需求扭矩(SPN 2432,偏移 -125)的位置。只读来打印,未发布 它应当跟随油门,并在油门松开瞬间转负
    65215 11 4 88 / 39 到 220 与车速 r = +0.84,偏移 125 = 零。若刻度成立,这是来自 ABS 模块的后轮速度——第三个速度源 一段已知急加速的抓包
    65265 11 0 2 / 63 到 127 标准:驻车制动 / 双速轴 / 巡航暂停,均为两位字段 一次受控测试
    61441 11 5 3 / 204 到 220 0xCC、0xCD、0xDC——与巡航开关字节相同的三个值,可能是镜像 停车按十分钟 SET 与 RESUME
    65265 0 6 2 / 240 到 241 241 出现在除六条之外的全部记录;240 出现过两次各约一秒 未知,价值低
    61445 39 4 2 / 32 到 83 标准 ETC2 字节 5 的变速箱字段;Indian 在此 PGN 已偏离标准(档位以 ASCII 编码放在字节 6) 未知,价值低
    65387 0 全部 无变化 钥匙开时发一次,作为对 SA 23 请求的应答 一段能触发新东西的抓包
    65388 23 全部 无变化 每次钥匙开时发一次,不是周期性的 同上
    65393 23, 39 全部 无变化(8 + 4 条记录) — 同上
    56832 23 全部 无变化(5 条记录) — 同上

    PGN 65382 的其余部分已经交出来了:字节 1 是转速除以 256(被撤回的「油门」),字节 3-4 是仪表显示的续航里程——十六位小端,字节 3 低、字节 4 高,一计数一公里,无缩放无偏移。所以 Indian 对发动机怎么运转还留着什么私货,最可能就在字节 0 里。

    一个仍未关掉的问题:油门字节有两个静止值

    PGN 65266 SA 0 字节 7(SPN 51)的解码本身已经定了,刻度也对:raw 250 恰好是 100.0%,正是 J1939 单字节百分比量程的顶端,全油门正落在上面。没定的是没人碰油门时阀片停在哪。车库里九小时、发动机从未启动的那一轮自己就证明了传感器只要点火开着就会报数——这个字节有 153 次变化。

    状态 中位数 最大
    发动机停转,低于 50 rpm 5.6% 到 6.0% —
    怠速,50 到 1200 rpm 4.4% 到 4.8% 12%
    骑行,高于 1200 rpm 9.6% 到 11.2% 100%

    停放着的机器读约 6%,这是阀片坐在怠速限位上而不是完全关闭,符合预期。不符合预期的是:同一天里这个字节还去过 0 到 1.6%,共二十六次,与正常的 4.0 到 4.8% 读数整天交替出现——不是另一次会话,两个簇在交替。发动机停着没人骑,阀片应该待在一个地方。候选有三个,都没测:回位弹簧没每次都把阀片留在同一位置;点火周期内传感器或 ECU 在首次真实读数前短暂报零;或者有别的东西在熄火状态下推动阀片,比如怠速执行器自检。

    已识别但故意不发货,以及确认不在总线上

    下面这些是已经看懂的,列出来是为了不让别人把它们当成未知,或者第二次去解它。

    PGN SA byte 它是什么 为什么不给字段
    65254 39 1, 2 时钟:分、时 快 12 小时 07 分,且不是显示屏上的那个钟
    65381 39 1,bit 2 / 4 / 6 转向灯开关左 / 右 / 取消,拨杆动作期间的一次短脉冲 灯本身已经从 65089 发货
    65386 39 1,bit 0 远光激活,全程保持 headlight 已经从 65381 取
    65276 23 1 组合仪表自己的油量读数 为了确定性选了 SA 0
    65265 39 6, 7 报文计数与校验和(SPN 524079) 不是信号
    65382 0 1 转速除以 256 —— 被撤回的油门 rpm 的粗副本
    65390 39 0 唤醒时的 DF 对 FF,同秒还有另外 8 个 PGN 在动 唤醒突发;总线活过来这件事本身说得更好

    「不在总线上」这一节有严格的入会条件:该信号必须在采集时被实际操作过且仍未出现。仅仅是「在它本来就不可能出现的数据里没出现」的,只能算未测。

    在总线上 不在总线上
    车速、档位、转速、胎压 喇叭
    灯、转向、危险警告 边箱锁
    刹车、巡航、加热手把 风挡电机(此地未装)
    倾斜、油量、温度 Trip 2

    规律是:这条总线承载的是别家模块需要的状态,不是便利性的作动。喇叭和边箱锁是「开关进模块、模块驱动自己的输出」,整条链路都在一个模块内部,没什么需要告诉别人。这也是为什么维修手册里 FMI 9「Abnormal Update Rate」格外有用。

    怎么读标准:FMI 9 是制造商的自白

    DTC 表列出部件、失效模式(FMI)与代码。多数失效模式描述的是一根线:开路、短路到 B+、电压过低。但 FMI 9 不一样。一个模块只有在「它期待某个信号周期性从别处来」的前提下,才可能抱怨这个信号来得太慢——在这台机器上,那个「别处」就是 CAN。所以每一条 FMI 9 都是制造商承认某信号被广播。整本手册里一共只有七条。

    SPN 信号 代码 本地状态
    84 Vehicle Speed Signal P160A 已发货 —— PGN 65265
    523 Gear Sensor Signal P1914 已发货 —— PGN 61445,也是档位突变日志的对象
    5582 Static Roll Angle P1062 已发货 —— 几乎可以确定就是 PGN 2304 的倾斜字节
    520300 Tire Pressure Sensor (Front) C1085 已发货 —— PGN 65268
    520302 Tire Pressure Sensor (Rear) C1090 已发货 —— PGN 65268
    520329 Operator Switch Status(pOSS1) P1063 部分回答:PGN 65381 的字节 1 位 2/4/6 是转向灯与取消,字节 2 位 0 是危险警告;2026-09-18 又发现字节 0 的两颗手把按键。但报文是专有的,无法证明它就是标准参数
    520330 Immobilizer P106A 已找到并发货 —— PGN 65386 SA 39 字节 0 位 6-7

    其中 SPN 5582 是一次安静的确认:倾斜值是先从 PGN 2304 里经验性地找到、并因看起来像而命名为「tilt」的,手册叫它 Static Roll Angle,来源是 SPN 520296「Accelerometer」。信号是真的,按设计就在总线上,我们读它这件事有了一个名字。

    手册还有两条限制要记住。其一,手册覆盖七款车而不是这一辆,DTC 表是七款的并集——SPN 520294/520295「Windshield Motor Driver / Switch」是 Chieftain 与 Roadmaster 的部件,Springfield 的挡风玻璃是快拆手动的;先确认车上有没有这个件再去追它的信号。其二,诊断码只能证明模块「知道」某个信号,不能证明它把它广播出来:前刹车开关是 SPN 520322、后刹车是 520323,两个都真实且有名有姓,但它们是一根根线进模块的,模块之后有没有把它们放上总线,是手册不回答的另一个问题。巡航那一节正是栽在这条上——出现在表里不等于出现在线上。

    常见问题

    这份计划有没有 DBC?

    没有。上游没有 DBC,这份材料是一份站得住的优先级清单加方法记录。它给出的是 PGN、源地址、字节位置、实测取值范围、已试过的动作和被推翻的假设,要落成 DBC 还得自己把每条信号按同样的受控动作再走一遍。

    42,365 帧能不能换算成报文速率?

    不能。固件只在某个 ID 的载荷与上一帧不同时才发布该帧,抓包记录的正是这条变化流。所以「帧数」是变化次数而不是发送次数:推导不出报文速率,也分不开周期性与事件驱动。唯一仍然成立的是「跨 N 条记录恒定」,但它不是关于 N 次发送的陈述。

    巡航「已接合」状态到底能不能读到?

    从 SA 39 读不到。2026-09-05 路试中巡航确实在保持(94、87、73 km/h,手离开手把),其 CCVS 字节 4 恒为 0xF7,位 0-1 始终是 11;设定车速字节在所有 SA 39 帧里恒为 0xFF。于是固件派生了一个 `cruise`:一次 SET 或 RESUME 按下配合摇臂开且不低于 35 km/h 进入待定,三秒内车速稳定在 3 km/h 以内确认;刹车、离合、摇臂关闭或偏离目标超过 6 km/h 持续两秒退出。取值写 HOLDING 而不是 ON,用一个词把「这是推断」标在数据里。

    SA 136 是什么?

    它声明了与组合仪表相同的功能(19)但不同的制造商代码(146,仪表是 340),而且在 42,365 帧里除了自己的地址声明之外什么都没发过;声明次数还是别人的两倍(四次骑行共 8 次)。最可能是边箱锁模块——Polaris 车身侧锁模块的描述正是「点火时声明地址,之后只在锁 / 解锁时发送」。前半句完全吻合,后半句被测量推翻:三次运行、每个字节都可见、执行器确实在动作,SA 136 一个字节都没发。要直接点名,需要查一下制造商代码 146。

    「不在总线上」和「未测」怎么区分?

    进入「不在总线上」需要该信号在采集时被实际操作过且仍未出现;仅仅在「它本来就不可能出现的数据里没出现」的,只能算未测。巡航条目就踩过这个坑:字节一直读 not available,但那四次骑行里巡航从来没接合过,所以那一节原本没有资格收录;直到 2026-09-05 的路试才把它坐实为 SA 39 一家的确认缺失,而不是整条总线的结论。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/docs/DECODE-PLAN.md(30 个 PGN 分组、地址声明、仍开放清单与优先级表)
    • 项目 01 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/docs/UNEXPLORED-BYTES.md(逐字节实测取值范围、油门双静止值与请求墙说明)
    • 项目 01 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/README.md(车辆与适用车型范围、不在总线上的确认清单与胎压换算方法)
    • 项目 01 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/SOURCE.md(固定修订、许可条款与范围限制)

    免责声明

    本文所述信号定义均为社区逆向工程产物,不代表车辆制造商的官方数据,且全部来自一辆 2017 Indian Springfield。手册覆盖的 Chief、Dark Horse、Vintage、Chieftain、Roadmaster、Elite 六款未直接测量,跨车型推断的依据是车主对车系的了解而非实测;Scout 与 FTR 是另一台发动机,不在范围内。固件运行在硬件只听模式,不发送任何帧,因此 DM2、DM4 等按需应答的数据不可能出现在现有抓包里。文中代码路径与候选字段不构成厂商规范。涉及安全相关用途时请仅作参考。

    更新记录

    • 2026-10-15 初稿

  • 菲亚特 Ducato X250 车身 CAN:五组抓包能还原出什么

    结论:这辆 Ducato X250 的 OBD 6/14 脚上只有 50 kbit/s 的车身 CAN,500 kbit/s 一帧都没有。五份抓包(30 s 到约 20 min)覆盖钥匙静态、车门与灯光、开关动作、冷启动加油到 7 km 实路行驶,总线共 18 个 ID、约 90 帧/s,19 条已验证解码逐条与仪表、GPS 或 OBD PID 对过。增压压力、发动机负荷、进气温度与故障码不在这条总线上——它们在 7 脚的 K 线上。

    五组抓包样本矩阵:每档各解决一类问题

    抓包是用仓库里的 tools/slcan_capture.py 通过 TCP 23 口连上只听模式的适配器录的,脚本先发 C(关通道)、S2(50 kbit/s)、L(只听),随后每帧写成一行「启动后秒数 + slcan 帧」,例如 t28180080803800000000 即 ID 0x281、DLC 8、后接八个字节。时间戳是相对的,不含位置信息。

    决定一份抓包能还原什么的是工况,不是文件体积。常发帧识别、开关类位分离、随动模拟量拟合、随负荷变化的量验证,各需要不同的一档;下面这张表按「不可替代性」分档,缺任何一档都会让相应的一类信号失去证据。

    抓包文件 时长 工况 能取到的数据 为什么这一档不可替代
    01_ignition-on_engine-off 30 s 钥匙拧到 MAR,全程不碰任何开关 静态基线与常发帧清单:0x281 20 Hz、0x286/0x2A0 10 Hz、0x180/0x380/0x39A 4 Hz、0x3C3/0x3E0 2 Hz、0x603/0x643/0x683 1 Hz;冷车水温与静态电瓶电压 唯一能界定「哪些帧与操作无关」的一档。没有它,后面的字节差分会把常发噪声当成动作响应
    02_doors_and_lights 300 s 车门逐个开合,示宽灯、近光、远光、闪光各一遍 0x380 的手刹 / 车门 / 倒挡 / 电瓶电压 / 低油量告警 / 油量;0x180 的示宽灯、近光、远光、后雾灯 灯光位只在原地逐个打才能分离;行驶中它们与负荷、电压混在一起
    03_misc-actions 420 s 转向灯、刹车踏板、驻车制动及其它开关 0x180 的刹车踏板(b0 bit 7)与左右转向(0x40 / 0x20 随闪光翻转)、0x380 b0 bit 5 手刹、0x39A b2 bit 0 安全带 转向灯是「闪烁」而非电平,只有这一段能看到周期性的位翻转,从而与常亮的示宽灯区分
    04_engine-idle_revs 180 s 冷启动,怠速约 800 rpm,再分别点油门到约 2000 与约 3000 rpm 0x281 的转速 / 水温 / 发动机在转判据;怠速与加油时的电压变化 转速刻度与「发动机在转」的判据只能靠怠速加两段加油对照,静态档给不出斜率
    05_short-drive 约 20 min 7 km 城镇 / 乡村路段,最高约 80 km/h 0x286/0x2A0 车速与 GPS 对照;0x603 里程与续航;0x643 小计(平均油耗、平均车速、时间、距离);0x683 仪表时钟 唯一带车速变化的一档。里程增量(7 km 行程后 +7 km)也只有这一段能验

    18 个 ID 的已验证解码

    参考表的口径:总线为车身 CAN(B-CAN),OBD 6/14 脚,50 kbit/s,11 位 ID,18 个 ID,约 90 帧/s。b0 是第一个数据字节,位号 7(最高位)到 0。每条解码都在车上对照过仪表、GPS 或重复动作,没有一条是仅凭取值范围猜的。

    ID 速率 DLC 信号 解码 怎么验的
    0x180 4 Hz 6 刹车踏板 b0 bit 7 踩踏板
    0x180 示宽灯 b1 bit 5 灯光开关
    0x180 近光灯 b1 bit 3 灯光开关
    0x180 远光 / 闪光 b1 bit 4 拨杆
    0x180 左 / 右转向灯 b2 = 0x40 / 0x20,随闪光翻转 拨杆
    0x180 后雾灯 b1 bit 1(仅在开灯时有效) 开关三次
    0x281 20 Hz 8 发动机在转 用「转速大于 300」,不要用 b1 bit 7 三次钥匙测试(仅钥匙开、启动、运转后熄火)
    0x281 冷却液温度 b3 减 40,摄氏度 水温表指针居中时读 81
    0x281 发动机转速 (b6 乘 256 加 b5)除以 8 怠速约 830,点油门 1800 / 3000
    0x286 10 Hz 8 车速 (b2 乘 256 加 b3)除以 16,km/h 四段匀速与 GPS 差在 1% 以内
    0x2A0 10 Hz 4 车速(副本) (b0 乘 256 加 b1)除以 16,km/h 同 0x286
    0x380 4 Hz 8 驻车制动 b0 bit 5 手刹杆
    0x380 车门 b1 等于 0x0C 表示任一门开,0x00 全关 驾驶室门、生活舱门、储物舱共用一个回路
    0x380 倒挡 b2 bit 2 进出倒挡三次
    0x380 启动电瓶电压 b3 乘 0.16,V(0x53 = 13.3 V) 20 min 行驶中对照启动电瓶库仑计
    0x380 低油量告警 b4 bit 1(0x02 进入储备区,否则 0x00) 仪表储备灯亮时读 0x02
    0x380 油量 b5,升 满箱 90 L 读 91;本车 23 对应 26%
    0x39A 4 Hz 8 驾驶员安全带 b2 bit 0,1 = 未系 插拔三次
    0x3C3 2 Hz 8 驾驶员安全带(副本) b4 bit 1,同 0x39A 同上
    0x603 1 Hz 8 总里程 20 位:b1 低半字节 + b2 + b3,km 61744 = 仪表;7 km 行程后 +7
    0x603 续航里程 11 位:b4 的 bit 2-0 + b5,km 272 = 仪表
    0x603 瞬时油耗(待行驶中验证) b0 + b1 高半字节,BCD,L/100km(11 6x = 11.6) 怠速时与仪表小计一致;随负荷变化
    0x643 1 Hz 8 小计平均油耗 b0 + b1 高半字节,BCD,L/100km 11.7 = 仪表
    0x643 小计平均车速 b2,km/h(截断) 48 = 仪表;等于距离除以时间
    0x643 小计时间 b3 小时、b4 分钟,BCD(47 37 = 47 小时 37 分) 仪表;分钟从 19 跳到 20
    0x643 小计距离 20 位:b5 + b6 + b7 高半字节,乘 0.1 km 2329.2 = 仪表;复位后 0.0
    0x3E0 2 Hz 4 启动电瓶电压(副本) b1 乘 0.16 V,同 0x380 b3 同上
    0x683 1 Hz 6 仪表时钟 b0 小时、b1 分钟,BCD(16 50 = 16:50) 仪表时钟(本车慢约 3 分钟)

    三处「看起来能用、实际会错」的位

    0x281 b1 bit 7 只在点火开且发动机停时为 1,熄火最后一帧它读「在转」,行驶结束后 ECU 还会继续发约 20 s;三种钥匙测试下都以「转速大于 300」为准。0x603 b4 bit 3 是发动机运转标志位,做续航时必须排除,否则会得出 2265 km 这种数。车门位 0x380 b1 只回答「有门开着」,房车改装上驾驶室门、生活舱门与储物舱在同一回路,无法区分。

    灯光的另一个工程约束:同一 ID 上挂三条位条目在 0x281 上能工作,但测试里 0x180 上分离的位条目发布并不可靠,所以灯光、刹车踏板与转向灯在适配器里被合成一个 24 位的 raw_180 值发布,拆位留到 Home Assistant。过滤器文件的字段口径也要注意:CANID 用十进制(641 = 0x281),StartBit 从 b0 的最高位算起(b0 的 bit 7 是 0,b1 的 bit 7 是 8),Expression 里 V 是取出的值、B5 是字节 5。

    证据边界:不在这条总线上,以及会骗人的那一帧

    这套数据最有价值的部分之一,是它明确标注了「测不到」的地方。下面每一条都是试过之后的结论,不是「没看到就等于没有」。

    边界类型 具体情形 处理动作
    总线静默 钥匙拔出后总线完全静默,停车状态读不到任何东西 实时传感器设 expire_after: 15,让它变成 unavailable 而不是冻在旧值
    假帧 钥匙关闭前的最后一帧是假的:油量 0、手刹释放、发动机仍显示运转 不要把任何自动化建在 key-off 边沿上
    错误判据 0x281 b1 bit 7 不是「发动机在转」 一律用转速大于 300 判定
    位污染 0x603 b4 bit 3 是运转标志,参与续航解码 做 11 位续航时排除该位
    回路合并 车门状态只有一个共用回路 只能读「有门开着」,不能定位到具体门
    协议外 增压压力、发动机负荷、进气温度、故障码走 7 脚 K 线(ISO 14230-4 KWP2000) 只带 CAN 的适配器看不到;电瓶电压改看 0x380 b3(车身电脑视角)
    波特率 6/14 脚只有 50 kbit/s 的车身 CAN,500 kbit/s 无帧 50K 是唯一可用档位,模式设 Silent(只听)

    常见问题

    这五份抓包能直接当 DBC 用吗?

    不能。它们是 slcan 文本行(相对秒 + 帧),仓库里没有 DBC。仓库提供的是 tools/decode.py,只解已知信号、只输出变化行,并带 --test 自检。要把抓包变成 DBC,得自己按 ID 做字节差分,再逐条与仪表、GPS 或 OBD PID 对照。

    为什么钥匙拔掉之后一个数据都读不到?

    因为这条车身 CAN 在钥匙离开 MAR 之后完全静默,停车时没有任何帧可听。这不是适配器的问题,是车辆本身的行为,所以任何「停车监控」类的需求在这条总线上都不成立,传感器只能走过期置为 unavailable 的路子。

    车速有两个来源,该用哪一个?

    0x286 的 b2/b3 与 0x2A0 的 b0/b1 都是车速,都除以 16 得 km/h,区别只在 DLC(8 与 4)与所属报文。两者结果一致,与 GPS 对照的偏差在 1% 以内,任选其一即可,但不要在同一条链路上混用而忽略 DLC 差异。

    油量 0x380 b5 为什么不能当百分比用?

    因为满箱 90 L 的箱子上它读到 91,如果是百分比应该接近 100。它的单位接近升,但零点还没在这辆车上最终确认(本车 23 对应 26%,OBD 燃油 PID 给 24%),且钥匙关闭帧里读 0。作为趋势量可用,作为绝对值要谨慎。

    能不能靠这些抓包拿到增压压力或故障码?

    不能。这两类数据在发动机 ECU 的 K 线上(OBD 7 脚,ISO 14230-4 KWP2000),需要主动发请求才会应答。这里全部是只听模式,从不发帧,因此它们不可能出现在抓包里。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/danderik88-fiat-ducato-x250/captures/README.md(五份抓包的时长、工况与录制格式)
    • 项目 01 —— public-can-dbc-datasets/additional/danderik88-fiat-ducato-x250/docs/can-id-reference.md(18 个 ID、速率、DLC、逐信号解码与验证方式)
    • 项目 01 —— public-can-dbc-datasets/additional/danderik88-fiat-ducato-x250/README.md(车辆配置、OBD 引脚分配、Gotchas 与免责声明)
    • 项目 01 —— public-can-dbc-datasets/additional/danderik88-fiat-ducato-x250/tools/slcan_capture.py(S2 = 50 kbit/s、L = 只听的初始化序列)

    免责声明

    本文所述解码均为社区逆向工程产物,不代表车辆制造商的官方数据,且全部来自一辆 2009 年 Ducato X250(2.3 MultiJet,Elnagh Prince 55L 房车改装,意大利市场)。同平台另有 Citroën Jumper 与 Peugeot Boxer(2006–2014),但只有文中这辆 Ducato 实测过。不同车型年款、市场与 ECU 版本可能存在差异。文中所有操作均为只听,不向总线发送任何帧;连接任何设备到车辆 OBD 口的风险由操作者自行承担。涉及安全相关用途时请仅作参考。

    更新记录

    • 2026-10-15 初稿

  • VTRUX 与 Coda 的 CAN 解码笔记:信号、电芯索引与验证方法

    结论:这份笔记覆盖九份 DBC、合计 238 条报文与 1,066 条信号,分属 Coda 的 B/C/D 三总线、VTRUX 的 OBD/PT 两总线、Bel 逆变器的 J1939 扩展帧,以及一辆 1975 Porsche 914 改装车的自定义 VCU 遥测。它的价值不在清单本身,而在把「反编译出来的标签」和「验证过的信号」分成五档,并如实记录了一次被纠正三次的电芯索引映射与八条被推翻的假设。

    九份 DBC 的量级与定义来源

    仓库统计明确说明:下面的报文 / 信号数来自拷进来的 DBC 文件本身,而不是上游 README 的表格——后者已经过期。Coda 的 B、D 两总线在上游 README 里写的是 35 和 22,实际文件是 34 和 23;914 的 README 还在描述一份 75 报文 / 496 信号的 schema 3.0,而文件已经是 schema 4.2、hash 0x09EB175A。

    DBC 文件 报文 / 信号 总线 定义来源 证据边界
    CODA-B-CAN.dbc 34 / 156 B CAN 原厂 CODACAN LabVIEW 诊断应用 + 实车抓包 上游 README 的 35 为过期值,以文件为准
    CODA-C-CAN-cells.dbc 26 / 104 C CAN 26 帧 0x000–0x019,每帧 4 个 16 位 Motorola 电芯,1 mV/bit 电芯编号自 2026-07-22 起改为 1-based
    CODA-D-CAN.dbc 23 / 44 D CAN LabVIEW 反编译 + 日志 上游 README 的 22 为过期值
    epri-obd-bus.dbc 12 / 18 OBD EPRI Logger iPhone 应用的 Ghidra ARMv7 反编译,再用车辆日志比对修正 字节位置与刻度并非一律正确
    epri-pt-bus.dbc 26 / 101 PT 同上 同上
    vtrux-obd-experimental.dbc 3 / 5 OBD 作者由日志推导的实验性定义 含未解析报文桩
    vtrux-powertrain-experimental.dbc 19 / 26 PT 同上 同上
    BelInverter-v2.dbc 8 / 73 J1939 扩展 ID EPRI 结论 + 一份更早的 DBC 合并 原始作者与部分字节布局未确认
    914-telemetry.dbc 87 / 539 自定义 VCU 遥测 改装 914 的 VCU 映射,非原厂 Porsche 协议 标准 11 位 ID 为真实车辆帧;29 位扩展 ID 为 VCU 串行遥测里的内部合成值

    确认档位:怎么区分「反编译出来的」和「验证过的」

    这份仓库最值得抄的一点是它不给信号打勾,而是打档。反编译只能告诉你应用把哪个字节当什么读,不能告诉你它读对了;日志相关只能告诉你两件事一起动,不能告诉你它们是不是一件事。于是每条信号都落在下面五档之一,档位直接写在验证表里。

    档位 含义
    CONFIRMED 编码与角色都被独立验证过:物理测试、行为日志证据、与已知参考相关、或跨 DBC 比对一致
    CONFIRMED-SYMM 靠与某个 CONFIRMED 信号的结构对称性确认,没有独立测试
    CONFIRMED-DECOMPILE 编码由 Ghidra 确认,角色只是应用自己的标签,没有独立物理或行为检查
    PARTIAL 编码确认,角色或刻度还有一条具体问题挂着
    REMOVED 按 DBC 信号策略删掉 SG_ 条目,原因记在 CM_ 注释里

    档位不是形式主义

    PT 总线上 0x0054 的 GENE_EmergcyStp_flg 是 CONFIRMED-DECOMPILE:Ghidra 里写着 (pbVar15[6] 与 8) 不等于 0,但所有日志里它一次都没触发过,没有行为测试。同理 0x0580 的 tcm_CAN_ERR。这类条目可以读,但不能当成「已经证明这个位是这个意思」来用。

    0x381 与 C CAN 电芯索引:一条被纠正了三次的映射

    C CAN 只在少数几次采集里被同时录下(需要第三个适配器),所以能回答这个问题的只有三份日志。总线识别靠内容而不是总线号:0x000–0x019 的电芯帧是 C CAN,0x381/0x382/0x383/0x390/0x439 是 B CAN,0x308/0x312/0x325/0x330/0x55C 是 D CAN——两次会话给同一条物理总线编的总线号并不一致。

    会话 日志 配对样本 偏移 +1 严格命中率
    2026-07-21 Android 三适配器 coda_20260721_192435_T0..T2、_201109_T0/T1、_202031_T0 660 82–87%
    2026-02 Bonnydoon 行驶 33 min projects/coda/logs/frombonnydoon.log 1,972 80–84%
    2026-07-22 充至 100% coda_20260722_173203_T0..T21 979 100%

    合计 43 万帧以上的 C CAN 电芯帧、8,300 帧以上 0x381、3,600 对以上时间配对样本,且配对时刻 C CAN 数组完整、没有帧旧于 2 秒。充电会话最干净:负荷低而稳,电芯在 B 与 C 两轮扫掠之间几乎不重排,严格测试在 VmaxId(591 样本)与 VminId(706 样本)上都命中 100.0%。

    会话 信号 严格样本数 命中偏移 +1 不同 ID 数 ID 范围
    Android VmaxId 135 82.2% 11 6–104
    Android VminId 146 87.0% 26 1–101
    Bonnydoon VmaxId 225 79.6% 44 6–104
    Bonnydoon VminId 376 84.3% 33 1–104
    充电 07-22 VmaxId 591 100.0% 2 82–95
    充电 07-22 VminId 706 100.0% 1 96

    「严格」的口径是:只保留 C CAN 数组自身的极值恰好等于所报极值、该极值由唯一一只电芯持有、且领先第二名至少 3 mV 的样本。行驶会话里没有任何竞争偏移超过 4%;剩下约 15% 也不是反例——两条总线不是同时采样的,C CAN 扫完 26 帧要约 800 ms,而 0x381 只有约 1.1 Hz,行驶中负荷波动会在两个时刻之间把几乎并列的电芯重排。签名也说明这是偏斜而不是置换:未命中的配对集中在少数几个本来就常年处于极值的 C CAN 索引上(max 侧 81/83/94/102,min 侧 76/80/95),真置换会把它们撒满整个数组。

    三次纠正各纠正了什么

    第一次是编号口径:映射被发现时 C CAN DBC 还是 0-based,关系是「上报 id 等于旧索引加 1」;2026-07-22 改为 1-based 后加 1 消失,两套编号重合。这也推翻了更早那句「id 用的是与 C CAN 位置无关的 BMS 内部编号」——BMS 编号就是 C CAN 的发送顺序(1-based)。

    第二次是字节序。2026-07-15 之前 0x381 的归属是 B0-1=MinCellVoltage、B2-3=MaxCellVoltage、B4-5=AvgCellVoltage、B6=VminId、B7=VmaxId;修正后是 B0-1=Avg、B2-3=Max、B4-5=Min、B6=VmaxId、B7=VminId。当年的错误来自照着 LabVIEW cluster 的名字「VminVmax」排,而不是按 LabVIEW 字段顺序 Vavg、Vmax、Vmin、VmaxId、VminId。重跑严格测试可以量化这两种读法的差距。

    归属方式 Android 样本 / 命中 +1 Bonnydoon 样本 / 命中 +1
    修正后 max — 值 B2-3,id B6 135 / 111(82.2%) 225 / 179(79.6%)
    修正后 min — 值 B4-5,id B7 146 / 127(87.0%) 376 / 317(84.3%)
    旧 max — 值 B2-3,id B7 135 / 0(0.0%) 225 / 1(0.4%)
    旧 min — 值 B0-1,id B6 0 / 0 0 / 0

    两端的失效并不对称。min 侧当时根本没有信号可用:旧的 MinCellVoltage 读 B0-B1,而那其实是包平均值;平均值几乎不可能唯一且带余量地等于某一只电芯,所以两次会话里都是零样本存活,没有东西可相关。min 侧还有第二个错:id 也取自错误的字节(B6 其实是真正的 VmaxId)。max 侧则是「值对、id 错」:B2-B3 在两种读法下都真是最大值,但索引来自 B7(真正的 VminId),于是正确的最大电压配上了最小电芯的编号,噪声里最好的偏移只有 21%——读起来很像「另一套编号约定」,非常容易被误判。

    第三次是对比方式。frombonnydoon.log 同时带 C CAN 与 0x381,它自己的 0x381 报 VminId 95 / VmaxId 84,正是那次笔记已经点名的两只电芯。也就是说这条映射在单份日志内部就可验,而当时的笔记却拿它们去和另一次(充电)会话的 96/76 比,把差距读成了编码差异。结论成了方法:只要两条总线同时在场,就在同一会话内部比。

    还有一条适用范围限制:本节的「+1」只适用于经 DBC 从原始字节解出来的值。从 CODACAN 界面截图上读到的数字(如充电分析里的 VminId=96 / VmaxId=76)来自 LabVIEW cluster,它一直是对的,不受 DBC 错误影响。哨兵值 255 也要单独处理:104 只电芯的包里 255 不可能是索引,它是无效 / 无数据哨兵,不要当成「第 254 只电芯」。

    证据边界:部分解码、未解与已推翻

    「已确认且完整」的信号有其编码摘要,例如 0x275 BMSDriveLimits 的 B0 = 放电限值(uint8 乘 2 得 A)、B1 = 充电限值(乘 2 得 A)、B2-B3 = 包电流(BE uint16 乘 0.1 A,零点 0x8000)、B4-B5 = 包电压(BE uint16,1 V/bit)、B6 = HVAC 限值(乘 2 得 A)、B7 未知(基线 0xDD)。下面列的是还没收口的。

    ID 名称 已知 还缺什么
    0x050 BMSChargerCmd B0-B1 = HVCurrentCmd(BE uint16 乘 0.1 A,R2 = 0.992;基线 0x00DC = 22 A);B2-B3 = MaxVoltage(乘 0.1 V,R2 = 0.605;基线 0x0FF7 = 408.7 V);中位帧 00 dc 0f f7 00 01 3e 01 B4-B5 取非基线值会把 Main Current 压到约 6 A,疑似帧校验或滚动计数;B6-B7 未知;需注入测试
    0x270 BMS_FaultStatus B0 为故障字节(0x00 无故障,0x12 = 故障码 18,bit 1 = 0x02 与 bit 4 = 0x10 置位);比 0x271 早一帧;drop 后 CODACAN 的 BMS Fault Severity 掉下去 B0 内部故障码与严重度的分界未扫;B6-B7 未知
    0x2C1 BMSDrivingRange B0 状态字节(raw = 0x70 时翻转);B1 / B3 / B5 分别为 Exp / Max / Min,R2 约 0.96–0.97;比例暂定约 1.1 乘 raw 减 19 刻度 / 偏移未精确确认;B2、B4、B6-B7 未扫;单位可能是英里
    0x330 Long_Accel 被抑制时会掉,但与噪声边界模糊;VICD 刻度为有符号字节乘 0.08 m/s² 未确认为模拟量;需要一次含急刹的行驶事件做时序提取
    0x383 BMSBattStatus SoC 在 B0-B1(BE uint16 除以 10 得 %)已确认;同时带 HVBattCharging、ChrgPortOpen、ChargeCableConnected 三个布尔位的确切位号未记录
    0x410 AC_Compressor_Command B2 = compressor_on_off / CASS_on_off / warmup_cycle_cntr_incr;B6 = 目标转速(乘 60 rpm/bit);B7 = 最大功耗(乘 0.1 kW/bit) B0 的三个布尔位(HVAC FaultRed、FaultYellow、KeepWakeNetworkHVAC)位号未解;也可能是扫描引起的 ECU 响应假象
    0x241 MCM_Thermal 角色已确认:drop-ID 后 Rotor / Stator / IGBT 三个字段归零;DLC = 8 已由日志确认 逐字节归属未确认;偏移假定为减 40 摄氏度;B4 恒为 0x00,疑似哨兵或非温度字段
    0x491 / 0x273 IPK 帧 两者都带 Primary ODO(km)、Interior Illum、Side Light Active、Low Beam Active;0x491 还会点亮 Overview 的 IPK 指示,0x273 不会 ODO 的字节位置与编码(可能是 BE uint24 或 uint32);灯光的位号

    八条被推翻的早期假设

    这些条目都曾写进笔记或报告,后来被数据推翻。留着不是自曝,而是让下一个人不用再踩一遍。

    早期假设 更正为
    0x212 = EPS_SAM_1(转向角,0.25 deg/count) 0x212 = DLCM Torque Request;转向角在 0x080
    0x210 = Vehicle_Mode 含 VBatt(乘 0.4 V/count) 0x210 B2 = ThrottlePedalPos(乘 0.4 %/count)
    0x271 = Death Counter 的一部分(整数字节计数) 0x271 = GWM 心跳 + VehFaults 的源
    0x55C = VehFaults(3 字节:灯 / 严重度 / 故障字) 0x55C = TCM 心跳
    0x381 = BMSDriveLimits 候选(哨兵 1000.0 A) 0x381 = BMSVminVmax;BMSDriveLimits 在 0x275
    0x382 B0 = 充电阶段计数器(0x8B 到 0x8E 步进) B0 = Cell_T_avg;充电过程中包升温时为 11–14 摄氏度
    0x275 B4 = HV Active 布尔标志 B4-B5 = PackVoltage(BE uint16,1 V/bit);104 串 LFP 包始终使 uint16 的最高位置位
    BattSentDischargeLimit / ChargeLimit 刻度 = 1 刻度 = 2(uint8 乘 2 得 A)

    常见问题

    反编译出来的 DBC 能直接拿来解日志吗?

    不能直接。反编译只证明应用把某个字节按某种方式读,不证明它读对了。所以这里把信号分成 CONFIRMED、CONFIRMED-SYMM、CONFIRMED-DECOMPILE、PARTIAL、REMOVED 五档,只有前两档带独立验证,第三档只是「应用自己这么命名」。

    电芯编号到底是 0 起还是 1 起?

    C CAN DBC 自 2026-07-22 起改为 1-based(Cell1 到 Cell104),与 BMS 自己的 VmaxId / VminId 直接对应,VmaxId 82 就是 Cell82。此前是 0-based,老 CSV、老图、老导出都要加 1 才能对上,例如旧 Cell94 等于现 Cell95。MinTempId / MaxTempId 是另一套索引,不受影响。

    为什么 0x381 的映射要改字节序?

    因为最初的归属照着 LabVIEW cluster 的名字「VminVmax」排,把 Min 与 Avg、VminId 与 VmaxId 都放反了;按 LabVIEW 字段顺序应是 Vavg、Vmax、Vmin、VmaxId、VminId。重跑严格测试后,旧的 max 读法命中 0.0%,旧的 min 读法零样本存活,修正后分别是 82.2% 与 87.0%。

    偏航率刻度为什么判不出来?

    两种说法分别是 0.0045(转向角 / 轴距运动学模型)与 0.003924(后轮差速几何法),但它们不是两条独立标定:同一几何法随速度窗口与轮距取值会给出 0.00347 到 0.00488。系统误差预算合计 43.4%(左右不对称 34.1%、速度窗口 21.5%、旅程间 16.0%),远大于两者相差的 14.7%,因此只能记为「判不出」。

    这份素材的许可证状况如何?

    被检查的上游快照里没有许可证文件,本文所依据的是一份离线私有研究副本。公开仓库可访问并不等于取得再分发或制作衍生作品的权利,对那些从第三方应用推断出来的定义尤其如此。共享或商用之前应与相关权利人确认。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/nickyivyca-vtrux-coda/SOURCE.md(九份 DBC 的报文 / 信号数与权利边界)
    • 项目 01 —— public-can-dbc-datasets/additional/nickyivyca-vtrux-coda/projects/coda/notes/codacan-signal-decode-notes.md(CODACAN 台架方法、分阶段完成表、模块在位映射与已推翻假设)
    • 项目 01 —— public-can-dbc-datasets/additional/nickyivyca-vtrux-coda/projects/coda/notes/cell-index-mapping.md(0x381 VmaxId/VminId 与 C CAN 电芯数组的三次纠正与严格测试口径)
    • 项目 01 —— public-can-dbc-datasets/additional/nickyivyca-vtrux-coda/projects/vtrux/notes/epri-verification.md(PT 与 OBD 总线的逐信号确认档位与 Gap)

    免责声明

    本文所述信号定义全部来自社区逆向工程,不代表车辆制造商的官方数据。Coda 与 VTRUX 两家整车企业均已退出市场,无原厂文档可核对;VTRUX 的 EPRI 定义最初由一款 iPhone 日志应用的二进制反编译重建,再用车辆日志比对修正,字节位置与比例并非一律正确。上游快照未包含许可证文件,公开仓库可访问不构成再分发或衍生权利。涉及安全相关用途时请仅作参考,并以实际测量为准。

    更新记录

    • 2026-10-15 初稿

  • 用 SavvyCAN 示例数据集复现 CAN 分析流程:三份 DBC 与 12 种格式

    结论:SavvyCAN 自带的 examples/ 目录是最小成本的复现环境:三份示例 DBC 分别是 10 报文 22 信号的动力总线样本、501 报文 548 信号的大规模档案、6 报文 31 信号的部件级总线,量级相差约 80 倍,正好覆盖「小规模逐条核对—大规模过滤检索—部件级拓扑」三类分析动作。采集硬件并非必需,工具能直接读写 12 种日志格式(其中 3 种只读),因此用示例数据就能把整条流程走通。需要注意的是:三份示例都没有独立的年款适配与信号验证记录,且其中一份大规模档案在归档里还有 502 报文 761 信号的后续修订版,两者应按不同来源快照分别留存。

    三份示例 DBC:量级差 80 倍,用途完全不同

    把三份示例放在一张表里看,最直观的不是报文数,而是它们的性质差异:LeafPowertrainBus.dbc 是标注为 Leaf 的动力总线样本,规模小到可以逐条人工核对;ThinkCity.dbc 是 501 条报文的城市车档案,价值在于压测过滤与检索;bms.dbc 只有 6 条报文却命名了 EVTVBMS、GEVCU 与逆变器三类部件,是典型的部件级总线示意。

    示例文件 报文数 信号数 文件性质 证据边界
    LeafPowertrainBus.dbc 10 22 标注 Leaf 的动力总线示例 代数、年款、硬件与信号验证均未记录
    ThinkCity.dbc 501 548 标注 Think City 的大规模档案 并非每条报文都确立了车型年款适用性
    bms.dbc 6 31 部件级示例,含 EVTVBMS、GEVCU、逆变器 通用部件示意,不是某款整车的原厂 DBC
    归档中的 ThinkCity_modified6.dbc 502 761 同名的后续大幅扩充修订版 与上一行是两个来源快照,不可互相覆盖

    第四行值得单独说明:501/548 与 502/761 只差 1 条报文,信号数却差了 213 条。这说明后者的修订主要集中在信号定义而非报文条目扩充。归档时的正确做法是把两者当作独立快照各自留存,而不是用新版本替换旧版本。

    用示例数据复现分析流程:每个文件演示什么

    三份示例对应三种不同的分析动作。小规模样本适合验证「DBC 定义与原始字节是否自洽」,大规模档案适合验证「过滤、分组与检索是否好用」,部件级示例适合验证「多设备报文关系能否被正确建模」。把它们按这个顺序跑一遍,就能在不接硬件的前提下判断工具链是否完整。

    分析动作 推荐示例 可验证的能力 演示不了什么
    逐条核对信号定义 LeafPowertrainBus.dbc 报文清单浏览、信号曲线绘制、缩放与偏移是否自洽 代数与年款适配判定
    大规模检索与过滤 ThinkCity.dbc 按 ID 区间过滤、按报文名搜索、大文件加载与刷新性能 逐条物理值的实测验证
    部件级拓扑建模 bms.dbc 多设备(BMS、整车控制器、逆变器)报文归属与发送关系 整车级网络拓扑与网关行为
    格式往返一致性 任意一份 + 日志导出 导入后再导出,比较 ID 与数据字节是否逐帧一致 时间戳在不同格式间的保真度差异
    来源快照比对 ThinkCity.dbc 与修订版 同名报文在两版之间信号数变化的对比 哪一版更接近原车的判定

    为什么「导入再导出」是最先该跑的一条

    这条流程不需要理解任何信号含义,只需要比对 ID 与 8 个数据字节是否逐帧一致。它能一次性暴露三类问题:格式解析器的边界处理、扩展帧与标准帧的区分、以及多帧时序是否被保留。在这条通过之前,后续任何信号级分析都建立在不可靠的输入上。

    十二种读写格式:九种可写,三种只读

    工具的定位是「加载、保存与采集 CAN 帧」,用于可视化、逆向、调试与抓包。它明确说明采集设备并非必需,因此格式支持清单直接决定了它的离线分析能力边界。清单里前九种可读写,后三种只能读。

    序号 格式 读写能力
    1 BusMaster 日志文件 读 + 写
    2 Microchip 日志文件 读 + 写
    3 CRTD 格式(OVMS 日志格式) 读 + 写
    4 GVRET 原生格式 读 + 写
    5 通用 CSV(ID 加 D0 到 D7) 读 + 写
    6 Vector Trace 文件 读 + 写
    7 IXXAT Minilog 文件 读 + 写
    8 CAN-DO 日志 读 + 写
    9 Vehicle Spy 日志文件 读 + 写
    10 CANDump / Kayak 只读
    11 PCAN Viewer 只读
    12 Wireshark socketcan PCAP 文件 只读

    采集侧则走另一条路:除推荐的 CANDue 板(需运行 GVRET 固件)之外,可以使用任意 Qt SerialBus 驱动,包括 socketcan、Vector、PeakCAN 与 TinyCAN。也就是说,离线分析用文件,实车采集走 SerialBus,两条路径互不影响。

    可复现环境:依赖全部在源码树内

    这份工程不依赖源码树或 Qt 安装器之外的任何东西,绘图库 QCustomPlot 已直接集成进源码,无需单独下载。编译门槛集中在 Qt 版本上:因为依赖 QtSerialBus 及其他新特性,需要 5.14.0 或更高版本。

    环境项 要求 说明
    Qt 版本 5.14.0 或更高 低于此版本缺少 QtSerialBus,无法编译
    屏幕分辨率 至少 1024×768 支持多显示器,4K 显示器可用
    macOS 二进制 至少 macOS 10.15 针对当前二进制构建的要求
    Qt6 支持 QT6WIP 分支,2026-03-11 用 Qt 6.9 测试通过 质量约为 beta,多数功能可用
    绘图依赖 QCustomPlot 已集成 无需外部下载
    Ubuntu 模块缺失 安装 libqt5serialbus5-dev、libqt5serialport5-dev、qtdeclarative5-dev、qttools5-dev 解决「Unknown module(s) in QT」类报错
    调试构建 qmake CONFIG+=debug 后 make 获取更多运行期信息

    标准编译路径是克隆仓库后依次执行 qmake 与 make,再直接运行可执行文件;Linux 上可用 ./install.sh 生成桌面快捷方式。若编译失败,官方给的第一步重试动作是重新 qmake、make clean、make;仍未解决则检查安装 Qt 时是否勾选了 SerialBUS 支持。

    常见问题

    没有采集硬件,能用 SavvyCAN 做分析吗?

    可以。工具明确说明采集设备不是使用前提,它能直接加载并保存 12 种格式,其中 9 种可读可写,CANDump/Kayak、PCAN Viewer 与 Wireshark socketcan PCAP 三种为只读。用 examples/ 下的三份 DBC 配合日志文件即可跑完整条离线流程。

    三份示例里哪份适合作为第一条分析流程?

    建议从 bms.dbc 或 LeafPowertrainBus.dbc 这类小文件起步。LeafPowertrainBus.dbc 有 10 条报文 22 条信号,可以逐条核对缩放与偏移是否自洽;bms.dbc 有 6 条报文 31 条信号,适合看多设备报文归属。501 报文 548 信号的 ThinkCity.dbc 更适合压测检索与过滤性能。

    ThinkCity.dbc 与归档里的另一份 ThinkCity 该怎么取舍?

    不取舍,两份都要留。归档记录显示后者是同名的后续大幅扩充修订版,规模为 502 报文 761 信号,比前者多 1 条报文、多 213 条信号。两者属于不同的来源快照,正确做法是按各自 provenance 分别留存,而不是用新版覆盖旧版。

    bms.dbc 能当整车 DBC 用吗?

    不能。它是部件级示例,6 条报文 31 条信号里命名的是 EVTVBMS、GEVCU 与逆变器等部件,用于展示部件之间的报文关系。它既不是某款命名整车的原厂 DBC,也不包含整车级拓扑与网关行为。

    Qt6 分支现在可以投入日常使用吗?

    需按 beta 质量评估。仓库里的 QT6WIP 分支可配合 Qt6 编译,2026-03-11 用 Qt 6.9 测试通过,官方表述是「多数功能应该可用」,并请求反馈问题。若用于正式分析流程,仍建议以 Qt 5.14.0 或更高的稳定构建为主。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/collin80-savvycan-examples/SOURCE.md(三份示例 DBC 的报文数、信号数、SHA-256 与修订版快照关系)
    • 项目 01 —— public-can-dbc-datasets/additional/collin80-savvycan-examples/README.md(12 种读写格式、Qt 版本与分辨率要求、编译与排错步骤)

    免责声明

    本文所述示例 DBC 均为公开仓库中的演示文件,其代数、年款、硬件适配与信号验证均未在说明文件中确立,不代表车辆制造商的官方数据。文中数字均来自上述公开仓库的说明文件,未经独立实车验证。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • 马自达 RX-8 的 CAN 笔记:6 个 ID、9 个信号与两处未定系数

    结论:这是一份为赛道遥测整理的马自达 RX-8 CAN 笔记,用 6 个报文 ID 承载 9 个信号:0x201 同时给出油门、转速与车速,0x212 给出刹车与手刹两个开关量,0x231、0x420、0x250、0x81 各给出一个信号。它的价值在于把字节偏移、长度、位掩码与换算公式写到了可直接落地的粒度;边界也同样清楚——只在 2006 年款(series 1)手动挡带 DSC 的一台车上用 OBDLink MX+ 与 RaceChrono v7.5.3 验证过,转速除数还有 4.0 与 3.85 两套并存,刹车压力至今只有开关量、没有连续量。

    九个信号的字段边界

    先要澄清一个术语:笔记里的「PID」指的是 CAN 报文 ID,不是 OBD-II 服务 01 下的参数标识符。这决定了取数方式是被动监听总线,而不是主动请求应答。多字节值统一按大端解析,这是后面所有公式的前提。

    信号 报文 ID 字节偏移 长度 位掩码 类型 换算公式
    油门开度 0x201 6 1 无 UINT8 百分比 = 值 / 2(原始值范围 0 到 200)
    引擎转速 0x201 0 2 无 UINT16 rpm = 值 / 4.0
    车速 0x201 4 2 无 UINT16 km/h =(值 – 10000)/ 100.0
    刹车踏板 0x212 5 1 0x08 Bool 踩下 = 值
    手刹 0x212 4 1 0x40 Bool 拉起 = 值
    空挡 0x231 0 1 0x80 Bool 空挡 = 取反后的值
    冷却液温度 0x420 0 1 无 UINT8 摄氏度 = 值 – 40
    进气温度 0x250 3 1 无 UINT8 摄氏度 = 值 – 40
    转向角 0x81 2 2 无 INT16 度 = 值(有符号)

    九个信号里 0x201 一条报文就占了三个,且彼此不重叠:转速在偏移 0 占 2 字节,车速在偏移 4 占 2 字节,油门在偏移 6 占 1 字节。这种紧凑布局意味着解析时一次取 8 字节即可解出三个量,但也意味着任何一个偏移写错都会静默地取到相邻信号。

    位掩码到 RaceChrono 位号的换算

    笔记给字节偏移与位掩码,RaceChrono 公式里用的却是 0 到 63 的位号,两者需要对账。RaceChrono 的约定是从最高位起算:位 0 是最高位,位 57 的权值为 64。据此可以推出换算关系——位号等于字节偏移乘以 8,再加上掩码在该字节内从高位往低数的序号。

    信号 字节偏移 位掩码 掩码在字节内的高位序号 RaceChrono 位号 RaceChrono 公式
    空挡 0 0x80 0 0 (1 – BitsToUInt(raw, 0, 1)) * 100
    手刹 4 0x40 1 33 BitsToUInt(raw, 33, 1) * 100
    刹车踏板 5 0x08 4 44 BitsToUInt(raw, 44, 1) * 100

    三个位号都能对上:0 = 0×8+0,33 = 4×8+1,44 = 5×8+4。三个开关量都乘 100,是为了把布尔量塞进 RaceChrono 的百分比通道。空挡那一项额外做了取反:原始位在空挡或踩离合时为 0,其余情况为 1。

    两处未定系数与一处待办

    笔记里真正需要用户在落地时做判断的,是笔记公式与 RaceChrono 公式不一致的地方。这些差异大多有明确原因(单位制不同),唯独转速那一处被原作者标记为「需要调查」。

    信号 笔记公式 RaceChrono 公式 差异原因 是否待定
    引擎转速 值 / 4.0 值 / 3.85 4.0 是标准公式,3.85 更贴合仪表显示 是,原作者标注需调查
    车速 (值 – 10000)/ 100.0 得 km/h (值 – 10000)/ 360 RaceChrono 需要 m/s,故除以 360 而非 100 否
    冷却液温度 值 – 40 得摄氏度 值 – 40 RaceChrono 自动转换为华氏度 否
    进气温度 值 – 40 得摄氏度 值 – 40 RaceChrono 自动转换为华氏度 否
    转向角 值(有符号) 值 × -1 RaceChrono 需取反才能正确显示转向动画 否
    刹车压力 无 无 笔记 TODO:希望以压力量替代开关量 是,尚未找到

    转速除数为什么不能随手选一个

    4.0 与 3.85 在 7000 rpm 处的差值约 273 rpm,足以让换挡提示与圈速分析出现系统性偏差。笔记明确写到除以 4 是标准公式,但 3.85 看起来更接近车辆仪表显示的值,而作者并未判定哪个正确。落地时的合理做法是用仪表或独立转速计做一次标定,而不是沿用其中任意一个。

    车速公式里的 10000 偏移

    车速要先把原始值减掉 10000 再除以 100,说明这条通道带了一个 10000 的零点偏移,而不是从 0 计起。这样的设计让原始值具备表达负速度(倒车)的余量,但也意味着如果直接把该 uint16 当无符号数解释而忘记减偏移,会得到约 100 km/h 的固定假值。落地时应先确认目标工具是按有符号还是无符号取值,并在静态停车状态下先读一次原始值做零点校验。

    验证环境与适用边界

    这套代码带的免责声明写得很直接:仅供实验用途,使用风险自负。它的验证矩阵也很窄,只有一台车、一个适配器、一个手机型号与一个软件版本。

    项目 取值 对适用性的影响
    车辆 Mazda RX-8 2006(series 1),手动变速箱,带 DSC 自动挡或其他年款未验证
    适配器 OBDLink MX+ 蓝牙扫描仪 换适配器后需重新确认透传是否完整
    手机 Huawei P30 Pro,Android 10 蓝牙协议栈差异可能影响采样连续性
    软件 RaceChrono v7.5.3,需开启实验功能 7.5.3 起必须启用实验特性才能生效
    字节序 多字节值为大端 按小端解析会得到完全错误的速度与转速
    位编号 从最高位起算,范围 0 到 63,位 57 的权值为 64 与常见 LSB 起算工具不通用

    常见问题

    这里的 PID 是 OBD-II 的 PID 吗?

    不是。笔记里的 PID 指 CAN 报文 ID,例如 0x201、0x212、0x231、0x420、0x250、0x81,取数方式是被动监听总线而不是主动请求应答。这与 OBD-II 服务 01 下的参数标识符是两套体系,混用会得到完全不同的字节布局。

    这些报文适用于所有 RX-8 年款吗?

    不能这样假定。笔记声明只在 Mazda RX-8 2006(series 1)、手动变速箱、带 DSC 这一台车上验证成功,并明确为实验用途。自动挡、其他年款或不同市场版本的报文布局可能不同。

    引擎转速为什么会有 4.0 和 3.85 两套除数?

    笔记写到除以 4 是标准公式,但 3.85 看起来更接近车辆仪表显示的值,作者自己也标注「不知道哪个是对的,需要调查」。两者在高转速区的差值可达数百 rpm,落地前应用仪表或独立转速计做一次标定。

    RaceChrono 里的位号 44、33、0 是怎么算出来的?

    由字节偏移与位掩码换算而来。RaceChrono 从最高位起算,位号等于字节偏移乘 8 再加掩码在字节内从高位往低数的序号:刹车 0x08 在偏移 5,得 5×8+4 = 44;手刹 0x40 在偏移 4,得 4×8+1 = 33;空挡 0x80 在偏移 0,得 0×8+0 = 0。

    刹车压力能从这些报文里取到吗?

    暂时不能。笔记只解出了 0x212 里的刹车踏板开关量与手刹开关量,并把「找到刹车压力代替开关信号」列为 TODO。也就是说目前只有布尔状态,没有连续的制动压力通道。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/topolittle-rx8-can-notes/README.md(9 个信号的报文 ID、字节偏移、位掩码、换算公式与验证设备清单)

    免责声明

    本文所述的 CAN 报文解析均来自公开仓库的实验性笔记,原作者明确声明仅供实验用途、使用风险自负,且与文中提到的任何公司无关联或赞助关系。文中数字未经独立实车验证,不同年款、市场与 ECU 版本可能存在差异。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • Freelander 2 中速 CAN 梳理:两个 DBC 版本、39 报文与 125 kbit/s

    结论:神行者 2(Freelander 2)的这套中速 CAN 材料不是一个已完成的解码成果,而是一个进行中的信息娱乐替代工程副产品。它的核心是两份同名不同版本的 DBC:FL2_13MY_MSCAN r01.dbc 有 35 条报文 12 条信号,r03.dbc 有 39 条报文 39 条信号——两者 ID 相互重叠,是迭代关系而非总线分区互补。信号数从 12 跳到 39 而报文只多 4 条,说明大量条目仍停留在报文清单或初步解释层面。硬件侧倒是清晰:两路 MCP2515 分别跑 125 kbit/s 与 500 kbit/s,对应中速与高速两条总线。

    两个版本是迭代关系,不是互补分区

    最容易犯的错是把 r01 与 r03 当成两条不同总线的定义拼在一起用。归档记录明确写着:这是两个版本、ID 重叠,不是互补的总线分区。正确做法是只取较新的一份作为当前基线,把旧版留作来源快照。

    文件 报文数 信号数 与另一版的关系 使用建议
    FL2_13MY_MSCAN r01.dbc 35 12 较早版本,ID 与 r03 重叠 留作来源快照,不参与合并
    FL2_13MY_MSCAN r03.dbc 39 39 较新版本,比 r01 多 4 条报文、多 27 条信号 作为当前基线,逐条核对

    多出来的 27 条信号分布在 39 条报文里,平均下来每条仍不足 1 条。这个比例本身就是一条判据:文件里相当一部分条目只是被登记了报文 ID,尚未解出对应的物理信号。较新版本还包含 4 条扩展 ID 条目,发送方被标注为项目自定义来源(原文记作 JPL-Added),分别对应转向灯、背光、驻车雷达与钥匙电池状态。

    三条总线的分工:中速、高速与娱乐总线

    这个工程同时面对三条总线。中速 CAN 是主攻方向,高速 CAN 目前主要用于生成 CanDump 供调试;娱乐总线则是音频主机与显示屏之间的专用链路,独立于 MS/HS 之外,解码进度反而更具体。

    总线 速率 接口 承载内容 解码状态
    中速 CAN(MS-CAN) 125 kbit/s can0 车身与信息类 ID,含 VIN 进行中,README 标注 work in progress
    高速 CAN(HS-CAN) 500 kbit/s can1 车辆高速总线 可生成 CanDump 用于调试开发
    娱乐总线(Entertainment Bus) 未在 README 中标注 音频主机与主机显示屏之间 音源(FM/DAB/AM/Aux/蓝牙,CD 待定)、电台名与 RDS 附加数据、音量、蓝牙媒体的曲名与艺术家 部分解码,条目比 MS-CAN 更具体

    娱乐总线的音量项有个细节:它只在操作原车硬件旋钮开关时弹出。这类「事件触发而非周期广播」的行为,是被动监听时最容易漏掉的报文类型,也说明了为什么单纯抓一段 CanDump 不足以还原总线行为。

    硬件与接口配置:两路 MCP2515 与两个波特率

    工程跑在树莓派上,通过 SPI 挂两路 MCP2515 控制器。/boot/config.txt 里先开 SPI,再声明两个 overlay,晶振均为 16000000,中断脚分别是 25 与 23;/etc/rc.local 里在 exit 0 之前拉起两个接口,速率一高一低。

    配置项 取值 说明
    SPI dtparam=spi=on MCP2515 经 SPI 挂载的前提
    can0 晶振 16000000,中断 23,bitrate 125000 对应中速 CAN
    can1 晶振 16000000,中断 25,bitrate 500000 对应高速 CAN
    系统依赖 can-utils、libsocketcan2、libsocketcan-dev 通过 apt 安装
    运行时 Node.js 20.10.0(仅在此版本测试过) 随后执行 npm i
    构建目标 pi64-build(RPi 4 且 4GB 以上)、pi32-build(RPi 3 或 4GB 以下的 RPi 4)、electron-build(Ubuntu,仅供测试) 产物在 /dist 下,运行 AppImage
    免硬件调试 vcan 加 can-gw 双向转发 先 down 掉 can1 再以 125000 拉起,或建两条 vcan 互转

    证据边界:哪些是已解码,哪些只是假设

    这份材料的价值在于把「已实现」「进行中」「假设」分得很清楚。直接照抄 DBC 里的信号名会带来两类风险:把未验证的假设当结论,以及把项目自定义的编码当原车报文。

    条目 状态 边界说明
    VIN 解析 已实现 解析 VIN 得出车龄、品牌与型号;首次启动需要一点时间完成配置
    娱乐总线解码 部分实现 音源、电台名与 RDS、音量、蓝牙曲目均已覆盖
    CD 音源 待定 原文标注为 Pending
    MS-CAN ID 解码 进行中 README 明确标注 work in progress
    4 条扩展 ID(转向灯、背光、驻车雷达、钥匙电池) 未确立 发送方被标注为项目自定义来源,尚未确认是原车观测帧还是项目自有编码
    带问号的注释(如胎压归属) 假设 仍是推测,未验证
    车辆配置文件解析 TBC 是否需要尚未确定
    逐信号验证与配置/固件适配 缺失 README 只给出工程与大致车型范围
    许可证 无 检查的快照中没有许可证文件

    被动监听时要特别留意的两类帧

    第一类是非周期帧:娱乐总线的音量只在操作原车旋钮时弹出,短时抓包很可能整段缺失。第二类是来源存疑的帧:那四条扩展 ID 与带问号的注释都属于此类。合理的抓取策略是先长录一段覆盖静置、上电、操作旋钮与行驶四个阶段,再按 ID 出现次数做筛选,而不是只看某一段 CanDump 里出现了什么。

    常见问题

    r01 与 r03 该用哪个?

    用 r03 作基线,r01 只作来源快照。归档记录明确说明两个版本 ID 相互重叠、是迭代关系而非互补的总线分区,把它们合并会引入重复 ID 与冲突定义。r03 有 39 条报文 39 条信号,比 r01 多 4 条报文、27 条信号。

    125 kbit/s 与 500 kbit/s 分别对应哪条总线?

    125 kbit/s 是中速 CAN,绑定在 can0;500 kbit/s 是高速 CAN,绑定在 can1。两者都由 MCP2515 经 SPI 提供,晶振 16000000,中断脚分别为 23 与 25,配置写在 /boot/config.txt 与 /etc/rc.local 里。

    那四条扩展 ID 是原车报文吗?

    尚未确立。它们出现在较新版本里,对应转向灯、背光、驻车雷达与钥匙电池状态,发送方被标注为项目自定义来源。归档记录明确写到,尚未独立确认这些条目是观测到的原车帧还是项目自有编码,因此不能当作原厂信号使用。

    娱乐总线和中速 CAN 是同一条总线吗?

    不是。README 把娱乐总线描述为音频主机与主机显示屏之间的专用总线,独立于 MS/HS 之外,并单独列出了音源、电台名与 RDS、音量、蓝牙曲目等解码项。它的速率未在 README 中标注。

    这套配置能直接搬到别的车型上吗?

    硬件部分可以复用,报文部分不能。两路 MCP2515 加 can-utils 的接法与车型无关;但 DBC 里的 ID 与信号是针对 2012 年款之后的 Freelander 2 整理的,且 README 未提供逐信号验证与具体配置、固件适配的证据,换车型必须重新取证。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/n95jpl-freelander2-mscan/SOURCE.md(两个 DBC 版本的报文数与信号数、重叠关系、扩展 ID 与许可证状态)
    • 项目 01 —— public-can-dbc-datasets/additional/n95jpl-freelander2-mscan/README.md(功能清单、娱乐总线解码项、树莓派双 CAN 接口配置与 vCAN 调试步骤)

    免责声明

    本文所述内容均为社区逆向与开发中的工程产物,不代表车辆制造商的官方数据。文中数字均来自上述公开仓库的说明文件,未经独立实车验证;不同车型年款、配置与固件版本可能存在差异,部分条目在原始材料中即标注为假设或未确立。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • 改装 ECU 的 CAN 仿真器:8/90 与 38/159 两份样例 DBC 怎么验

    结论:用桌面 CAN 仿真器验证改装 ECU 的 DBC,最省事的路径是先跑 virtual 接口做单进程自检,再用 vcan 或真实 SocketCAN 做端到端收發比对。这份归档里的两份样例分别是 8 报文 90 信号与 38 报文 159 信号,文件名指向两款常见改装 ECU,但仓库没有给出固件版本、装车适配和物理标定记录——它们能验证的是编码/解码链路本身,不能验证信号物理含义。

    两份样例 DBC 的实际量级

    仿真器自带两个样例库,归档时按 Git blob 与 SHA-256 做了固化。两者的量级差了一个数量级:小的一份 8 条报文却塞了 90 个信号,说明单帧内信号排布非常密;大的一份 38 条报文 159 个信号,更接近一台完整发动机控制器的输出规模。

    文件 报文数 信号数 SHA-256(前 16 位) 推断的 ECU 证据状态
    databases/emu_black.dbc 8 90 61caa4ea47dc0be3 ECUMaster EMU Black 名称推断,固件与装车未记录
    databases/haltech_elite.dbc 38 159 cbe0b8c73c842df1 Haltech Elite 名称推断,固件与装车未记录

    其中 emu_black.dbc 含有遗留的非 UTF-8 单位字节,归档时保持原样未做转换。这一点对工具链有实际影响:按严格 UTF-8 读取单位字段的解析器会报错或产生乱码,需要在加载前明确编码容错策略。另外,这两份文件是部件级协议样例,不是整车网络地图——把它们当成某台车的完整定义来用,从一开始就错了。

    三种接口的适用边界

    工具支持三类接口,选择依据不是「哪个更好」,而是当前验证处在哪个阶段。virtual 接口不需要硬件也不需要 root,但只在同一个 Python 进程内有效;socketcan 能跨进程、可配波特率,但改波特率需要 CAP_NET_ADMIN;slcan 面向 USB 串口适配器,适合接真实硬件。

    接口类型 硬件需求 权限需求 能否跨进程 波特率可配 适用阶段
    virtual 无 无 否,仅同进程 不适用 UI 与编码逻辑快速自检
    socketcan 真实或虚拟 CAN 接口 改波特率需 CAP_NET_ADMIN 是 是 与第三方工具联调
    slcan USB/串口适配器 无特殊权限 是 是 接真实改装 ECU

    SocketCAN 的波特率是网络链路自身的属性,不是应用每次连接时设定的。工具里的「Apply Bitrate」按钮实际执行的是把接口 down 掉、用 ip link 设定位速率、再 up 起来的三步操作,因此必然需要管理员权限;如果失败,可以事先自行配置好接口再启动工具。「Create vcan」按钮同理,它加载 vcan 内核模块并起一个虚拟链路,默认名 vcan0,之后另一个终端用 candump 就能看到流量。

    一条可复用的 DBC 验证流程

    把仿真器当验证工具而不是发帧玩具,核心是让「发什么」和「收回来解出什么」形成闭环。工具本身已经提供了闭环所需的两个能力:展开报文后按 DBC 定义生成控件,以及把总线上收到的每一帧连同解码结果打进日志。

    步骤 操作 判据
    1 加载 载入目标 DBC,观察是否有解析告警 无告警再继续;非 UTF-8 字节需先定编码策略
    2 展开 展开报文,数值信号看滑块量程,枚举信号看下拉项 量程与下拉项应与 DBC 的 range/resolution 和值表一致
    3 编码 拖动滑块,观察实时生成的原始字节 字节随取值单调变化,边界值不溢出
    4 发送 打开 TX 开关按周期发,或用 Send once 单发 周期默认 100 ms;DBC 未指定时以此为准
    5 回收 在日志里核对 RX 帧与解码结果 ID 在 DBC 内则应解码成功;回环数值应与发送值一致
    6 压力 在高负载总线上观察日志 出现 RX overflow 说明日志丢弃,不能据此判定丢帧

    第 5 步是这个流程的关键:只有当发出的值在接收侧被同一个 DBC 解回相同数值时,编码与解码的一致性才算被验证。它验证的是链路,不是物理含义——滑块拉到某个位置对应的字节是否正确,与这个字节在真实 ECU 上代表多少 kPa,是两个问题。

    日志里 RX overflow 不是丢帧证据

    日志面板会打印总线上收到的每一帧,格式形如 RX 0x360 [8] 后面跟数据。在非常繁忙的总线上,多余的帧会被从日志中丢弃并报告为 RX overflow。这是日志侧的丢弃,不是总线侧的丢帧,两者不能混为一谈;要测丢包率应当用独立的计数器,而不是看日志有没有 overflow。

    常见问题

    这两份样例 DBC 能当作某台改装车的完整网络定义吗?

    不能。它们是部件级协议样例,文件名指向两款改装 ECU,但仓库没有记录具体固件版本、装车适配、信号原作者或物理标定。能验证的是编码与解码链路,信号物理含义需要另行标定。

    没有硬件能不能先把验证跑起来?

    可以。virtual 接口是 python-can 的进程内总线,不需要硬件也不需要 root,适合做 UI 与编码逻辑的快速自检;若需要跨进程联调,则用 socketcan 加 vcan 虚拟链路,两个应用打开同一个接口即可互通。

    为什么点了 Apply Bitrate 会失败?

    因为 SocketCAN 的波特率属于网络链路属性,按钮实际执行的是 down、设定位速率、再 up 三步,需要 CAP_NET_ADMIN。权限不足时可以自行提前配置接口,或以足够权限运行工具。

    周期发送的默认周期是多少?

    打开报文的 TX 开关会按该报文的周期时间发送,周期可在界面上编辑;如果 DBC 没有指定周期,则默认取 100 ms。单帧发送则用 Send once。

    日志里的 RX overflow 意味着总线丢帧吗?

    不意味着。它表示繁忙总线上多余的帧被从日志面板丢弃,是日志侧的限流行为,不是总线侧丢帧。判定丢包率要用独立计数器,也可以取消勾选日志头的 Show received frames 来静音接收帧显示。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/candbcemu-aftermarket-ecu/SOURCE.md(两份样例 DBC 的报文/信号数、Git blob 与 SHA-256、非 UTF-8 字节说明与权利状态)
    • 项目 01 —— public-can-dbc-datasets/additional/candbcemu-aftermarket-ecu/README.md(三种接口类型、波特率配置、vcan 创建、TX/RX 行为与项目结构)

    免责声明

    本文所述功能与参数均来自公开仓库的说明文件,未经在真实改装 ECU 上的独立验证。两份样例 DBC 的车型归属为名称推断,固件版本、装车适配与信号物理标定均未由仓库给出。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿