标签: CAN总线

  • sygnal_dbc 前缀契约:cb_niro_dcan 不是原厂帧

    结论:sygnal_dbc 最容易被误读的一点是目录名叫 niro。归档说明明确指出:cb_niro_dcan/ 里的四个单报文文件描述的是 Sygnal 项目自己的 UserApplication 到 MCM 接口,其 CAN ID 与位布局不能被假定为 Kia Niro 的原厂诊断帧。而真正属于 Hyundai/Kia 整车定义的是另一个文件——140 条报文、1,301 个信号的 hyundai_kia_generic.dbc,它同样没有标定到具体年款。

    包结构与前缀规则

    这个仓库的做法是把每个子系统目录都做成一个独立的 ament_cmake 包,用 dbc_gen_cpp 从目录里的 .dbc 生成并导出 C/C++ 报文类型。七个目录对应七个包,每个包有固定的库前缀。

    目录 包名 库前缀
    mcm/ dbc_sygnal_mcm mcm_
    io/ dbc_sygnal_io io_
    cb/ dbc_sygnal_cb cb_
    cb_niro_dcan/ dbc_sygnal_cb_niro_dcan cb_niro_dcan_
    hpo/ dbc_sygnal_hpo hpo_
    vehicles/ dbc_sygnal_vehicles vehicles_
    sygnal_dbc/ sygnal_dbc 伞形包,无前缀

    命名规则是「<前缀>_<dbc 文件名主干,小写>」,并且这一串字符串同时是库名、C++ 命名空间、C 符号前缀与头文件目录。例如 mcm/Control.dbc 产出库 mcm_control、头文件 mcm_control/mcm_control.h 与 .hpp、命名空间 mcm_control、C 符号 mcm_control_*。

    C 用法的关键是:这些库以命名空间化的 imported target 导出,写作 dbc_sygnal_mcm::mcm_control。跨子系统同名的 DBC 不会冲突,因为包名已经把作用域隔开了。

    为什么必须有前缀

    前缀不是洁癖,而是被 colcon 与链接器逼出来的。有六个文件名在 cb/、hpo/、io/、mcm/ 四个子系统中同时存在:Control.dbc、Heartbeat.dbc、Identify.dbc、Configuration.dbc、Error.dbc、Commissioning.dbc。

    若按主干直接命名 后果
    四个库都叫 Control 同时链接其中任意两个即出现重复符号错误
    C 符号均为 control_* 静态链接阶段冲突,且无法按子系统区分版本
    头文件都装到 include/Control/Control.hpp 安装阶段互相覆盖,包含路径失去区分度

    还有一个目录结构的细节值得记住:cb_niro_dcan/ 是 cb/ 的兄弟目录,而不是 cb/niro_dcan/ 子目录。原因是 colcon 不会进入一个它已经识别为包的目录的子目录。但在安装产物里,database 树仍然把它摆回 cb/niro_dcan/ 的位置——也就是说源码布局与安装布局故意不一致,这是构建系统约束的结果,不是笔误。

    新增一份 DBC 不需要改 CMake

    每个包的 CMakeLists.txt 都只是一个薄壳,真正干活的是共享的 cmake/dbc_package.cmake 里的 dbc_package() 函数:它 glob 目录里的每一个 *.dbc,为每个文件生成一个导出库。因此新增一份 DBC 只需把文件丢进目录,无需改任何构建脚本。

    需要跑到原始文件时,find_package(sygnal_dbc) 会把 SYGNAL_DBC_DIR 指向 <install-prefix>/share/sygnal_dbc/database,并保留 <子系统>/<名称>.dbc 的原始布局;每个子系统包也会把自己的 DBC 装到 share/<包名>/database 下。要用哪一层,取决于你是想按子系统引用还是想按整车打包。

    向后兼容也做得干净:以前这个包会编译出一个名为 sygnal_dbc 的聚合库,并把头文件安装成 sygnal_dbc/<前缀>_<名称>.h。拆分之后两种方式都还能用——聚合库变成一个链接了所有生成库的 INTERFACE 库,转发头文件位于 include/sygnal_dbc/<库名>.h。关键在于旧的构建本来就给 cantools 传 --database-name <前缀>_<名称>,正好等于新的库名,因此 C 符号完全没变,老代码无需改动。新代码则应包含 "<库名>/<库名>.hpp",直接链接 dbc_sygnal_<子系统>::<库名>。

    两个必须核对的事实点

    第一,cb_niro_dcan 的四个文件——batterySOC.dbc、door_seatbelt_state.dbc、dtc.dbc、tpms.dbc——每个只有一条报文,合起来描述的是 SOC、车门与安全带状态、DTC 状态与胎压。它们是工程接口定义,不是车型 niro 的诊断帧;把它当作 Kia Niro 的原厂数据去对接,方向一开始就错了。

    第二,hyundai_kia_generic.dbc 虽然有 140 条报文、1,301 个信号,但它的问题恰恰藏在规模里。归档对比发现,这份文件相对于一份较早的 OpenDBC 派生副本修改或移除了多条报文与信号布局;而仓库既没有固定上游修订版,也不解释每一处改动,更没有说明对应的车型年款,也不提供匹配的抓包数据。这五个 Git blob 在归档收录时都不在已有存档里,Niro 那些文件还保留着原始的 CRLF 行尾。

    结论很直接:Apache-2.0 许可对仓库代码成立,但整车数据的来源与权利链并没有被记录下来。若要把这份 140 报文的文件用在项目里,需要先回溯原始许可链,并用真实抓包做车型适配验证——规模大不等于证据强。

    常见问题

    cb_niro_dcan 里的四个文件是 Kia Niro 的原厂 CAN 定义吗?

    不是。归档说明明确写道,这四个单报文文件描述的是 Sygnal 项目中 UserApplication 到 MCM 的接口,涵盖电池 SOC、车门与安全带状态、DTC 状态与胎压;其 CAN ID 与位布局不能被假定为工厂 Kia Niro 的诊断帧。

    为什么库名必须带子系统前缀?

    因为文件名在多个子系统里重复。Control、Heartbeat、Identify、Configuration、Error、Commissioning 六个文件名在 cb、hpo、io、mcm 中都存在,按主干命名会产生四个同名库、四份同名 control_* 符号与四条相同的安装路径,同时链接其中两个即报重复符号错误。

    新增一份 DBC 需要改 CMakeLists 吗?

    不需要。每个包的 CMakeLists 只是薄壳,实际调用共享的 cmake/dbc_package.cmake 里的 dbc_package() 函数,该函数 glob 目录内的所有 dbc 文件并为每个文件生成一个导出库。把新文件放进目录即可。

    hyundai_kia_generic.dbc 有 140 报文,能直接用吗?

    不建议直接用。归档对比发现它修改或移除了多条报文与信号布局,而仓库既没有固定上游修订版,也没有解释改动、标注车型年款或提供匹配的抓包数据。使用前需回溯 OpenDBC 的许可链并用真实抓包验证车型适配。规模大不等于证据充分。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/polymathrobotics-sygnal-niro/sygnal_dbc/README.md(七个子系统与七个 ament_cmake 包及其库前缀、dbc_package() 与 cmake/dbc_package.cmake 的 glob 机制、mcm/Control.dbc 到 mcm_control 的命名规则、同名文件在四个子系统中重复导致的重复符号问题、cb_niro_dcan 作为兄弟目录的 colcon 原因、命名空间化 imported target、向后兼容的 INTERFACE 库与转发头文件、SYGNAL_DBC_DIR 与安装布局)
    • 项目 01 —— public-can-dbc-datasets/additional/polymathrobotics-sygnal-niro/SOURCE.md(仓库与快照 commit、采集日期 2026-10-04、四个 Niro 接口文件的性质与「不得假定为原厂帧」的断言、140 报文 1,301 信号的 hyundai_kia_generic.dbc 及其与 OpenDBC 派生副本的差异、五个 blob 的 sha 记录、Apache-2.0 保留与整车数据权利链未记录)

    免责声明

    本文所述包结构、命名规则与文件规模均来自公开开源仓库的说明与归档文件,未经实车独立验证,也不代表任何车辆制造商的官方数据。涉及车辆定义的文件并未标注适配年款,也无匹配抓包可供核验。涉及行车安全的功能请以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • RiceTimer:GNSS UTC 统一时钟,DBC 解析仍在计划里

    结论:RiceTimer 是一台把 GNSS、IMU 与 CAN 三路原始数据同步写进 MicroSD 的记录器,但它今天并不解析信号——data/dbc/ 目录下目前只有一份版权声明,说明数据部分派生自 MIT 授权的 OpenDBC;真正的 DBC-based CAN bus parsing 明确写在 Planned Future Work 里,并且作者特别注明它不会影响日志输出,日志永远是原始 CAN 报文。想拿发动机转速和挡位,得自己离线过一遍 DBC。

    它记录什么:三路数据共用一个 GNSS 时钟

    这个项目最扎实的设计决定是把时间基准统一了:所有消息都按 GNSS 的 UTC 时钟打时间戳,而不是按各自 MCU 的上电时间。这决定了后面能不能把 IMU 的姿态和 CAN 的轮速对齐到同一条时间轴上。

    数据源 器件 时间戳方式 注意点
    GNSS uBlox NEO 系列模块 + 外接有源天线 NMEA 语句本身带 UTC 必须接 SMA 天线,板上没有内置 GNSS 天线
    IMU ST LSM6 系列(LGA14)六轴加速度 + 陀螺 硬件在 data available 时刻打时间戳 SPI 总线占用 IOMux 快速引脚,不可随意改引脚
    CAN 一路 3.3 V 非隔离收发器 固件在报文交付时刻打时间戳 兼容 5 V 网络;支持 11/29 位帧,不支持 FD

    三者的时间戳来源不同——IMU 是硬件级的、CAN 是固件级的——这意味着它们相对于 GNSS 时钟都存在各自的偏移。做融合之前,这个偏移必须测出来并补偿,否则 IMU 与 CAN 的数据在时间上会有系统性的错位。

    日志格式也刻意朴素:每行一个数据点,且每一条有效 NMEA 语句都被逐字写入。这样做的代价是文件体积偏大,收益是后期可以用任何外部工具重放,不必依赖设备自身的解析器。示例日志 sample-log.txt 里 GPS 坐标做了部分脱敏处理,因此那份文件的 NMEA 校验和是对不上的——这不是日志坏了。

    硬件接口契约

    接车之前值得把引脚定义核对一遍,因为它是裸板电源与总线共口的设计,接错就是烧片子。

    接口 引脚 电气取值 注意点
    USB Micro-B 供电 + 串口调试烧录 CP210x 桥接 同时也是 ESP32 的编程控制台
    JST SH 5 针(短边) 1 GND、2 VIN、3 Reserved、4 CAN L、5 CAN H VIN 标称 5 至 14 V CAN 与电源共用同一个座,引脚 3 保留未接
    SMA(短边) 外接有源天线 必需 无内置天线,不接则 GNSS 不工作
    JST SH 4 针(长边) 1 GND、2 VCC、3 SDA、4 SCL VCC 标称 3.3 V 兼容 QWIIC 与 Stemma QT,现用于 SH1107 的 128×64 OLED
    Micro SD 4 位 SD 总线 Micro-SDHC 占用 IOMux 快速引脚;重流量下建议低延迟卡

    SD 卡这条容易被忽略。CAN 数据不多时任何 Micro-SDHC 都能用,但报文流量较大时建议换低延迟卡,以避免潜在丢数。市面上通常标注为 Industrial、Endurance 或「行车记录仪专用」的就是这一类。换句话说,丢帧的根因未必在 CAN 侧,可能在文件系统的写入延迟上——而这个问题在 CAN 侧是查不出异常的。

    DBC 目录现在的实际内容

    往下钻一层看 data/dbc/,会发现这个目录目前只有一份 README,全文只有一个信息:这里的数据部分派生自 OpenDBC(MIT 授权),详见 LICENSE。目录里没有可加载的 .dbc 文件。

    这与 README 里的计划清单完全对应——DBC-based CAN bus parsing 被列在 Planned Future Work,描述是「把 DBC 加载到设备上,从而提取并利用实时信号,例如发动机转速、油液温度、车辆自身的 IMU、轮速等」。而紧接着那句话才是关键:这不会影响日志输出,日志始终包含原始 CAN 报文。

    这条约束很值得照抄。它把设备切成两条正交的路径:实时显示在未来可以走 DBC 解析,落盘数据则永远保持原始。收益是后处理链路不会因为解析定义的改动而失效——原始帧始终可以重新解码;代价是每次会话都会多写一份原始报文,占用存储。对一个以复盘为目标的项目来说,这是一笔划算的买卖。

    计划清单里剩下的四件事

    README 明确列出了待办,读它能判断这台设备的成熟度:一是稳定日志格式与后处理流程(当前日志格式尚未正式规定,这对依赖它做自动分析的人是硬约束);二是传感器融合与标定,需要对 IMU、车辆、GNSS 天线之间的刚性变换做标定;三是预测圈速,当前 OLED 只显示少量实时诊断信息;四是启用 Wi-Fi 与 BLE——选 ESP32 就是为了留这一步。

    还有一条对项目形态影响很大:README 明确写「本项目目前不接受贡献」。这解释了为什么它是一个清晰的单人项目而不是一个社区协议库——想要更多的信号定义,只能等作者更新或自己在离线侧补全。

    作为参照,作者已经用早期原型硬件在 Thunderhill East 赛道的实数据跑通过后处理,转换成空格分隔表并交给 CircuitTools 分析。也就是说「赛道实车采集的数据转成空格分隔表,再交给 CircuitTools 分析」这条主链路是通的,缺的只是设备端的 DBC 解析那一环。

    常见问题

    RiceTimer 现在能直接在设备上解出发动机转速吗?

    不能。DBC-based CAN bus parsing 仍列在 Planned Future Work 中,data/dbc/ 目录目前只有一份说明版权与 OpenDBC 派生关系的 README,没有可加载的 dbc 文件。要得到转速、水温、轮速等信号,需要在拿到原始日志后自行用外部工具按 DBC 解码。

    这台设备支持 CAN FD 吗?

    不支持。它只有一路 3.3 V 非隔离 CAN 收发器通道,兼容 5 V 网络,支持 11 位与 29 位帧,文档明确指出 FD 不支持。接 FD 总线不会得到正确报文。

    为什么建议换低延迟的 SD 卡?

    因为写入延迟会在 CAN 流量大时造成丢数。作者说明 CAN 数据不多时任何 Micro-SDHC 都能用,但报文流量较大时应换低延迟卡,通常是标注 Industrial、Endurance 或行车记录仪专用的型号。这类丢帧在 CAN 侧查不到异常。

    示例日志里的 NMEA 校验和为什么对不上?

    因为示例日志的 GPS 坐标做了部分脱敏处理。README 明确说明这一操作会导致校验和不匹配,这是隐私保护的结果,不代表日志损坏或记录链路有问题。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/hpde-rice-timer/README.md(定位与原名 ShiftWatch、三种数据源与器件型号、GNSS UTC 统一时间戳、CAN 收发器电气与 FD 不支持、两个 JST SH 接口的引脚定义、SD 卡低延迟建议、示例日志脱敏说明、Planned Future Work 六项、暂不接受贡献)
    • 项目 01 —— public-can-dbc-datasets/additional/hpde-rice-timer/data/dbc/README.md(该目录数据部分派生自 MIT 授权的 OpenDBC,详见 LICENSE)

    免责声明

    本文所述硬件规格、引脚定义与项目状态均来自公开开源仓库的说明文件,属社区项目产物,未经实车独立验证,也不代表任何制造商的官方数据。日志格式尚未正式规格化,接口定义可能随硬件版本变化。涉及车载供电与总线接入的操作请以实际测量与官方资料为准。

    更新记录

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

  • PSA 架构逆向:94 份报文 YAML 与 DBMUXEv 格式

    结论:PSA-RE 不是 DBC 集合,而是一套自研的 DBMUXEv 描述格式:归档快照含 94 份总线报文 YAML、110 份车型映射文件,覆盖 AEE2001(VAN)、AEE2004(第一代 FullCAN)与 AEE2010 三代架构。它不用 DBC 的原因很具体——需要同时描述多个世代,而每个世代又包含多条网络,DBC 这种单网络格式装不下。

    为什么放弃 DBC:单网络格式的边界

    DBMUXE 格式的规范文档写明了动机:现有格式(包括 Vector 的 DBCan)无法满足需求,因为要描述多代设计,而每代设计又包含多条网络。格式名本身也是线索——DBMUX 取自 PSA 内部用于描述多路复用网络的软件名,后缀 ev 在 PSA 语境里常表示某个事物的演进版本。

    维度 DBC(DBCan) DBMUXEv
    组织单位 单一网络上的报文与信号 architecture、variant、network、bus、node 逐层嵌套
    多世代设计 需拆成多份彼此无关的文件 按目录分层;跨架构相同的报文只写一份,其余用符号链接
    诊断数据 不在格式范围内 同级 diag 目录下有 dids、dtcs、resets、routines 四类
    协议覆盖 主要面向 CAN 面向多种车载网络,规范仍列为待完成项的有 LIN、KWP2k、K-lines、PSA2k
    语言 单一语言 按 ISO 两字母码扩展,示例仅设置 en 与 fr
    转出工业格式 即用 规范 TODO 中:需编写生成器解析 YAML 产出 DBC、ODX

    代价也很清楚:这套格式目前没有官方工具链,想把它喂给 SavvyCAN 或 CANoe,要先自己写生成器。仓库 README 的求助清单里,「编写生成器把 YAML 转成 DBC、ODX 等工业标准格式」被列为最需要的贡献之一。

    目录结构即数据模型

    规范给出的目录树基本等同于它的概念模型:architecture 是一组设计模板的名字(如 AEE2004),variant 是其衍生版本;network 是共享节点的一组总线,bus 是节点之间的物理链路(可以是 CAN,也可以是 LIN);node 是挂在一或多条总线上的控制器;protocol 是在总线上发送数据的协议;message 是总线上的一帧;signal 是帧里的一个数据点。

    路径 存放内容 作用
    architectures.yml 架构定义 整个数据集的顶层索引
    cars/{id}.yml 车型到架构的映射 把具体车型挂到一或多个架构上
    nodes/{architecture}.{variant}.yml 节点定义 描述该架构变体下有哪些 ECU
    buses/{architecture}.{variant}/{network}.{bus}/{message}.yml 单帧报文 一帧一个文件,是快照里 94 份报文文件的所在
    diag/{architecture}.{variant}/{node}/ dids、dtcs、resets、routines 诊断侧数据,与总线报文分列

    命名上用点号 . 作分隔符,需要时嵌套。跨架构复用有一条明确规则:若某条报文在多个架构(及其版本)中完全相同,只在第一个实现它的架构的最相关版本里描述一次,其余位置创建符号链接。这条规则让 94 份报文文件能覆盖远多于 94 个「车型 × 总线」组合。

    车型命名规则:第二位数字是车身

    仓库单独写了一份车型命名说明。规则是:一个字母加一个数字构成基础车型,后面可能跟第二个数字表示车身形式。

    第二位数字 车身形式
    0 3 门
    1 5 门
    2 SW / Break(旅行版)
    3 4 门
    4 休闲车 / MPV / 大型多功能
    5 Coupe
    6 Coupe / Cabriolet(敞篷)
    7 Cabriolet(敞篷)
    8 Monospace / Minispace
    9 (小型)多功能 / 商用

    另外说明提到改款通常(但不总是)把第一个数字加 1。这条规则的价值在于把 110 份车型映射文件变成可推导的体系:看到车型代号就能预判它挂在哪个架构上,而不必逐份打开文件。

    证据边界:覆盖率与安全内容的取舍

    归档说明给出的边界必须先看。上游 README 声称理论上覆盖 1993 年雪铁龙 XM(首款使用 VAN 的车)到 2020 年代初的标致、雪铁龙与 DS,并说明 2022/2023 年起的新架构尚不清楚;但快照里的报文文件实际位于 AEE2001/CONF 与 AEE2004.full 的 HS.IS 或 LS.CONF 之下,也就是说 README 的车型覆盖表述并不能证明每个车型或信号都已收录。

    上游 107 份总线 YAML 中含有防盗或安全访问相关术语的 13 份被刻意剔除,未纳入本次归档。仓库声明 Apache-2.0 并保留 LICENCE,但 README 同时警告数据可能有误,并承认部分材料来自无法追溯的泄露,因此原始数据权利并未完全确立。留存的报文仍需要与被动抓包做独立的适配性与缩放核对。

    常见问题

    PSA-RE 里为什么没有 DBC 文件?

    因为它用的是自研的 DBMUXEv 格式。规范文档写明动机:现有格式(包括 Vector 的 DBCan)无法描述多代设计,而每代设计又包含多条网络。该项目用 YAML 按 architectures、cars、nodes、buses、diag 分层组织,把 YAML 转成 DBC 需要另外编写生成器,这一点被列在仓库的求助清单里。

    94 份报文 YAML 覆盖了哪些架构?

    项目目标是 PSA 的 AEE2001(VAN 架构)、AEE2004(第一代 FullCAN 架构)与 AEE2010(2010 年至约 2020 年的车型)三代。但本快照的报文文件实际位于 AEE2001/CONF 与 AEE2004.full 的 HS.IS 或 LS.CONF 之下,README 中关于覆盖 1993 年至 2020 年代初的宽泛表述并不能证明每个车型或信号都已收录。

    车型文件的命名规则是什么?

    规则是一个字母加一个数字构成基础车型,后面可跟第二个数字表示车身形式:0 为 3 门、1 为 5 门、2 为旅行版、3 为 4 门、4 为休闲车或 MPV、5 为 Coupe、6 为 Coupe 或敞篷、7 为敞篷、8 为 Monospace、9 为小型多功能车。此外改款通常(但不总是)把第一个数字加 1。

    为什么收录时刻意剔除了 13 份报文文件?

    因为上游 107 份总线 YAML 中含有防盗或安全访问相关术语的 13 份被判定为不宜纳入,未进入本次归档。同时仓库 README 警告数据可能有误,并承认部分材料来自无法追溯的泄露,原始数据权利未完全确立,因此留存报文仍需与被动抓包做独立的适配性与缩放核对。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/prototux-psa-re/README.md(项目目标、AEE2001/AEE2004/AEE2010 架构范围、覆盖声明与免责警告)
    • 项目 01 —— public-can-dbc-datasets/additional/prototux-psa-re/dbmuxev/doc/README.md(DBMUXEv v0.1 规范:术语定义、目录结构、符号链接复用规则与待完成项)
    • 项目 01 —— public-can-dbc-datasets/additional/prototux-psa-re/cars/README.md(PSA 车型代号命名规则与车身形式编码)
    • 项目 01 —— public-can-dbc-datasets/additional/prototux-psa-re/SOURCE.md(94 份报文文件、110 份车型映射、13 份剔除说明与权利状态)

    免责声明

    本文内容整理自公开开源仓库,属社区逆向工程成果,不代表标致、雪铁龙或 DS 的官方数据。原仓库明确警告信息可能不正确,且部分材料来源无法追溯,权利未完全确立。留存报文未经独立抓包验证,不同车型、年款与 ECU 版本可能存在差异,应以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • Polaris Sportsman 的 J1939 档案:12 个 PGN 与 250 kbit/s

    结论:Polaris Sportsman 的这份 J1939 档案给出 250 kbit/s、29 位扩展 ID 下 12 个 PGN 的信号定义,但它们是 2022 款 Sportsman 570 的逆向结果,工具面向的 2026 车型仍需逐条复验。另外两处硬边界必须知道:仓库未找到许可证文件,且工具导出的 DBC 因多信号 PGN 会重复占用同一 CAN ID,未被作为可用文件归档。

    12 个 PGN 分成两类看

    整车走 J1939,位速率 250 kbps、29 位扩展 ID,硬件链路是 Polaris 8 针诊断口 → GT150 → DB9 → PCAN DSUB9,配合 PEAK PCAN-USB FD 适配器与 PCAN-Basic 驱动,Python 侧通过 python-can 的 pcan 接口调用 PCANBasic.dll。配置集中在 polaris_can/config.py:interface 为 pcan,channel 为 PCAN_USBBUS1,bitrate 为 250000。

    把 12 个 PGN 按性质分类,比按地址排序有用得多:一类是状态枚举(取值是离散码),另一类是数值量(需要字节序与缩放)。

    PGN(含字节位) 信号 取值 / 换算 类别
    0x18F00500[5] 挡位 0x4C = L、0x48 = H、0x4E = N、0x52 = R、0x50 = P 状态枚举
    0x18FEF100[0] 手刹 0x37 = 已拉起、0x33 = 已释放 状态枚举
    0x18FEF1FE[3] 脚刹 0xDF = 踩下、0xCF = 释放 状态枚举
    0x18FF6CFE[1] 安全带 0xF7 = 系好、0xF3 = 解开 状态枚举
    0x18F006FE[1] 差速锁 0xDF = 锁止、0xCF = 打开 状态枚举
    0x18FDDFFE[0] 四驱模式 0xFC = 2WD、0xFD = 4WD 状态枚举
    0x18FEF200[6] 油门 0x19–0xFA 映射为 0–100% 数值量,有量程端点
    0x18FEF100[1:2] 车速 小端 uint16 除以 500,单位 mph 数值量,需字节序
    0x18FF6600[0:1] 发动机转速 小端 uint16 数值量,未给缩放
    0x18FEEEFE[0] 冷却液温度 字节值 + 40°C 偏移 数值量,偏移方向需复核
    0x18FEFC00[1] 油量 0–254 数值量,未给百分比换算
    0x18FEE500[0:1] 发动机小时计 小端 uint16 数值量,未给缩放

    这张表里最值得注意的是最后一列。状态枚举只要码值对得上就能用;而转速、油量、小时计三项只给了类型与字节序,没有给缩放因子,水温那条甚至写成「字节 + 40°C 偏移」——与常见的减 40 相反。这四项在使用前都必须用已知工况反推。

    为什么导出的 DBC 不能直接用

    工具提供了 polaris-can export-dbc,输出 cantools 兼容格式,可导入 SavvyCAN、Cabana、Vector CANoe。但归档说明明确指出:导出函数会为多信号 PGN 创建多个使用同一 CAN ID 的独立报文,因此该输出未被作为经过验证的 DBC 归档。

    这个坑在 J1939 场景下很典型。像 0x18FEF100 这样同时承载手刹与车速的 PGN,在 DBC 里应当是同一条报文下的两个信号;若导出成两条同 ID 报文,解析器要么只认第一条,要么按 ID 覆盖,结果就是丢信号。因此正确做法是把这份 PGN 表当作原始事实,手工建 DBC,而不是依赖自动导出。

    五种模式:哪一种是真正的逆向工具

    工具提供 decode、log、discover、replay、export-dbc 五种模式,其中 discover 才是为新车型定位信号的核心手段。

    模式 命令 输出 适用场景
    实时解码 polaris-can decode 终端仪表盘,10 Hz 刷新,含帧率、总线负载百分比、唯一 ID 计数 已知信号的日常查看,可加 --output 落盘
    记录 polaris-can log session1.log 微秒级时间戳的 candump 兼容日志 外场采集,后续导入 SavvyCAN 等工具
    发现 polaris-can discover --warmup 30 基线冻结后报告新 ID 与变化字节 新车型定位信号:怠速 30 秒建基线,再逐个操作开关
    回放 polaris-can replay session1.log --dashboard 离线回放,可实时或加速 无硬件时开发与验证
    导出 polaris-can export-dbc polaris.dbc DBC 文件 仅作起点,多信号 PGN 需手工修正

    discover 的工作流是:预热阶段(默认 30 秒,可用 --warmup 60 延长)记录基线流量并冻结,随后进入发现阶段,监控新出现的 ID 与发生变化的字节。文档给出的示例输出显示基线里冻结了 47 个 CAN ID,随后报告新 ID 与具体字节的旧值到新值变化。操作要领是预热期间车辆真正处于怠速,之后一次只动一个开关或踏板。

    解码时匹配成功的信号会打印 [KNOWN],不匹配的被标为需要重新映射的候选——2026 与 2022 的差异正是靠这个标记暴露出来的。

    常见问题

    2022 年的 PGN 表能直接用在 2026 车型上吗?

    不能直接套用。README 明确说明工具面向 2026 款 Sportsman 570 EPS,但内置的 12 个 PGN 定义来自 2022 款 Sportsman 570,属于基线事实,需要在目标车型上逐条验证。若发现不匹配,应用 discover 模式重建:先怠速建立基线,再逐个操作开关与踏板,观察新 ID 与字节变化。

    为什么导出的 DBC 没有被当作可用文件归档?

    因为导出函数对多信号 PGN 会生成多条使用同一 CAN ID 的独立报文。例如 0x18FEF100 同时承载手刹与车速,正确形态应是同一条报文下的两个信号;拆成两条同 ID 报文会导致解析器丢信号。因此该输出未通过验证,未被归档,建议以 PGN 表为事实源手工建库。

    车速 PGN 0x18FEF100 的换算单位是什么?

    原文给出的是小端 uint16 除以 500,单位为 mph。也就是说原始值需要先按小端字节序拼成 16 位无符号整数,再除以 500 得到英里每小时;若系统内部使用 km/h 或 m/s,还要再做一级单位换算。

    没有 PCAN 硬件能不能用这套工具?

    可以。replay 模式支持离线回放日志文件,可实时或加速播放并接入仪表盘,仓库也提供了 tests/sample.log,在硬件未连接时用示例数据即可跑通,单元测试同样不依赖硬件。真正需要硬件的只有 decode、log 与 discover 三种模式。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/marvbull-polaris-sportsman-can/README.md(250 kbit/s J1939 配置、12 个 PGN 的信号定义、五种工具模式与故障排查)
    • 项目 01 —— public-can-dbc-datasets/additional/marvbull-polaris-sportsman-can/SOURCE.md(快照提交、证据边界、PGN_MAP 的 12 个标识符与导出 DBC 的缺陷说明、权利状态)

    免责声明

    本文所述 PGN、码值与换算均来自公开开源仓库的自述与工具代码,属社区逆向工程产物,不代表车辆制造商的官方数据。信号定义来自 2022 款车型,未经独立抓包验证,不同年款、市场与 ECU 版本可能存在差异。仓库未找到许可证文件,相关材料应作为私有离线研究副本,在权利确认前不得再分发或集成。

    更新记录

    • 2026-10-14 初稿

  • DBC 规范索引:8 段关键字与 7 份可下载文件

    结论:nberlette-canbus 这个仓库的价值不在报文数量,而在它把 DBC 规范拆成 8 个可查段落并挂出 7 份可直接下载的 DBC。真正该先核对的是版本与来源:7 份里两份(Mazda 2017、Lexus RX350)版本栏是「–」,另外五份才有版本号;同目录的 license.md 是许可证文本,不是技术素材。

    DBC 是什么:一份把广播翻译成信号的字典

    CAN 总线上,每个控制器节点把自己所有数据广播出去,由监听节点自行过滤出需要的流量。原始报文对人不可读,因此由 Vector GmbH 发展出一种半标准化格式,把传感器与模块的原始值翻译成带名称和单位的可读量——这就是 .dbc。仓库自述也说明了这类字典的现实来源:各家整车厂都有自己的私有字典(含调整因子、偏移、标签与单位),有时会泄露到网上或被内部人员出售,而大多数情况是爱好者在自己的车上花大量时间逆向出来。

    换句话说,拿到一份 DBC,第一件要做的事不是数它有多少报文,而是确认它属于哪一类来源:官方泄露、社区逆向,还是从其他格式转换而来。这决定了它的可信度等级。

    七份可下载 DBC 的版本与来源

    仓库提供七份文件,混合了自有逆向成果与来自其他项目的转载。下表按「能不能追溯版本」整理,这是判断可维护性的第一层筛选。

    车型 / 用途 文件名 版本 来源性质
    BMW E90 bmw-e90.dbc 2021.6.8 仓库自有逆向,带明确日期版本
    BMW E39 bmw-e39.dbc 2021.6.6 由 .kcd 格式转换而来,非原生 DBC
    Mazda(2017) mazda_2017.dbc — 转载自 opendbc,未标版本
    Lexus RX350 lexus_rx350.dbc — 转载自 opendbc,未标版本
    Tesla Model 3 tesla_model3.dbc 2020.40.1 转载自 onyx-m2 项目的 DBC 仓库
    OBD2(通用) obd2.dbc 0.0.1 转载自 csselectronics.com
    J1939(通用) j1939.dbc 7.6 来源未知,转载自 haskell.org

    版本栏为「–」意味着无法判断这份文件与上游当前状态的距离:opendbc 的 Mazda 与 Lexus 文件在各自仓库里是持续更新的,转载快照一旦脱离上游就会静默过期。带日期版本的两份 BMW 文件虽然量级未必更大,但至少可以判断新旧。

    另一条容易被忽略的信息是 BMW E39 那一份由 .kcd 转换而来。跨格式转换会引入字节序、因子与信号命名的二次解释,因此它的原始证据链比原生 DBC 多一层,核对时应回到 .kcd 源。

    八段规范:从文件头到枚举值

    仓库把 DBC 规范按关键字拆成八节,配 wiki 逐节说明语法、属性与示例。这八节既是写作顺序,也是阅读一份陌生 DBC 的检查顺序。

    关键字 含义 阅读时该看什么
    VERSION 版本 文件头,先确认是否与上游一致
    NS_ 新符号 声明用到的符号集合,缺失会导致部分工具解析失败
    BU_ 节点(Board Units) 定义了哪些 ECU,是判断发送方归属的基础
    BO_ 报文(Messages) ID、DLC 与发送节点,含属性定义
    SG_ 信号(Signals) 起始位、位长、字节序、有无符号、因子与偏移、单位;含复用(Multiplexers)
    BA_ 属性(Attributes) 属性定义与默认值,承载周期一类的元信息
    CM_ 注释(Comments) 全局、节点、报文、信号四个层级的说明,是逆向记录的主要载体
    VAL_ 取值(Values) 枚举值表,把数字映射成文字状态

    其中 SG_ 的复用机制值得单独留意:它解决的是同一条报文在不同场景下承载不同信号的问题。若解析器不支持复用,这类报文会被解成错误的信号组合。

    配套资源:从规范到工具链

    仓库另附两组外部链接。工具与规范类包括 CANpy 的 DBC 规范文档、opendbc 开源 DBC 项目、BMW KCAN / KBUS / IBUS 参考项目、BMW K-CAN 文档站,以及 canmatrix(用于把 DBC 转成其他格式)。参考类包括 PiSnoop 的 DBC 帮助页、Racelogic 面向 VBOXII 与 PRO v4 的 CAN 格式说明、来自 haskell.org 的 J1939 DBC,以及 CANtool 手册。

    这套组合的实用意义在于:读规范解决「字段怎么写」,canmatrix 解决「格式怎么转」,BMW 专项资料则示范了单一品牌多总线(KCAN / KBUS / IBUS)的文档化方式。拿到一份陌生 DBC 时,按八节顺序过一遍也能快速定位问题:先看 VERSION 判断新旧,再看 BU_ 确认节点是否齐全,随后在 BO_ 与 SG_ 上核对 ID、DLC 与字节序,最后读 CM_ 注释寻找作者留下的逆向依据。

    还要留意仓库自述本身把这项工作描述为进行中的状态。因此即便带版本号的文件,也应理解为某一时点的快照,而不是最终结论。

    常见问题

    这个仓库能直接当车型数据库用吗?

    不能。它只提供 7 份可下载的 DBC 文件与规范文档,覆盖 BMW E90、BMW E39、Mazda 2017、Lexus RX350、Tesla Model 3 以及通用的 OBD2 与 J1939,规模远小于整车网络定义。它的主要用途是规范速查与少量可下载样本,车型级数据仍应回到 opendbc 这类专门项目。

    同目录的 license.md 是什么,能当素材读吗?

    它是仓库的许可证文本,不是技术内容,不应作为报文或信号的资料来源。阅读该仓库时应把 readme.md 与 wiki 当作内容,把 license.md 当作使用边界——引用或再分发这 7 份 DBC 前必须先确认各自的许可条款,尤其是转载自 opendbc、csselectronics 与 haskell.org 的那几份。

    BMW E39 的 DBC 是怎么来的?

    它是从 .kcd 格式转换而来的,仓库明确标注了这一点,版本号为 2021.6.6。跨格式转换会引入字节序、因子与命名的二次解释,因此核对信号定义时应回到原始 .kcd 文件,而不是把转换结果当作一手证据。

    DBC 里的 multiplexer(信号复用)解决什么问题?

    它解决同一条报文在不同场景下承载不同信号的问题:报文里用一个复用选择器决定其余位的含义,从而在不增加 CAN ID 的前提下表达更多状态。仓库的规范文档把 Multiplexers 单列为 SG_ 信号一节的子主题。需要注意若解析器不支持复用,这类报文会被解成错误的信号组合。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/nberlette-canbus/readme.md(DBC 格式定义、8 段规范索引、7 份可下载 DBC 的车型与版本、外部资源与参考链接)

    免责声明

    本文内容整理自公开开源仓库的自述文档,所述文件、版本号与来源标注均以该仓库快照为准,未经独立验证。转载类 DBC 可能已与其上游产生差异,使用前请核对上游当前状态与各文件的许可条款。

    更新记录

    • 2026-10-14 初稿

  • Mazda MX-5 NC 的 CAN 笔记:10 个 ID 与 RaceChrono 公式

    结论:Mazda MX-5 NC(2005–2015)的公开 CAN 笔记给出 10 个可用 ID 与配套 RaceChrono 公式,但覆盖面有硬边界:0x081 转向角、0x085 制动压力、0x090 疑似加速度三帧只在带 DSC 模块的车型(2007 年起)上出现;10 秒怠速直方图里 20 个 ID 中只有 8 个达到 100 Hz,真正被写清解码的不超过 10 个。

    先分清哪些 ID 依赖 DSC

    这份笔记面向第三代 MX-5(NC / NCFL / NCFLFL,即 MK3 / MK3.5 / MK3.75),按 CAN ID 组织,每个 ID 给出字节含义表与 RaceChrono 通道公式。使用时第一个判断不是「这个 ID 有没有」,而是「这辆车有没有 DSC 模块」——转向角、制动压力、疑似加速度三组信号都只在配备 DSC 的车型上存在,也就是 2007 年之后的车。

    CAN ID 更新频率 关键字节 公式 前提条件
    0x201 100 Hz 0–1 转速、4–5 车速、6 油门、7 恒为 FF 转速 = bytestouint(raw,0,2)/4.00;车速 = ((bytestoint(raw,4,2)/100.00)−100)/3.6;油门 = bytestoint(raw,6,1)*2.00 全系
    0x4B0 100 Hz 0–1 左前、2–3 右前、4–5 左后、6–7 右后 四角统一为 ((bytestoint(raw,N,2)/100.00)−100)/3.6 全系,独立承担轮速
    0x200 100 Hz 6 制动开关、7 节气门位置 制动 = data[6] 与 0x1 按位与;节气门 = bytestouint(raw,7,1)*100/255.00 全系;byte7 与 0x215 byte6 同源
    0x215 100 Hz 6 节气门位置,其余多为故障码 bytestouint(raw,6,1)*100/255.00 全系;byte0 与 byte2 互为镜像,byte1 与 byte3 互为镜像
    0x231 40 Hz 1 的 bit3 空挡、bit1 离合 空挡 = data[1] 与 0x4 按位与;离合 = data[1] 与 0x2 按位与 手动挡其余字节恒为 FF 或 00
    0x240 10 Hz 0 计算负载、1 水温、4 进气温度 水温 = bytestouint(raw,1,1)−40;进气 = bytestouint(raw,4,1)−40 全系;水温与 0x420 byte0 同源
    0x081 100 Hz 2–3 有符号转向角,仅 4 字节 bytesToInt(raw,2,2),正值向右 需 DSC 模块,2007 年起
    0x085 100 Hz 0–1 制动压力、2 的 bit0 制动开关 压力 = (3.4518689053*bytesToInt(raw,0,2)−327.27)/1000.00,单位 kPa 需 DSC;系数源自 miata.net 用户数据,作者标注可能错误

    表里最该被记住的不是公式本身,而是最后一列。0x081 与 0x085 一旦用在 2006 年及以前的车上,会表现为「完全没有该 ID」,而不是数值为零。

    车速公式里那两个魔数的来历

    0x201 与 0x4B0 共用同一套换算:原始值以 km/h 为单位但带 100 km/h 偏移,因此先除以 100 再减 100;末尾的 3.6 是把 km/h 换成 m/s,因为 RaceChrono 内部以 m/s 计算,之后由软件按用户选择的单位再乘回去。自己写解析器时若直接用 m/s 之外的单位,就要把这一级换算还原。

    油门通道的公式是 bytestoint(raw,6,1)*2.00,对应 0.5% 的步进;0x201 的 byte2 与 byte3 虽跟随转速变化,但笔记标注它疑似带 0x7fff 偏移且与发动机扭矩无关,属未完成解析项。

    10 秒直方图:用帧数反推频率

    笔记给了一张停车场怠速状态下 10 秒窗口的报文计数直方图,共 20 个 ID。把帧数除以 10 就得到各 ID 的实际频率,这张表可以直接用来判断采样与总线负载。

    10 秒帧数 换算频率 CAN ID(十六进制) 说明
    1000 100 Hz 081、085、090、200、201、211、215、4B0 含全部已解析的动态信号
    500 50 Hz 204、21A 未解析
    400 40 Hz 231、4EC 231 为变速箱,与笔记标注的 40 Hz 一致
    100 10 Hz 212、240、39A、420、430、4FF 240 为发动机数据,与标注的 10 Hz 一致
    10 1 Hz 4F0、4F1 低频,疑似诊断或状态帧

    这张表的实用价值在于排错:如果某台设备上 0x4B0 的计数明显低于 1000,先查总线负载与过滤规则,再去怀疑解码;如果它和 0x240 一起掉,问题多半在总线本身而非解析。

    恒值与未完成项要单独标记

    笔记里有几类条目不能当信号使用。0x211 全为 0xFF;0x212 恒为 80 00 20 40 00 00 00 00,原文用问号表示这只是观察结果;0x090 整帧标记为 WIP,只推测与加速度有关;0x430 的 byte2–7 恒为 0x00,且笔记提示 0x430 在 ND 上才是油量。把它们写进解析配置只会产生恒零通道。

    0x240 这一帧同样混着可用与不可用项:byte0 的计算负载公式为 100*(bytestouint(raw,0,1)/255.00,笔记说明作者在 RaceChrono 的通道列表里找不到对应的 Engine Load 通道;byte3 的节气门位置被标注为绝对开度(计入怠速开度),但作者实测怠速值偏高(约 11%),提示缩放仍需调整;byte2 疑似点火提前角,未给出公式。

    常见问题

    这份 MX-5 NC 的 CAN 笔记覆盖哪些年款?

    笔记标题写明覆盖 2005–2015 的第三代车型(NC / NCFL / NCFLFL,即 MK3 / MK3.5 / MK3.75)。但转向角 0x081、制动压力 0x085 与疑似加速度 0x090 只在带 DSC 模块的车型上存在,也就是 2007 年起;更早的车上这些 ID 根本不会出现。

    0x085 的制动压力公式能直接用吗?

    需谨慎。笔记给出的公式是 (3.4518689053*bytesToInt(raw,0,2)−327.27)/1000.00,单位为 kPa,但作者明确标注系数来自 miata.net 用户数据、可能有误。作为替代,笔记还给出百分比算法 min(0.2*(bytesToInt(raw,0,2)−102),100),未踩时基准值为 102,松开后短暂降到 99 会出现轻微负值。

    车速公式里为什么既要减 100 又要除以 3.6?

    两级换算是两件事。原始车速以 km/h 为单位但带 100 km/h 偏移,所以先除以 100 再减 100 还原真实 km/h;再除以 3.6 是换成 m/s,因为 RaceChrono 内部以 m/s 计算,最终按用户选择的单位自动乘回。自建解析器时若不需要 m/s,应去掉这一级。

    离合与空挡信号在自动挡车上也能用吗?

    不能直接套用。0x231 的 byte1 中 bit3 表示空挡、bit1 表示离合,笔记说明该字节的解读基于手动挡车:手动挡时 byte0、byte2、byte3 恒为 FF,byte4–byte7 恒为 00。笔记也提到该帧对自动挡车可能有更多有意义的数据,但并未给出自动挡下的解析。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/hatsunearu-mx5-nc-notes/mazda_mx5_nc.md(10 个 CAN ID 的字节表、RaceChrono 公式、更新频率与 10 秒怠速直方图)

    免责声明

    本文内容整理自公开开源笔记,其中公式、系数与频率均为原作者基于自车观察给出的结果,部分条目被作者本人标注为未完成或可能错误,未经独立实车验证。不同年款、市场、ECU 版本与是否带 DSC 模块均会导致差异,请以实际抓包与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • VW Grand California 生活舱 CAN:7 个 ID 与 9 条命令

    结论:VW Grand California 的生活舱 CAN 独立于 Crafter 底盘总线,社区已给出 500 kbit/s 的接入方式、7 个 29 位 ID 的功能归属、13 条解码样例与 9 条 cansend 命令。但同一个 ID 在不同字节位上混装多种含义,电流与电压两条规则作者未给出可复核的推导,因此这份表格适合做功能定位与命令复现,不适合直接当计量依据。

    接入:从树莓派到技术柜里的 9、10 针

    项目面向 Grand California 600 与 680 的生活舱总线,作者在免责声明中明确这是教育与研究用途,相关知识产权归属大众集团。硬件用 Raspberry Pi 3B+(作者说明 Pi Zero 2 W 更小巧省电)加一块 Waveshare RS485 CAN HAT(CAN 控制器 MCP2515、485 收发器 SP3485)。软件侧是 can-utils 加 Node-RED 的 node-red-contrib-socketcan 节点,用来搭可在浏览器里打开的仪表盘。

    总线初始化命令为 sudo ip link set can0 up type can bitrate 500000 loopback off listen-only off,监听用 cansniffer can0 -c -t0,发送用 cansend can0 18EF70C9#00.40.00.00.00.00.00.00。物理接入点选在 RGB 灯带控制器(零件号 7C4 947 022)的 9、10 针,该控制器位于 230V 配电盘正下方的技术柜内——这是全篇最省事的一条经验,避免了拆仪表台找线。

    作者还为 SavvyCAN 提供了一份 DBC:VW_GrandCalifornia_J608.dbc。

    七个 ID 的功能归属:一帧多用是常态

    生活舱总线的 ID 全部是 29 位扩展格式(形如 18EFxxxx),且普遍存在「一帧承载多个功能」的情况。下表按作者给出的归属整理,是判断该盯哪一帧的第一层筛选。

    ID 承载功能 备注
    18EF70C9 显示屏开关、卫星(SAT)开关、氛围灯 / 外部灯 / 内部灯 也是文档示例里的发送目标
    18EF70EB 卫星开关、灯光开关、电池剩余时间、车门锁状态 状态回读帧
    18EF71C9 露营模式、WiFi、音响(含蓝牙)、踏板自动 / 伸出 / 收回 命令侧主要目标
    18EF71EB 接收大量内容;露营模式、WiFi、音响状态 作者标注「接收很多东西」
    18EF72EB 灯光开关、230V 输入、电池电流、电压、电量百分比 电池参数集中在这一帧
    18EF73EB 230V 输入、清水与灰水水位 水位需第 1 字节为 01 才有效
    18EF60C9 设置灯带颜色 Y / R / G / B 四组预设值

    注意 18EF72EB 同时承担电流、电压、电量三项:这三项的字节位置完全不同,且分属不同的码制,因此不存在「一个 ID 对应一组语义」的捷径。

    解码规则与位序陷阱

    下表按作者原文的 0 起字节编号整理(原文写作 0ºB、1ºB……)。每行都附了原文给出的样例帧,这是判断规则可信度的关键——有样例的规则可以复现,无样例的只能照抄。

    内容 ID 样例帧 解码规则 可复现性
    清水 / 灰水水位 18EF73EB 00 00 00 00 0B 00 04 00 0 起编号第 4 字节为清水百分比(样例 0x0B)、第 6 字节为灰水(样例 0x04);首字节为 01 时清水箱为空 高,样例与规则自洽
    电池电流(充电) 18EF72EB 50 00 00 8A 59 00 07 02 0 起编号第 6 字节为电流正值(样例 0x07);首字节大于 0 表示充电中 中,未给单位换算
    电池电流(放电) 18EF72EB 00 00 00 0A 4C 00 FF 01 0 起编号第 6 字节为负值,FF = −1、FE = −2、FD = −3,按 MOD 2 递推 中,负值为自定义编码
    电池剩余时间 18EF70EB 01 00 3A 26 00 00 00 00 原文称第 2 字节为小时、第 3 字节为分钟,样例对应 0x3A 与 0x26 中,需确认编号起止
    电池电压 18EF72EB 00 00 00 0A 50 00 FF 01 原文称取第 5 字节(样例值 0x50)转十进制,十位加 5 得整数部分、个位为小数部分 低,推导未说明,需实测复核
    电池电量百分比 18EF72EB 00 00 00 0A 50 00 FF 01 原文称取第 4 字节(样例值 0x0A)为百分比除以 10,经 10*10 换算为 100 低,表述与样例存在张力,需复核
    显示屏开 / 关 18EF70C9 00 40 … / 00 00 … 由 I/O 按键触发,0 起编号第 1 字节为 40 时开、00 时关 高
    车门锁 18EF70EB 00 04 3A 26 00 00 00 00 0 起编号第 1 字节为 04,随后回到 00 中,仅给出单帧切片
    灯带颜色 18EF60C9 1E.00.64.2F… / 08.00.64.25… / 7D.00.64.23… / F5.00.64.2F… 四组预设分别对应 Y、R、G、B,0 起编号第 0 与第 3 字节变化 高,可整帧复现

    两条被标为「低」的规则是最该警惕的:电流与电压共用同一帧,且放电电流用 FF / FE / FD 表示负值、按 MOD 2 递推,与电压那条「十位加 5」的规则都不是标准编码。在没有万用表对照之前,这两项只能看趋势。

    字节编号在同一份表里并不统一

    这是使用这份表格时最容易踩的坑。同一份文档里,水位行说「4ºB = 0B」,只有按 0 起编号才能在样例帧 00 00 00 00 0B 00 04 00 里对上;电流行说「6ºB 是安培值」,也只有 0 起编号才能在 50 00 00 8A 59 00 07 02 里取到 0x07。但电压行与电量百分比行的样例值(0x50 与 0x0A)在同一帧里分别位于从 1 起数的第 5 与第 4 个字节。也就是说原文的编号起止在不同行之间不一致。正确做法是先拿样例帧反推真实位置,再写解析规则,不要直接信任编号本身。

    九条可复现的命令

    作者把可发送的命令单独列了一张表,全部基于 cansend,这也是整份资料里最容易验证的部分。

    功能 命令载荷 目标 ID 效果
    露营模式 00.40.00.00.00.00.00.00 18EF71C9 开 / 关切换
    WiFi 00.01.00.00.00.00.00.00 18EF71C9 开 / 关切换
    踏板自动 04.00.00.00.00.00.00.00 18EF71C9 开 / 关切换
    踏板伸出 10.00.00.00.00.00.00.00 18EF71C9 单次动作
    踏板收回 40.00.00.00.00.00.00.00 18EF71C9 单次动作
    氛围灯 04.40.00.00.00.00.00.00 18EF70C9 开 / 关切换
    外部灯 00.41.00.00.00.00.00.00 18EF70C9 开 / 关切换
    内部灯 01.40.00.00.00.00.00.00 18EF70C9 开 / 关切换
    卫星(SAT) 00.50.00.00.00.00.00.00 18EF70C9 开 / 关切换

    这张表的结构是「同一 ID 内按位区分功能」:18EF71C9 上,0 起编号第 1 字节的 40 / 01 / 04 / 10 / 40 分别对应露营模式、WiFi、踏板自动、踏板伸出、踏板收回;18EF70C9 上则靠 0 起编号第 0 与第 1 两个字节的组合区分氛围灯(04 40)、外部灯(00 41)、内部灯(01 40)与卫星(00 50)。做自动化控制时,正确做法是先读回当前状态再发送,而不是按记忆中的固定序列盲发。

    常见问题

    生活舱 CAN 和 Crafter 底盘 CAN 是同一条总线吗?

    不是。项目说明明确指出生活舱 CAN 独立(或几乎独立)于 Crafter 底盘总线,本文涉及的 ID、命令与解码只适用于生活舱部分。想取发动机、变速箱或底盘数据,需要另外接入底盘侧总线,不能指望从这些 ID 里读出来。

    从哪里接入生活舱总线最省事?

    作者最终选择接在 RGB 灯带控制器(零件号 7C4 947 022)的 9、10 针上,该控制器位于 230V 配电盘正下方的技术柜内。原厂接线图上也标注了多个可接入「便利 CAN」的点位,但灯带控制器这个点被作者评价为最方便。

    电池电流的负值为什么用 FF、FE、FD 表示?

    这是作者从样例帧中归纳出的自定义编码:放电时第 6 字节按 FF = −1、FE = −2、FD = −3 的方式递推,原文写作 MOD 2,与充电时的正值编码不是同一套。由于文档未给出单位与系数推导,实际使用前应与钳形表对照测量。

    清水和灰水水位在同一帧里怎么区分?

    靠字节位置区分:样例帧 00 00 00 00 0B 00 04 00 中,0 起编号第 4 字节(0x0B)是清水百分比、第 6 字节(0x04)是灰水百分比。另外原文注明当首字节为 01 时清水箱判定为空,因此解析时必须先看首字节再取水位值。需注意的是原文编号起止在不同行之间并不统一,实际接入应先按样例帧反推。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/mk4001-vw-grand-california/README.md(硬件与软件清单、500 kbit/s 初始化命令、接入点位与免责声明)
    • 项目 01 —— public-can-dbc-datasets/additional/mk4001-vw-grand-california/Table.md(7 个 ID 的功能归属、13 条解码样例与 9 条 cansend 命令)

    免责声明

    本文内容整理自公开开源项目,原作者已声明该项目仅用于教育与研究,相关 CAN 代码与协议的知识产权归属大众集团,不构成对任何专有系统的授权访问或修改许可。文中字节位置与换算规则均为原作者基于自车观察给出的结果,未经独立验证,不同年款与配置可能存在差异。

    更新记录

    • 2026-10-14 初稿

  • Suzuki Swift ZC32S 的 CAN 地图:6 条报文与 9 个信号

    结论:Suzuki Swift Sport ZC32S 的公开 CAN 地图只有 6 条报文、9 个信号,且刹车压力仍是无物理单位的裸值、转向角只是近似量。它足够驱动一块 ESP32 + MCP2515 的车载 OLED 仪表,但不能当整车网络定义或标定依据——派生出的 DBC 明确假设 Motorola 字节序、DLC 8 与 Unknown 发送方,全部未经实车抓包复核。

    六条报文能做什么:一份为显示服务的地图

    这份地图来自一个车载显示项目,硬件是 ESP32 WROOM 加 MCP2515 CAN 控制器,输出到 SSD1306 OLED,另有 8 颗 WS2812 组成换挡灯、旋转编码器切换页面、ESP32 内置 BLE 被动接收 4 个原厂 TPMS 传感器。它的目标不是整车解析,而是把七个显示页面需要的数据取出来,因此覆盖面天然很窄:转速、四轮轮速、水温、油门、转向角、刹车压力,加上蓝牙胎压。

    CAN ID 信号 字节位置 换算 证据强度
    0x124 发动机转速 data[1]、data[2] raw 为 data[1] 高字节、data[2] 低字节合成的 16 位值;RPM = raw / 4 高,README 与固件一致
    0x1B8 四轮轮速 FR 0–1、FL 2–3、RR 4–5、RL 6–7 km/h = raw × 0.0276923 高,四角各 16 位
    0x310 冷却液温度 data[1] TempC = data[1] − 40 高,单字节偏移
    0x122 油门踏板 data[1] Pedal% = data[1] × 100.0 / 255.0 高,单字节比例
    0x119 转向角 data[2]、data[3] 居中约 32768,满舵约 ±495°(左约 37792、右约 27808) 中,作者标注为近似
    0x1AF 刹车压力 data[6]、data[7] 无换算,保留有符号裸值 低,未声明物理单位

    真正决定这份地图可用性的不是 ID 数量,而是最后一列。前四行的公式是可以直接搬进固件的;转向角只能用于「左打还是右打」这类定性显示;刹车压力连单位都没有,只能画相对变化趋势。

    TPMS 走的是蓝牙,不是 CAN

    四个原厂胎压传感器通过 BLE 广播被 ESP32 被动接收,按固定 MAC 地址区分左前、右前、左后、右后。压力换算为 ((data[3] << 8 | data[4]) / 10.0 * 0.0689476) - 1.0(单位 bar),温度为有符号字节 data[2]。扫描跑在独立的 FreeRTOS 任务里,以免阻塞 CAN 接收。这意味着胎压与 CAN 数据是两条独立链路,做数据融合时必须各自打时间戳,不能假设同源同周期。

    派生 DBC 的四条假设:用之前必须知道

    归档方从这份公开地图生成了一份派生 DBC(6 条报文、9 个信号),但它同时明确列出了自己做过的假设。这四条假设就是使用边界。

    假设项 取值 为何这样假设 校验方式
    字节序 Motorola(高字节在前) 固件表达式为高字节在前 抓包后按两种字节序分别解码比对
    帧长度 DLC 8 README 未给出实际帧长 抓包读取实际 DLC
    发送方 Unknown,消费者标记 Display 发送 ECU 身份未知 按 ID 反查总线活动与断电隔离
    单位与标定 刹车保持裸值,转向角近似且被固件截断为整数 固件显示公式未声明物理单位 需与制动压力传感器、转角台架对照

    把假设显式写出来,比把不确定项悄悄填成确定值要安全得多。派生文件本身也被声明为独立整理的研究草稿,既不是上游产物也不是原厂 DBC;车型适配、总线段归属、单位与缩放都未经抓包核对。

    100 Hz 与 10 Hz:为什么轮速帧要单独分配缓冲

    这一条是整份文档里最有工程价值的细节。轮速帧 0x1B8 的速率是 100 Hz,水温帧 0x310 是 10 Hz,两者速率相差一个数量级。MCP2515 的硬件滤波器把接收缓冲 RXB0 单独留给水温 ID,避免高频轮速帧把尚未读取的水温帧覆盖掉。

    同一条经验对任何 MCU 方案都成立:当同一总线上混装不同周期的报文时,接收缓冲与中断优先级的分配要按「最慢的那一帧」来设计,而不是按平均速率。否则表现不是报错,而是某个慢信号偶发跳变——这类问题在后期极难定位。

    另外还需注意权利状态:归档说明指出该修订版本未找到仓库许可证,因此派生文件与来源 README 被作为私有离线研究副本保留,在权利确认前不宜再分发或集成。

    常见问题

    这份 ZC32S 的 CAN 地图能直接用于整车网络解析吗?

    不能。它只有 6 条报文、9 个信号,目标是为车载显示取数,不是整车网络定义。派生 DBC 也明确声明车型适配、总线段归属、单位与缩放未经抓包核对,未找到上游许可证,只能作离线研究参考。

    为什么 0x1B8 轮速帧要单独处理接收缓冲?

    因为速率相差一个数量级:轮速帧 0x1B8 为 100 Hz,水温帧 0x310 为 10 Hz。作者用 MCP2515 的硬件滤波器把接收缓冲 RXB0 单独分配给水温 ID,使高频帧无法覆盖尚未读取的低频帧,否则故障表现是水温偶发跳变而非报错。

    转向角 0x119 的 ±495° 能直接当作标定值用吗?

    不能。归档说明指出转向角是近似值,且固件把它截断为整数处理。它只能支持定性显示(居左、居中、居右)与粗略角度趋势,要做转向角的定量分析需要在转角台架上重新标定,并确认左约 37792、右约 27808、居中约 32768 这三个锚点。

    派生 DBC 里刹车压力为什么没有单位?

    因为来源固件的显示公式没有声明物理单位,归档方据此保留了有符号裸值 raw = (data[6] << 8) | data[7]。在获得制动压力传感器的对照测量之前,这个值只能用于观察相对变化,不能换算成 bar 或 MPa,更不能作为制动强度的判断依据。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/8rea-suzuki-swift-zc32s/README.upstream.md(6 个 CAN ID 的字节位置、换算公式、帧率与 MCP2515 缓冲分配)
    • 项目 01 —— public-can-dbc-datasets/additional/8rea-suzuki-swift-zc32s/SOURCE.md(派生 DBC 的 6 报文 9 信号、Motorola 与 DLC 8 假设、权利状态)
    • 项目 01 —— public-can-dbc-datasets/additional/8rea-suzuki-swift-zc32s/README.md(硬件清单、TPMS 蓝牙换算与显示页面结构)

    免责声明

    本文所述 CAN ID、字节位置与换算公式均来自公开开源仓库的说明文件,属社区逆向工程产物,不代表车辆制造商的官方数据,未经独立实车抓包验证。不同车型年款、市场与 ECU 版本可能存在差异。涉及行车安全的改动请以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • DBC 到固件的版本校验:T26 用 64 位 SHA-256 心跳

    结论:T26 的 DBC 工作流把版本一致性做成了一条 CAN 心跳:cantools 生成 C 代码的同时,脚本把每个 DBC 的 SHA-256 截断为前 8 字节(64 bit)写成宏,各 ECU 用专用 ID 0x055、DLC 8 周期广播并互相比对。截断到 64 bit 不是为了省事,而是为了塞进一帧经典 CAN 的 8 字节载荷——代价是碰撞概率从 2⁻²⁵⁶ 升到约 2⁻⁶⁴,对这个用途完全够用。

    DBC 字段与固件解码的一一对应

    DBC 的价值在于把十六进制报文翻译成带名字和单位的信号。T26 的流程从 Kvaser Database Editor 建库开始:先建节点(如 ECU_Principal),再建报文(Name、ID、DLC、Transmitter),最后逐条加信号。每个字段的填写错误都会直接变成固件里的读数错误。

    DBC 字段 要填什么 填错后的固件表现
    ID 与 DLC CAN 标识符与字节长度(如 0x101、8) 收不到该帧,或按错误长度解包直接越界
    Start bit 与 Length 起始位与位长度(如 0、16) 取到相邻信号的位,数值整体偏移
    Byte order Intel(小端)或 Motorola(大端) 高低字节互换,数值随量级剧烈跳变
    Value type Signed / Unsigned 负值变成极大正数,温度、转矩类信号尤其明显
    Factor 与 Offset 缩放因子与偏移(如 factor = 0.1,则 100 表示 10.0 km/h) 量程整体缩放错误,趋势对但绝对值全错
    Unit 单位(如 km/h) 不影响解码,但跨团队协作时是主要误读源

    这张表也是版本校验为何必要的直接解释:上述任何一格被改动,固件都不会报错,只会安静地输出错误数据。

    自动生成:DBC 到 C 代码与 Excel

    仓库配了一个 GitHub Actions 工作流,每当 DBC 变更被推送,就用 python3 -m cantools generate_c_source Autonomous.dbc --output autonomous_c_output 重新生成 C 代码,产物落在 generated/。同一个工作流还会导出 xls,每个 DBC 一个页面、每个 ID 一张表,方便非固件成员审阅。

    把生成环节放进 CI 的意义在于消除「本地改了 DBC、忘了重新生成」这类偏差。手工维护的解码头文件几乎必然与 DBC 漂移,而漂移本身不可见。

    版本校验怎么做

    工作流同时执行 embed_dbc_sha256.py,计算每个 .dbc 的 SHA-256,并把结果作为宏写进生成的头文件:

    #define DATA_T26_DBC_SHA256 0x3ee5339f1dc658c6ULL

    为塞进经典 CAN 单帧最大 8 字节的限制,哈希被截断为 SHA-256 的前 8 字节(64 bit)。文档给出的取舍依据是:两个不同版本碰撞的概率约 2⁻⁶⁴;要累积到约 43 亿个版本才有 50% 的碰撞概率;而加密哈希的前 64 位仍保留完整的雪崩效应,改一个字节就会改变该值。

    方案 承载报文 载荷长度 碰撞概率 适用网络
    截断 64 bit 经典 CAN 2.0,DLC 8 8 字节 约 2⁻⁶⁴,约 43 亿版本才有 50% 概率 CAN 2.0 网络
    完整 256 bit CAN FD 单帧 32 字节 2⁻²⁵⁶ 需 CAN FD(单帧至多 64 字节)

    文档给的实现示例是 STM32 HAL + CAN 2.0:每个 ECU 用专用 ID 0x055(文中示例为每 1 秒一次)发送 8 字节版本帧,其余 ECU 收到后与自身宏比对,不一致即判定为版本落后并告警或拒绝该节点。拷贝时所有 ECU 必须统一使用 Intel 小端字节序,否则比对本身会失效。

    不做校验会发生什么

    文档把风险写得很直白:运行旧版 DBC 的 ECU 会按错误的 bit order、factor、offset 或信号位置去解释报文,可能导致传感器读数错误、发动机与制动等系统误动作、以及难以诊断的安全故障——而这些症状在运行时没有任何可见错误。加上版本常量比对后,版本分歧在第一帧收到时就能被发现。

    在 Teensy 4.1 上的落地形态

    仓库给出的 MCU 示例用 FlexCAN_T4,CAN.setBaudRate(500000),接收队列 RX_SIZE_256、发送队列 TX_SIZE_16。解码时直接包含生成的头文件,例如 autonomous_dv_driving_dynamics_1.h,调用 autonomous_dv_driving_dynamics_1_unpack 读入 speed_actual、speed_target、steering_angle_actual;回包时用 _pack 打包,示例把 speed_target 改为 150 后写回同一 ID。

    这条链路把「DBC 是唯一事实源」落到了实处:固件里不应再出现手写的位运算,所有位定义都来自生成产物,而生成产物与 DBC 哈希绑定。

    常见问题

    为什么 SHA-256 要截断到 64 位?

    为了塞进一帧经典 CAN。CAN 2.0 单帧最多 8 字节,因此只取 SHA-256 的前 8 字节(64 bit)作为宏。文档给出的依据是碰撞概率约 2⁻⁶⁴、需约 43 亿个版本才有 50% 碰撞概率,且前 64 位保留完整雪崩效应,改一个字节即变化。

    DBC 版本不一致在实车上会表现出什么症状?

    不会报错,只会输出错误数据。运行旧版 DBC 的 ECU 会按错误的 bit order、factor、offset 或信号位置解包,导致传感器读数错误、执行系统误动作以及难以诊断的安全故障,运行期没有可见错误提示。因此需要版本心跳在第一帧就比对出来。

    版本心跳必须用 0x055 吗?

    不必。0x055 只是文档示例里为版本心跳专门分配的 ID,任何未被占用的标准 ID 都可以,关键是全网络约定一致、DLC 固定为 8,且所有 ECU 拷贝常量时使用相同的 Intel 小端字节序。

    没有 CAN FD 的网络还能做版本校验吗?

    能。经典 CAN 用截断到 64 bit 的方案即可,把 8 字节常量放进 DLC 8 的帧里周期广播。若网络支持 CAN FD(单帧至多 64 字节),则可以一帧发送完整的 32 字节 SHA-256,无需截断。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/fslart-t26-dbc/README.md(DBC 字段定义、cantools 自动生成、SHA-256 截断与 0x055 心跳示例、Teensy 4.1 用例)

    免责声明

    本文内容整理自公开开源仓库的自述文档,其中的宏值、ID、波特率与概率估算均为该仓库给出的示例或说明,未经独立实测验证。不同工具链、编译器与网络拓扑下的实现细节可能不同,工程落地请以实际测试为准。

    更新记录

    • 2026-10-14 初稿