标签: CAN总线

  • 电动车与性能数据的三条通道:OBD、专属 CAN 与车企云端

    结论:电动车与性能数据可以归到三条通道:标准 OBD2 服务、车型专属 CAN(含专用线束)、车企云端接口。三者读取的原始信号不同——标准通道给出发动机与排放相关的 PID / DTC;专属通道给出 BMS 单体电压、温度、SOC 与充电记录,或电机扭矩等;云端接口给出由车企托管的历史车况。选型时最需要先确定的是数据来自哪条通道,因为「有 OBD2 接口即可读」对电池类信号并不成立。

    三条数据通道与它们能读到什么

    公开资料把车载数据按用途分成三类,每类的核心原始信号与验证风险都不同:

    数据用途 核心原始信号 用户真正需要的输出 主要验证风险
    通用 OBD2 诊断 排放相关 PID、DTC、冻结帧 故障原因、可否继续驾驶、维修路径 适配器质量、车型协议、解释准确性
    电动车电池 BMS / CAN 单体电压、温度、SOC、充电记录 电池健康、衰减与购车风险 车型专有信号、网关限制、SOH 算法与实测差异
    驾驶 / 赛道数据 OBD2、GPS、IMU、视频 圈次、驾驶表现、可回放数据 时间同步、采样频率、GPS 精度、数据丢失

    三条通道的入口形态也不同:标准通道走通用适配器;电池通道往往要求专用 CAN 线束,公开资料明确某些车型「标准 OBD2 口没有该数据」;云端通道则依赖车企账号授权,硬件可完全缺席。把这三类混在一起比「支持多少模块」会失去意义。

    电池数据的价值在「单体」,不在「整车」

    电动车数据的核心颗粒度是电池单体。公开资料中,某类单车型电池监测应用可以读取约 96 组电池单体电压、最小 / 平均 / 最大值与分布图,用于监测均衡与健康;另一类产品则把单体电压、温度、SOC 离散度与充电限制汇成评分与 PDF,用于二手车交易沟通。

    同一份电池数据在不同产品上的解释口径并不统一。公开资料举例:有产品把电池健康分成「标称容量」与「交付容量」两种 SOH 基准;也有产品的电池健康图其实是基于续航、SOC 与效率的估计,而非直接测量。这意味着「SOH 多少」这句话只有附上基准与算法口径才可比较。

    此外,同一车型的年款覆盖也需要逐条核对。公开资料中,某款应用的适配车型列出 2011–2025 年款,2026 年车型尚未验证;这提醒我们,电动车数据的可用性受年款、总线与接头三重限制。

    性能数据的重心是圈次与时间轴

    驾驶 / 赛道数据的关键不是故障,而是时间轴对齐。公开资料中,赛道类应用以 GPS / IMU、受支持 OBD 适配器、自定义 CAN 通道与视频为输入,把 GPS 时间戳嵌入记录或用偏移对齐视频与会话,输出圈次分析、叠加视频与多种数据格式。这类应用常把 OBD 的 Fast / Slow 通道设置为共享带宽,因此参数越多,单项刷新越慢。

    还有一个容易被忽略的边界:油耗、功率、扭矩等显示项在部分产品中可能是计算值,不能等同于 ECU 直接回传。评估性能数据时,应区分「传感器 / ECU 原始值」与「由模型或公式推导出的值」。

    因此比较性能类产品时,应把「来源」写在指标旁边:哪些来自 OBD、哪些来自 GPS / IMU、哪些由公式推算。只有来源与采样口径一致,跨产品的圈次对比才有意义。三条通道还有一个共同前提是数据质量——断连、缺测、旧值与估算置信度都会影响结论,因此在选定通道后,仍需为每个字段标注来源与新鲜度。

    三条通道对应的验证清单

    把用途与风险对齐后,选型可以按下面三类问题逐项核对:

    通道 先问的问题 需要准备的条件
    标准 OBD2 目标车型支持哪些标准 PID 与服务 合适的适配器、稳定的连接
    车型专属 CAN 该信号是否走 BMS / 专用总线,是否需要专线束 对应车型的线束与解码定义
    车企云端 授权范围、数据字段与导出方式 车辆账号与相应接口权限

    这三类条件往往互不替代:标准适配器读不到电池单体,专用线束也拿不到其他车型的数据,云端接口则受账号与地区限制。

    常见问题

    有 OBD2 口就能读电池数据吗?

    不一定。公开资料明确某些车型的标准 OBD2 口没有电池数据,需要适配器加接入专用 CAN 总线的线束。电池类信号往往来自 BMS 或其他专属总线。

    电池健康(SOH)可以直接比较吗?

    不能直接比较。公开资料中,不同产品的 SOH 基准(标称容量 / 交付容量)与算法不同,有的还是基于续航与效率的估计。比较前必须核对基准与算法口径。

    赛道应用里的功率、扭矩是真实回传值吗?

    不一定。部分产品的油耗、功率、扭矩可能为计算值,不能等同 ECU 直接回传。判断时应区分原始信号与由公式推导的值。

    为什么同时看很多参数会变慢?

    因为赛道类应用常把 OBD 的 Fast / Slow 通道设为共享带宽,参数越多单项刷新越慢。这也是采样频率与时间同步成为主要验证风险的原因。

    延伸阅读

    参考资料

    • 项目 01 —— car-scanner-research/电动车与性能数据.md(取用三条数据通道、电池单体数据口径、SOH 基准差异、性能数据的时间轴与共享带宽口径;未引用任何逆向材料)。
    • 项目 01 —— car-scanner-research/横向对比与机会.md(取用电动车与燃油车数据价值不同的横向判断)。

    说明:本文仅取用公开产品说明对电动车与性能数据通道的分类口径,未安装任何安装包、未连接车辆或线束、未进行通信抓包,也未核验各产品宣称的车型覆盖、单体数量与算法准确性。文中所有通道、指标与边界均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

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

  • 雪铁龙 C2 的 CAN-Confort:125 kbit/s 上解码 16 个 PSA 标识符

    结论:在一辆雪铁龙 C2 1.1(TU1JP,BSI AEE2004,EMF 为 Magneti Marelli)上,舒适总线 CAN-Confort 是 125 kbit/s、11 位标识符,而且它不经过 OBD 口——只能在收音机后方的 Quadlock 连接器(pin 10 CAN-H、pin 13 CAN-L)上接入。文档在该总线上识别出 16 个 PSA AEE2004 标识符,并解码转速、车速、水温、车门、灯光、方向盘按钮、续航与保养提醒等信号。边界有三条:部分信号只有单点标定或来自公开参考结构、未在本车验证;外部温度与总里程存疑;结论只覆盖这一辆 C2,不能外推到其他 C2 或 PSA 车型。

    本文整理自该项目的 CAN 解码文档。文档为每个信号标注了证据等级,本文原样保留其分级。

    车辆与适用范围

    数据来自一位车主的这辆 C2;原车 RD4 收音机换为一台后装安卓车机,解码用于方向盘控制、实时仪表与多功能屏(EMF)操控。

    项 内容
    车型 雪铁龙 C2 1.1(发动机 TU1JP,BSI AEE2004,EMF 为 Magneti Marelli)
    年款 / 市场版本 源文档未给出具体年款(PSA C2 平台文档标注为 2003–2009,BSI 第二代)
    ECU / 改装状态 原车 RD4 收音机已拆,替换为后装安卓车机;由一款 SLCAN 协议的开源 CAN 适配器接入
    采集跨度 实车现场测试 2026-04-26;配合诊断工具截图的标定会话 2026-05-03
    适用范围 仅这一辆 C2;多条标定仍需在车上复核

    总线与寻址

    目标是舒适总线 CAN-Confort,速率 125 kbit/s、11 位标识符。接入点在收音机后方的 Quadlock,pin 10 为 CAN-H、pin 13 为 CAN-L;文档明确指出 OBD 口不暴露这条总线,因此不能从诊断座直读。适配器未加 120 Ω 终端电阻(文档说明总线本身已有终端)。

    项 内容
    物理层 CAN-Confort,125 kbit/s(区别于 500 kbit/s 的 CAN-IS)
    链路层 11 位标识符
    接入点 收音机 Quadlock:pin 10 CAN-H、pin 13 CAN-L;OBD 口不暴露该总线
    CAN FD 源文档未提及,按 125 kbit/s 的 AEE2004 语境应视为经典 CAN
    现场总线负载 约 185 帧/秒、38 个不同标识符(现场测试记录)

    已解码信号

    下表从文档信号表中抽取代表性条目,证据等级沿用原文:✅ 在本车验证(现场测试或用户确认)、🎯 只用一个测量点标定(该点正确、斜率未验证)、📄 取自公开的 AEE2004 参考结构(未在本车验证)、⚠ 来源互相矛盾。字节从 0 起编号,BE 为大端。

    信号 位置(ID / 字节) 解码 证据
    发动机转速 rpm 0x0B6 字节 0-1(BE) ÷ 8,四舍五入到 0.1 转/分 ✅ 怠速 704–768 转/分(诊断工具读数)
    车速 speed 0x0B6 字节 2-3(BE) ÷ 100,四舍五入到 0.1 km/h ✅ 静止时确认;行驶中待与 GPS 比对
    冷却液温度 tCoolant 0x0F6 字节 1 字节 − 53 摄氏度;0xFF 表示未就绪(null) 🎯 92 摄氏度对应 0x91(测量中水温在 86–92 波动)
    总里程 odo 0x0F6 字节 2-4(BE) ÷ 10 公里;0xFFFFFF 表示未就绪 ⚠ 取自参考结构;现场测试未找到对应图案
    外部温度 tExt 0x0F6 字节 6 字节 − 102 摄氏度;0xFF 表示未就绪;另加用户偏移 ⚠ 三种假设互相矛盾
    倒挡 reverseGear 0x0F6 位 7.7 位为 1 表示挂倒挡 📄 参考结构
    手刹 handbrake 0x128 位 0.5 位为 1 表示手刹拉起 ✅
    转向灯(左 / 右) 0x128 位 4.1 / 4.2 对应位为 1 表示点亮(双闪为两位同时) ✅
    远光 / 近光 / 示宽灯 0x128 位 4.5 / 4.6 / 4.7 对应位为 1 表示点亮 ✅
    机油温度 tOil 0x161 字节 2 字节 − 64 摄氏度;0x00 与 0xFF 表示未就绪 🎯 71 摄氏度对应 0x86(算出 70)
    燃油百分比 fuelPct 0x161 字节 3 直接取百分比 ✅ 用户确认(2026-05-09)
    续航 rangeKm 0x221 字节 3-4(BE) 公里;0xFFFF 表示未计算 ✅ 440 km(帧内 0x01B8)
    瞬时油耗 fuelInst 0x221 字节 1-2(BE) ÷ 10 升/百公里;0xFFFF 表示未计算(停车时) 📄 与诊断工具「停车时显示未计算」一致
    方向盘按钮 0x21F 字节 0(位图) 位 1 源、位 2 音量减、位 3 音量加(本车与通用文档相反)、位 6 上一曲、位 7 下一曲 ✅ 本车完全验证
    车门(驾驶员 / 乘客 / 尾门) 0x220 位 0.7 / 0.6 / 0.3 对应位为 1 表示打开 ✅
    平均油耗 tripAvgCons 0x261 字节 4 ÷ 10 升/百公里 ✅ 7.6 升/百公里对应 0x4C

    读取方法与注意事项

    哨兵值一律视为「未就绪」。文档规定:温度为 0xFF、里程为 0xFFFFFF、0xFFFF 类字段在充电或刚唤醒时代表「尚未可用」,解码器应输出 null,绝不当作真实数值。

    节奏由 0x0B6 决定。0x0B6 以 20–50 Hz 发送,界面按 10 Hz 采样,音频逐帧跟随。

    按钮要防抖,并注意本车接线方向。0x21F 的字节 1 是滚轮的累计计数,应用需自行计算两帧之间的带符号差值。信号处理采用上升沿加 200 毫秒防抖。这台 C2 的 VOL+ 与 VOL− 与通用文档相反,位图不能照抄。

    发送会落在真车上。文档列出的发送帧(如多功能屏按键、校时帧)会直接发到车辆实际总线,有风险。关于用 CAN 设置 EMF 时钟:文档记录了多次尝试与「未提供可行方法,也不建议尝试」的结论——校时要么走多功能屏自身的菜单,要么依赖原车收音机的私有序列,不存在文档化的 CAN 校时方案。

    证据等级与边界

    文档的分级是硬边界:✅ 本车验证,🎯 只有单点标定(点正确、斜率未验证),📄 取自公开参考结构未在本车验证,⚠ 来源互相矛盾。也就是说,🎯 与 📄 两类条目尚未在这辆 C2 上成立,不能当作已确认字段使用。

    文档还专门列出「待复核」清单:外部温度存在三种互斥假设,都只在 23 摄氏度一点上对齐,斜率未验证;总里程来自参考结构但现场测试未找到对应图案,且参考诊断点自身也不自洽;机油 / 水温斜率只有一个点;行驶中的车速尚待与 GPS 比对;保养 0x3A7 与行程距离 0x261 的格式也未确认。

    另有至今未找到的信号:电池电压、进气温度、BSI 时间(0x276 帧缺失)、EMF 时钟(不能通过 CAN 设置)。这些应记为「未确认」,而非「不存在」。所有结论限于这一辆 C2,不能外推到其他 C2 或 PSA 车型——本车已经出现了与通用文档相反的方向盘按钮接线,正说明逐车核对是必需的。

    常见问题

    雪铁龙 C2 的 CAN-Confort,能从 OBD 口直接读吗?

    不能。文档明确指出 OBD 口不暴露这条总线,接入点是在收音机后方的 Quadlock 连接器(pin 10 CAN-H、pin 13 CAN-L),速率 125 kbit/s、11 位标识符。

    为什么车速在静止时已确认,行驶中还要再核对?

    因为静止时只能确认零值与量程端点,无法验证斜率。文档把「行驶中把 speed 与 GPS 比对」列为待办,说明该字段在动起来之后仍需独立确认。

    为什么这台车的 VOL+ 和 VOL− 与通用 PSA 文档相反?

    文档记录这台 C2 的接线本身就把 VOL+ 与 VOL− 对调了。方向盘按钮 0x21F 虽已在本车完全验证,但位图不能照抄通用文档,必须按本车实测为准。

    外部温度和总里程为什么被标成存疑?

    外部温度有三种互斥假设,且都只在 23 摄氏度这一个点上对齐,斜率未验证;总里程取自公开参考结构,但现场测试未在总线上找到与仪表读数对应的图案,参考诊断点自身也不自洽。两者都需要更多实车数据才能确定。

    能用 CAN 设置多功能屏(EMF)的时钟吗?

    文档记录的全部尝试都失败了,并明确给出「源文档未提供可行方法,也不建议尝试」的结论。校时只能走多功能屏自身菜单,或依赖原车收音机的私有序列;不存在文档化的 CAN 校时方案。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/wasabules-citroen-c2/docs/can/signaux_decodes.md(本项目车型档案主来源,取用了信号表与证据分级)。
    • 项目 01 —— public-can-dbc-datasets/additional/wasabules-citroen-c2/docs/can/psa_can_confort.md(取用了 CAN-Confort 的通用标识符与载荷说明)。
    • 项目 01 —— public-can-dbc-datasets/additional/wasabules-citroen-c2/docs/can/c2_field_test_results.md(取用了现场测试的验证项与失败尝试记录)。

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

    更新记录

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

  • 大众 MLB/PQ 构帧器:返回类型不匹配与固件白名单

    结论:大众 MLB 与 PQ 共用同一个 CarController 和一套「统一 CCS 插件接口」,但两者的纵向实现并不等价。静态源码里有两处硬边界:PQ 纵向助手返回帧列表(与 can_sends.extend() 一致),而 MLB 助手返回 CANPacker.make_can_msg() 的 (address, bytes, bus) 单帧三元组,extend() 会把三个成员分别加入列表——这是源码可见的返回类型不匹配;同时 MLB 固件安全配置只允许 HCA_01、LDW_02、两总线的 LS_01,没有 ACC_05/ACC_02。统一接口不能掩盖这些差异。

    共享控制器与两套构帧器

    基线是 openpilot 固定快照 c8fb906,覆盖 mlbcan.py 与 pqcan.py 的全部实现函数,并追踪共享车型控制器、接口配置、DBC packer 与 panda safety。仅做静态分析:未发 CAN、未改 ECU、未跑实车。共享控制器 CarController.update() 先限扭矩、做重复值缓解,再以非零扭矩作为 HCA 使能值。

    功能 MLB 实现 PQ 实现
    转向 create_steering_control() 输出 HCA_01,状态 7/3 与 lkas_enabled 对应,扭矩拆绝对值和符号。 create_steering_control() 输出 HCA_1,仅在 enabled 且扭矩非零时状态 7,否则 3。
    LDW / HUD create_lka_hud_control() 直接委托 MQB 构帧。 构造 LDW_Status,可复制五个原车警示字段,再覆盖车道线/告警/转向提示。
    巡航按钮 复制 LS_01 四个配置字段,原车 COUNTER+1 mod 16,覆写 cancel/resume。 对 GRA_Neu 作同类处理。
    纵向状态 acc_control_value() 与 acc_hud_status_value() 均固定返回零。 acc_control_value() 按活动/主开关返回 1/2/0;acc_hud_status_value() 另将故障置 6。

    按钮帧由 pcmCruise、原车 COUNTER 变化与 cancel/resume 请求共同决定发送,总线由 CAN.ext 选择;LDW/HUD 按平台 LDW_STEP 发送,输入来自 CarState 的原车缓存。纵向状态分支只在 openpilotLongitudinalControl 为真时走自控纵向及其 HUD 分支。

    需要说明的是,「什么时候发」和「发什么内容」由不同东西决定:LDW/HUD 依平台的 LDW_STEP 节拍发送,纵向 HUD 依 ACC_HUD_STEP 把单个返回值 append 到发送列表,而内容取自 CarState 缓存的原车配置与计数。节拍常量与原车缓存只保证本机按序产出候选帧,并不等于车辆已接受该帧。

    纵向路径与返回类型不匹配

    加速度与纵向 HUD 构帧是差异最集中的地方。MLB 的 create_acc_accel_control() 用空字段构造单个 ACC_05 三元组,create_acc_hud_control() 用空字段构造 ACC_02;PQ 的 create_acc_accel_control() 构造 ACC_System 并返回单元素列表(关闭时加速度字段用 3.01),create_acc_hud_control() 构造 ACC_GRA_Anzeige,包含状态、目标车速和距离。

    控制器统一调用 can_sends.extend(...),但两种助手的返回类型并不一致:PQ 返回 list[frame],与 extend() 语义一致;MLB 返回 CANPacker.make_can_msg() 的 (address, bytes, bus) 单帧三元组,extend() 会把三个成员分别加入 can_sends,不再是帧列表。这是源码可见的返回类型不匹配,MLB 自控纵向不能据此视为可工作。

    这类差异不会在简单调用里立刻显形:PQ 返回单元素列表,可直接被 extend() 展开为帧;MLB 返回的是 make_can_msg() 的三元组,被 extend() 展开后会把地址、字节和总线各自当成一个元素,破坏原本的帧列表结构。只有真正进入发送链路,这种结构错位才会以异常或错误帧的形式暴露。

    校验与固件白名单

    MLB 的 volkswagen_mlb_checksum() 对十个指定地址使用不同 XOR 初值,其他地址回退 MQB/MEB CRC;PQ 文件没有独立校验函数,由其 DBC/packer 负责已声明的计数和校验字段。CANPacker.pack() 按 DBC signal 类型选回调并填入校验,但它不替代 panda RX/TX 安全检查。

    换句话说,校验只回答「这段字节是否按 DBC 约定自洽」,不回答「这条帧是否应该被允许发出」。后者由固件白名单与安全模式独立裁定,两者不能互相代替。

    可达性边界 源码可见事实
    接口能力 接口对 PQ/MLB 都可在 alpha_long 置位时设置 openpilotLongitudinalControl,但两者纵向实现不等价。
    返回类型 MLB 纵向助手返回单帧三元组,被 extend() 拆成三个成员;PQ 返回帧列表。
    固件白名单 MLB 仅允许 HCA_01、LDW_02 与两总线的 LS_01,无 ACC_05/ACC_02。
    构建门 MLB/PQ 两个 safety 模式都仅在 ALLOW_DEBUG 下注册,发布构建不能因识别到平台便假定可启用。
    数据质量 按钮门的当前实现只比较 COUNTER 是否变化,未同时校验该帧接收时间或原车数据质量。

    PQ 的 ACC_System 虽然存在明确的活动/非活动加速度编码、固件也有单独的纵向配置与加速度限幅,但这仅说明源码中存在对应路径,不等于车辆已验证。按钮帧引用 CarState 缓存的原车配置及计数,接线/插件层需保留 bus、时间戳与报文健康,不能只传一个 cancel 布尔量。

    新硬件的验收要点

    新硬件的验收应分别列出 MLB/PQ 车型身份、网络位置、线束、DBC、固件 safety 配置、计数/校验、失联数据新鲜度和拒帧行为。尤其不能让「统一 CCS 插件接口」掩盖 MLB 的占位纵向实现或返回类型差异。

    验收项 MLB 关注点 PQ 关注点
    纵向可发性 返回类型须先修正,且固件白名单不含 ACC 帧。 返回列表与 extend 一致,但仍需实车验证。
    安全模式 仅在 ALLOW_DEBUG 注册。 仅在 ALLOW_DEBUG 注册。
    计数/校验 十地址 XOR 初值 + MQB/MEB 回退。 由 DBC/packer 声明字段负责。
    数据新鲜度 按钮门不校验接收时间。 按钮门不校验接收时间。

    本机隔离探针未完成:系统 Python 缺 numpy,工作区 Python 缺 capnp;本篇没有运行 DBC 字节回放、目标固件或实车试验。归档源码未编辑。

    常见问题

    为什么大众 MLB 的自控纵向「看起来有实现」却不能用?

    因为源码里 MLB 的纵向助手返回的是 CANPacker.make_can_msg() 的 (address, bytes, bus) 单帧三元组,而控制器用 can_sends.extend() 追加,会把三个成员拆开,不再是帧列表;同时 MLB 固件安全配置只允许 HCA_01、LDW_02 与两总线的 LS_01,没有 ACC_05/ACC_02。返回类型不匹配与白名单缺口是两处独立证据。

    PQ 和 MLB 的转向构帧有什么差别?

    MLB 的 create_steering_control() 输出 HCA_01,状态 7/3 与 lkas_enabled 对应,扭矩拆成绝对值和符号;PQ 输出 HCA_1,仅在 enabled 且扭矩非零时状态取 7,否则取 3。两者都经共享控制器先限扭矩、做重复值缓解。

    两个平台都设了 openpilotLongitudinalControl 就等价吗?

    不等价。接口对 PQ/MLB 都可在 alpha_long 置位时设置 openpilotLongitudinalControl,但两者的纵向实现(返回类型、固件白名单、状态编码)都不同;且 MLB/PQ 两个 safety 模式都仅在 ALLOW_DEBUG 下注册,发布构建不能因识别到平台就假定可启用。

    按钮帧只比较 COUNTER 变化够吗?

    源码中该门只比较 COUNTER 是否变化,没有在本地控制器同时校验该帧的接收时间或原车数据质量。接线/插件层因此需保留 bus、时间戳与报文健康,不能只传一个 cancel 布尔量。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/VW_MLB_PQ_CAN_BUILDER_CONTRACT_DEEP_DIVE.md(取用了 MLB/PQ 构帧函数矩阵、纵向返回类型不匹配、MLB 校验与固件白名单、验收要点)。
    • 项目 02 —— openpilot-research/VOLKSWAGEN_MLB_PANDA_SAFETY_DEEP_DIVE.md(仅用于确认 MLB safety 语境的接续关系,未取用其未公开内容)。

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

    更新记录

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

  • VW PQ35 ABS 仿真器档案:Bremse 帧与 0x7E9 车速

    结论:这份档案记录的是 VW PQ35 平台上一组用于「替代原厂 ABS 模块后恢复仪表」的 CAN 报文:一台开源设备(ESP32 + MCP2515)从 OBD 地址 0x7E9 读取 09G 变速箱的车速(PID 0x0D),再向动力总成 CAN(500 kbit/s)发送 Bremse_* 系列帧,让车速表与里程表继续工作。源文档反复强调:它只恢复仪表信号,不恢复 ABS 制动与稳定控制,且没有真实 ABS 帧时制动系统可能报警或表现异常。下述说明仅限源文档记录的那一台车(2009 Jetta 2.5 / 09G / PQ35)。

    车辆与适用范围

    源文档是一个开源仿真器项目的说明,属于单台车实测 + 标定。它同时列出若干「大概率兼容」的车型,但明确标注这些只是推测,只有 Jetta 2.5 2009 一台被标为已测试。校准默认值是按这一台车标定的。

    项 内容
    车型 VW Jetta 2.5 2009(PQ35 平台)
    年款 / 市场版本 2009;源文档未给出市场版本
    ECU / 改装状态 09G 自动变速箱 TCU、MK60EC1 ABS 模块、PQ35 仪表;ESP32 Dev Module + MCP2515 接入动力总成 CAN
    采集跨度 源文档未给出日志数或帧数;标定基于实车速度与里程比对
    适用范围 仅 Jetta 2.5 2009(09G)被标为已测试;Rabbit/Golf 2006-2009、Audi A3 2006-2009、Passat 2006-2010、Skoda Octavia 2006-2008 均标为「大概率(Likely)」,需 09G TCU + MK60EC1 + 500 kbit/s 动力总成 CAN

    总线与寻址

    源文档明示接入的是动力总成 CAN(Powertrain CAN,500 kbit/s),不是舒适 CAN;MCP2515 需 8 MHz 晶振、移除 120 Ω 终端跳线(除非它是总线末端节点)。OBD 响应地址为 0x7E9,源文档未展开 11 位 / 29 位差异,但所列 ID(0x1A0、0x440 等)均为 11 位经典 CAN 口径。

    项 内容
    物理层 双绞屏蔽线 CAN;动力总成 CAN 高/低;两端各 120 Ω 终端
    链路层 / 比特率 500 kbit/s(源文档明示 VW 动力总成标准)
    寻址方式 11 位 ID(0x1A0、0x4A0、0x5A0、0x3A0、0x7E9、0x440、0x540 等)
    CAN FD 否;源文档按经典 CAN 8 字节处理
    方向 设备向总线发送 Bremse_* 帧;从 0x7E9 / 0x440 / 0x540 接收车速与挡位

    已解码信号

    下表登记源文档明确给出的发送帧与接收帧及其周期与用途。涉及具体信号位域的部分,源文档只给到「16 位原始值在 bits 17-31」「每位 10 位」这类粒度,未逐位展开。

    帧 / 信号 位置(ID / 位域) 解码 / 用途 证据
    车速(主来源) 0x7E9(TCU,09G),PID 0x0D OBD 响应读车速;驱动仪表与里程计算的输入 源文档「RX」表
    挡位 Getriebe_1(wahl) 0x440(TCU) 挡位选择,用于运动状态判定 源文档「RX」表
    接合挡 Getriebe_2 0x540(TCU) 接合挡与档位显示,用于驻车判定 源文档「RX」表
    Bremse_1 轮速 0x1A0,16 位原始值在 bits 17-31 车速表主来源;周期 10 ms 源文档「TX」表
    Bremse_3 轮速(冗余) 0x4A0,同 Bremse_1 部分仪表需要此冗余帧;周期 10 ms 源文档「TX」表
    Bremse_2 中轮转数与里程脉冲 0x5A0,16 位中轮转数 + 时间计数器 + 6 位里程脉冲 驱动里程计数;周期 20 ms;空闲用原始值 127(中性) 源文档「TX」表与 v2.0 安全说明
    Bremse_10 单轮脉冲 0x3A0,VL/VR/HL/HR 各 10 位 供 ABS 模块使用的单轮脉冲;周期 20 ms 源文档「TX」表
    Bremse_5 静止位 0x4A8,10 ms ESP 帧——静止位,中性加速度避免误报 源文档「TX」表
    Bremse_8 纵/横向加速度 0x1AC,20 ms 中性值 127 / 361 / 512,用于抑制错误的 ABS/ESP 报警 源文档「TX」表与 v2.0 说明
    Bremse_6 加速度帧 0x1A8,3 字节,10 ms 中性加速度 源文档「TX」表
    Bremse_11 校验帧 0x5B7,20 ms 中性校验值 源文档「TX」表
    Bremse_4 Haldex 帧(可选) 0x2A0,3 字节,20 ms 仅当开关打开时发送 源文档「TX」表

    读取方法与注意事项

    第一,源文档把「恢复什么、不恢复什么」写得很直白:恢复的是车速表指针、里程表公里数与车辆运动状态;不恢复的是 ABS 制动与稳定控制、实时加速度遥测、OBD2 诊断码,以及(没有 Getriebe 报文时的)挡位显示。因此这台设备不是「修复 ABS」,而是让仪表在没有原厂 ABS 模块时继续工作。

    第二,校准有三个默认值且都针对这一台车:车速表偏置修正系数 1.084、里程脉冲/km 系数 0.2581、车轮周长 1.985 m。源文档给出求值方法,例如车速系数可用「GPS 速度 / 表显速度」反推,里程系数用「OBD 脉冲 vs 实际公里」按比例调整,车轮周长按轮胎规格或实测滚动法获得。调整步长建议 ±0.01。

    第三,安全上与「误报」相关的是中性值:源文档在 v2.0 把 Bremse_2 的静止值设为 127、Bremse_8 的加速度中性值设为 127/361/512,目的就是避免触发错误的 ABS/ESP 警告灯;若灯亮,源文档建议先核对这三个中性值。

    第四,可诊断性:串口 115200 输出循环耗时、滤波前后车速、脉冲计数、TX 失败计数、堆/栈占用等指标;源文档提示循环耗时过大(>12 ms)说明时序有问题,TX 失败非零说明缓冲溢出或总线冲突,栈低于阈值会提示栈溢出风险。

    证据等级与边界

    可视为实车证据的是「已测试」一台车与三组默认标定值,以及 0x1A0/0x4A0/0x5A0 等帧 ID 与周期。属于推测的是「大概率兼容车型」列表,源文档用 Likely 标注,并要求用「OBD 响应地址、DBC 帧 ID 匹配、上路前用监测工具验证」三步自行确认。

    不能外推的地方有三处。第一,兼容性依赖三个前提同时成立:09G TCU、MK60EC1 ABS、500 kbit/s 动力总成 CAN;缺一即不适用。第二,标定值是单台车的,车速修正与里程系数在不同轮胎、不同表头下会不同。第三,源文档明确声明设备不恢复 ABS/ESP,制动行为可能异常,任何「照抄即上路」都超出证据范围。

    关于「安全访问」类问题:源文档未提供任何绕过方法,且不建议尝试;本文只整理公开文档登记的报文与标定,不涉及对车辆安全机制的规避。

    常见问题

    装上这个仿真器后 ABS 会恢复吗?

    不会。源文档明确写它只恢复仪表信号(车速表、里程表、运动状态),不恢复 ABS 制动与稳定控制;没有真实 ABS 帧时制动系统可能报警或行为异常。

    车速是怎么来的?

    设备从 0x7E9(09G TCU 的 OBD 响应,PID 0x0D)读取车速,再据此驱动 Bremse_1(0x1A0)/Bremse_3(0x4A0)的轮速与 Bremse_2(0x5A0)的里程脉冲。

    车速表读数偏高/偏低怎么办?

    调整车速表偏置修正系数(默认 1.084)。源文档给的方法是以恒定 GPS 速度行驶,比较表显值,用「GPS 速度 / 表显速度」推系数,再以 ±0.01 步长微调。

    为什么里程表不动?

    源文档把里程不增归因于里程脉冲/km 系数(默认 0.2581)不对,建议先核实车轮周长,再用实际距离与 OBD 脉冲比对后按比例调整。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/pandolfipedro-pq35-abs/README.md(主来源:车辆、总线、TX/RX 帧表、标定与安全说明)。

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

    更新记录

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

  • Toyota 雷达适配:A/B 槽聚合触发与健康发布的边界

    结论:Toyota 雷达接口不是「每帧到达就出结果」,而是跨轮聚合 A 槽、以最后一个 B 槽作为发布触发的观测链:只有 B 槽到达时才调用 _update() 并清空集合,否则返回 None。这带来三个可复核边界:触发长期缺失时不会生成新 RadarData 或错误事件;can_valid 只在 _update() 时被读取;无解析器时基类每五次调用输出空点,且外层 valid 为真并不代表实体雷达正常。ECU 禁用是独立的通信控制动作,与雷达观测插件必须分权。

    可用性由 DBC 决定,与 ECU 通信控制是两件事

    radarUnavailable 由 DBC 配置决定:TSS2 配置默认含雷达 DBC,而 RADAR_ACC 平台配置会移除雷达总线 DBC。源文档明确,radarUnavailable 表示当前适配没有可解析的雷达 DBC,不等于物理雷达不存在。该路径实例化的 RadarInterface 没有解析器,落入基类定期输出空点的路径。

    与可用性并列、但属另一层的是 ECU 通信控制:RADAR_ACC 且打开实验纵向时设置 DISABLE_RADAR,初始化时向 ECU 发通信控制,控制器周期发送 tester present。源文档强调这是车辆通信与纵向配置动作,不是 RadarInterface 的运行时健康开关,不能在没有车型、线束和安全审查时照搬。

    A/B 槽聚合与发布触发

    _create_radar_can_parser() 按车型选地址组与总线:TSS2 用 A 0x180..0x18f、B 0x190..0x19f;传统用 A 0x210..0x21f、B 0x220..0x22f。A/B 注册 20 Hz,STATUS_MSG 注册 10 Hz,总线为 1。

    解析组 地址范围 名义频率 总线
    TSS2 A 槽 0x180..0x18f 20 Hz 1
    TSS2 B 槽 0x190..0x19f 20 Hz 1
    传统 A 槽 0x210..0x21f 20 Hz 1
    传统 B 槽 0x220..0x22f 20 Hz 1
    STATUS_MSG 源文档未给出具体地址 10 Hz 1

    RadarInterface.update() 把解析器本轮成功解析地址并入跨轮集合;仅当最后一个 B 槽出现时才调用 _update() 并清空集合,否则返回 None。_update() 查询 can_valid 与状态/预故障,只处理累计集合里的 A 槽,按 VALID、LONG_DIST、NEW_TRACK、valid_cnt、对应 B 槽 SCORE 新建、延续或删除点。

    两处细节值得单独指出:B 的 SCORE 从 vl 当前缓存读,源文档指出它未要求 B 与 A 同周期;VALID 为真时直接满足发布条件,SCORE>50 仅为替代路径。A 槽中 NEW_TRACK 或距离越界会先清 valid_cnt,有效近距测量再加一;NEW_TRACK 新建 trackId,否则保留槽位现有点。

    健康与发布的三个缺口

    缺口 静态表现 结论边界
    B 触发长期缺失 无 B 触发时不发布新消息,也不生成错误事件;历史地址仍在集合里 适配层不会主动汇报该故障
    健康门只在 _update() 读取 can_valid 与 STATUS_MSG 只在生成结果时变成 RadarData.errors 触发丢失时错误来不及成为事件
    无解析器的空点路径 基类每五次调用产生空 RadarData;card 仅非 None 时发布 外层 valid 为 errors 全假,不代表实体雷达正常

    CANParser.update() 只返回本轮成功解析地址集,vl 保留各信号最近值;can_valid 检查注册消息缺失/超时和计数器,并有失效计数门。源文档明确 can_valid 只在 _update() 时被读取。无解析器时,RadarInterfaceBase.update() 每五次调用产生空 RadarData,card 仅在返回非 None 时发布 radarTracks,外层 valid 为 errors 全假。因此空点且外层 valid=True 不是「实体雷达正常」的证明,订阅者还要同时看 CarParams 与数据年龄。

    几何约定与插件重构验收

    几何输出为 dRel=LONG_DIST、yRel=-LAT_DIST、vRel=REL_SPEED。插件移植要锁定坐标约定、单位、测量时刻和传感器安装位姿,不能只复制数值字段。上游 radard 以 modelV2 为轮询源,读取最近的 radarTracks 和车况后发布 radarState;源文档提醒,上游不发布时融合循环仍按模型帧推进,不能把输出频率理解成雷达采样频率。

    插件输出应包含 sensor_id、车型/DBC 版本、采样时戳、扫描周期 ID、A/B 配对依据、点年龄、健康原因码和观测状态,并区分「不适用、被禁用、未收到、CAN 不健康、状态故障、正常空点」。接入 radard 前,用只读回放验证 16 组 A/B 顺序错乱、B 槽丢帧、状态报文丢失、NEW_TRACK 复用、距离 255 门槛、VALID 与低 SCORE 组合以及总线超时。

    源文档还给出触发缺失时的要求:应由独立 deadline 产生超时健康事件,而不是等待某个 B 地址恢复后才汇报;历史槽位与 SCORE 必须有最大年龄。这与「以最后一个 B 槽作为发布触发」的机制互补,提醒订阅者不能只依赖适配层的自行汇报。

    最后是分权:ECU 禁用/恢复与雷达观测插件分权,属受信任车辆网关能力,不要把诊断写操作授权给普通传感器插件。本篇未运行测试;上述风险是源码条件推论,不是已复现的实车缺陷。

    常见问题

    radarUnavailable 是不是代表车上没有雷达?

    不代表。源文档明确 radarUnavailable 由 DBC 配置决定:RADAR_ACC 平台配置移除了雷达总线 DBC,所以该路径没有可解析的 DBC,这不等于物理雷达不存在。

    为什么雷达偶发不出结果却不报故障?

    因为发布触发是最后一个 B 槽。源文档指出,B 触发长期缺失时不会生成新的 RadarData 或错误事件,历史地址仍在集合里;can_valid 也只在 _update() 时被读取,所以触发丢失时适配层不主动发布故障。

    没有雷达解析器时输出空点且 valid 为真,能认定雷达正常吗?

    不能。无解析器时基类每五次调用产生空 RadarData,card 仅在返回非 None 时发布,外层 valid 为 errors 全假。源文档明确这不能作为实体雷达正常的证明。

    DISABLE_RADAR 是雷达观测的健康开关吗?

    不是。源文档指出它是车辆通信与纵向配置动作:RADAR_ACC 且打开实验纵向时设置,并向 ECU 发通信控制、周期发送 tester present,与 RadarInterface 的运行时健康状态是两件事。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_RADAR_ADAPTER_DEEP_DIVE.md(取用了地址组与名义频率表、A/B 槽聚合触发语义、健康发布缺口与插件重构验收清单)。

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

    更新记录

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

  • 回放三入口:可视化订阅与 CAN 硬件回放的边界完全不同

    结论:openpilot 的「回放」有三个入口,用途完全不同:C++ replay 可执行文件发布历史消息与 VisionIPC 视频并驱动终端 UI;Python ui.py 只订阅数据做调试可视化;而 can_replay.py 会直接向 Panda Jungle 发 CAN 帧,是唯一对硬件有直接副作用的入口。三者中最容易被误用的就是把 --allow 当成 CAN TX 防火墙,或把可视化订阅当成只读安全——can_replay.py 不是只读分析工具。

    本文基于固定源码快照,静态梳理命令行、终端 UI、Python 调试画面与独立的 CAN 硬件回放脚本。仅做静态阅读,未运行任一回放命令、下载数据、连接/重置/刷写硬件或发送 CAN。CAN 报文解析的健康语义见相邻专题。

    三类入口:能力边界必须先分清

    C++ Replay 是开发进程,启动时会把日志中的 CarParams 写入本地 Params,并可切换 ZMQ=1 让其他 UI/PlotJuggler 订阅。--prefix 为实例指定前缀,但仅靠服务过滤或视觉界面并不能隔离同机所有消息、参数和设备资源,必须在独立开发环境核对具体命名空间。

    入口 实现 能力 关键边界
    C++ replay 可执行文件 main.cc 发布历史消息与视频、终端 UI、benchmark 启动改写本地 Params;--cache 最终仍被钳制为至少五段
    Python 可视化 ui.py raylib 窗口、相机画面、模型轨迹、告警曲线 只订阅数据;曲线是调试可视化,不是严格多主题时间对齐采样
    CAN 硬件回放 can_replay.py 直接向 Jungle 发 CAN 帧 对板卡状态有直接副作用,绝非只读分析工具

    parseArgs() 解析 --allow/--block、段缓存数、起点、倍速、--auto、--data_dir、--prefix、视频与 benchmark 标志,参数转换用 atoi/atof;缓存和倍速在 main 中按正数过滤,起点由 Replay::start() 处理。未知路段、无可用片段仍在后续加载失败。

    main() 随后可选创建 OpenpilotPrefix,实例化 Replay,设置缓存与倍速并加载路段:普通模式启动 ConsoleUI,benchmark 模式直接等待并打印时间线。两个边界要记牢:--cache 最终仍由 setSegmentCacheLimit() 钳制为至少五段;benchmark 只是发布吞吐统计,不是控制算法正确性验证。

    终端 UI 与 Python 调试画面

    ConsoleUI::exec() 约 20 Hz 刷新终端:空格暂停、s/m 前后跳、e/d/t/i/w/c 按时间轴跳、+/- 变速、回车输入绝对秒数。这里的 seek 输入会先暂停再恢复,但未检查 scanw 返回值;错误输入会保持初始 choice=0 并尝试 seek。这是 UI 层行为,不等同于引擎 seek 的参数校验。

    函数 功能 边界
    handleKey() 空格暂停、+/- 变速、回车输入绝对秒数 未检查 scanw 返回值,错误输入仍会 seek
    updateStatus() 从 carState/vehicleParameters 展示车速与转向参数 数据来自回放主题,不是实时车辆状态
    updateTimeline() 从 qlog 生成的 Timeline 绘制使能与告警 缺 qlog 时时间轴可不完整

    Python 侧 ui_thread() 创建 raylib 窗口,用 CameraView("camerad", NARROW_ROAD) 读取 VisionIPC,相机画面与消息图层分开获取;SubMaster 订阅车况、规划、控制、雷达、标定、模型、告警等主题。一个明确的窄边界:get_arg_parser() 接受 ip_address 和 --frame-address,但主入口只用 ip_address 设置 ZMQ 并传给 SubMaster,--frame-address 在本文件中没有被传入 CameraView。远端消息可连接不代表远端帧可显示,该参数在当前实现中无效。

    CAN 硬件回放:独立且危险的边界

    can_replay.py 的四个阶段各有副作用。load_route() 读取 carParams 和所有 can 消息转为逐帧 CAN 列表,无入参时使用默认公开路段;脚本没有依据目标车型、总线拓扑或插入设备自动校验安全适配。connect() 持续枚举 Jungle,每个序列号启动独立发送线程——新连接设备会自动进入发送流程。

    阶段 源码行为 安全含义
    载入 load_route() 读 carParams 与全部 can 消息 来源与内容必须固定、审计;不自动校验安全适配
    发现 connect() 枚举 Jungle 并起发送线程 新设备自动进入发送流程,不是只读工具
    设备配置 send_thread() 在 FLASH 存在时调用 flash(),随后 reset()、清缓冲、设 500 kbps、开点火与供电 对板卡状态有直接副作用;绝不能连实车总线运行
    发报 以 DT_CTRL 节拍按记录帧组循环,仅保留 bus 不高于 2 仅过滤总线号不构成安全认证;依赖物理隔离台架

    FLASH 是「存在即触发」,不是解析布尔值。发送循环仅过滤总线号,空日志会在取模位置失败,USB 超时被吞掉,不能把循环存活视作实际发送成功。

    插件化落点与验证顺序

    把三类入口分开:ReplayControl 只管理路线、时间、速率和服务白名单;ReplayVisualization 只订阅数据且不得取得 CAN 发送能力;HardwareCanStimulus 必须是独立、显式启用的台架插件,含设备白名单、物理隔离确认、报文/总线过滤、发送上限、急停和全量审计。

    1. 不能让通用插件注册机制自动发现并启用硬件刺激插件。
    2. 不能把 --allow 当作 CAN TX 防火墙。
    3. 验证先从固定日志与 mock sink 开始,再查 Params/ZMQ/VisionIPC 隔离、CLI 异常输入、UI 缺主题/缺帧、消息时序。
    4. CAN 输出仅在独立 HIL 台架上用目标硬件与外部监测完成。

    当前目录的 test_route.cc 只覆盖路线范围解析;本文没有运行 GUI、benchmark 或 HIL 测试,也未发现针对上述入口分支的同目录测试。

    常见问题

    can_replay.py 是只读分析工具吗?

    不是。connect() 会持续枚举 Jungle,每个序列号启动独立发送线程;send_thread() 在 FLASH 存在时调用 flash(),随后 reset()、清 CAN 缓冲、设 500 kbps、打开点火与供电。它对板卡状态有直接副作用,绝不能在连接实车总线时运行。

    replay 的 –allow 能当 CAN 发送防火墙吗?

    不能。--allow/--block 只是服务过滤;can_replay.py 的发送循环仅按记录帧组循环发报、只保留 bus 不高于 2,仅过滤总线号不构成安全认证,脚本依赖物理隔离的 Jungle 台架。

    为什么 ui.py 的 –frame-address 不生效?

    源码里 get_arg_parser() 接受 ip_address 和 --frame-address,但主入口只用 ip_address 设置 ZMQ 并传给 SubMaster,--frame-address 在本文件中没有被传入 CameraView,所以远端消息可连接不代表远端帧可显示。

    replay 曲线是严格时间对齐采样吗?

    不是。曲线历史仅在 carState 更新时前移,其余主题值写入最后一行,因此它是调试可视化,不是严格的多主题时间对齐采样;终端时间轴缺 qlog 时也会不完整。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/REPLAY_FRONTENDS_CAN_DEEP_DIVE.md(取用了 C++/Python/CAN 三类入口的功能矩阵、终端 UI 边界与硬件回放四阶段副作用)。
    • 项目 02 —— openpilot-research/REPLAY_ENGINE_DEEP_DIVE.md(仅用于确认回放引擎的消息发布与加载边界,未取用其未公开内容)。

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

    更新记录

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

  • 2017 Subaru BRZ 的 CAN 帧阅读笔记:端序、位序号与 WIP 配置

    结论:这台 2017 款 Subaru BRZ 的档案记录的不是一张成品信号表,而是一套「怎么读 CAN 帧」的方法笔记:如何区分 Motorola/大端与 Intel/小端、位序号为什么与端序无关、商业仪表工具里的 offset/length/startbit/bitcount 分别指什么,以及用回放脚本在没有实车时验证解码。主素材明确这是进行中(WIP)的工作,配置里的偏移、缩放与标签尚未逐条与保留的抓包核对;因此本文把它当作方法记录,而不是可直接套用的信号定义。下述结论仅限源文档记录的这一台车。

    车辆与适用范围

    源文档是车主对自己车辆的私有研究记录。按项目的来源说明,车辆是作者的 2017 Subaru BRZ,配置、市场与 ECU 变体未完全说明;仓库没有找到许可或再分发授权,因此属于非公开的研究副本。文档给出的抓包是作者自述的一段「普通短途驾驶」,共 23,451 行数据。

    项 内容
    车型 2017 Subaru BRZ(据仓库说明)
    年款 / 市场版本 2017;源文档未给出配置、市场版本与 ECU 变体
    ECU / 改装状态 取自 OBD 口的主 CAN 广播;作者用某款 OBD-USB 适配器按 500k 波特率读取
    采集跨度 保留一段约 23,451 行数据的短途驾驶日志;来源说明另提到其他抓包未一并保留
    适用范围 仅限这一台 2017 BRZ;配置的偏移、缩放与标签尚未与抓包逐条核对

    总线与寻址

    源文档按「8 字节 / 64 位经典 CAN 帧」讲解,没有涉及 CAN FD。示例帧是 0x141: 84 26 95 27 B1 82 A7 00,作者用它演示如何定位第 43 位。文档还提醒:商业仪表工具展示字节顺序的方式与常见约定不同,要单独留意。

    项 内容
    物理层 双绞线 CAN;作者按 500k 波特率读取(据文档自述)
    链路层 / 比特率 500 kbit/s(文档自述)
    寻址方式 源文档以 11 位示例 ID(如 0x141、0x0d3)讲解,未展开 11 位 / 29 位差异
    端序 Motorola = 大端,Intel = 小端;小端按递增字节地址读,大端按递减字节地址读
    位序号 全帧 64 位序号固定:字节 0 的位 0 是第 0 位,字节 1 的位 0 是第 8 位,依此类推;端序不改变位序号
    CAN FD 源文档未涉及

    已解码信号

    主素材没有给出成品信号表,只给了一个示例帧与若干配置属性。为守住「只抄有证据的条目」这条线,下表登记源文档明确写出的字段与规则,涉及具体缩放/标签的条目一律标注为未逐条核对。

    字段 / 规则 位置 解码 / 说明 证据
    Custom_Engine_Torque 0x141,bitcount=15 自定义输入;示例未给缩放 README 示例配置
    Engine_Engine_Stop 0x141,startbit=15,bitcount=1 1 位,单位 bit README 示例配置
    Wheel_Torque 0x141,offset=2(第 3 个字节) 示例未给长度与缩放 README 示例配置
    转速类目标值 0x141,offset=4,length=6 映射到商业仪表工具的 RPM 输入(targetId 37) README 示例配置
    车速 长度不足 8 字节的帧(示例 0x0d3) 回放补零后读不准,作者说明该信号受补零影响 README「回放」小节
    帧 ID 写法 XML 的 frame id 可为十进制或 0x 前缀十六进制;若外层有 baseId 则最终 ID = baseId + id README「frame id」小节
    值的 name 与 targetId XML 的 value 有 targetId 则写入工具内置输入;否则用 name 新建 ECU-Specific 自定义输入 README「value」小节
    配置规模 WIP 配置 28 个 frame 元素、145 个 value 元素;偏移、缩放、标签未逐条核对 来源说明
    位序号查找法 任意帧 先把每字节转 8 位,再按全帧序号表定位目标位 README「位序号」小节

    读取方法与注意事项

    第一条是端序与位序号要分开理解。源文档反复强调「位的位置不会因为端序改变」:不管大端小端,第 43 位永远是第 5 个字节里从右边数第 4 个位(位 3)。端序只影响你按什么顺序把连续的字节拼成一个多字节数值。混用是这类解码最常见的错误来源。

    第二条是配置属性的含义——startbit 是开始读的位,bitcount 是一次读多少位,offset 是从哪个字节开始(十六进制),length 是连续读几个字节。作者用一款商业 CAN 数据库编辑器做可视化对照来推导这些含义,因为该工具的术语与仪表工具不同。

    第三条是回放验证的坑。源文档说明其回放脚本会把不足 8 字节的帧用零补齐,例如 0x0d3: 00 06 C0 0F 00 00 42 会变成 8 字节。补零等于给多字节字段多加了 16 位,会改变按位计数与端序结果,因此「用回放测车速」这类信号会读不准。作者建议回放时把推送速率设到能产出约 400 帧/秒,以接近实车从 OBD 口 500k 波特率读到的速率。

    证据等级与边界

    属于方法性、可核对的:端序与位序号的对应规则、配置属性含义、帧 ID 与 baseId 的加法规则。属于未验证的:整套 WIP 配置的偏移、缩放与标签——来源说明写明它们「没有被独立地对照保留的抓包检查过」,而且这套配置是从公开的前代 Subaru DBC 改编而来。

    两处不能外推。第一,车辆本身就是单一样本,且配置、市场与 ECU 变体未说明;同型号不同配置不宜套用。第二,回放脚本的补零行为会系统性歪曲短帧信号,任何用回放得到的数值都不能当作这台车的真实解码结果。

    关于「安全访问」类问题:源文档未提供任何绕过方法,且不建议尝试;本文只整理公开文档记录的解码方法,不涉及对车辆安全机制的规避。

    常见问题

    大端和小端只影响读的顺序吗?

    是的。源文档说明位的位置不会因端序改变,改变的只是你按什么顺序把连续字节拼成多字节数值:小端按递增字节地址读,大端按递减字节地址读。

    第 43 位在示例帧里怎么找?

    按源文档的全帧序号表,第 43 位位于第 5 个字节(示例中为 0x82)内从右数第 4 位(位 3),该帧此位为 0。这个方法与端序无关。

    为什么回放测车速不准?

    因为回放脚本把不足 8 字节的帧用零补齐,等于给字段多加 16 位,改变了按位计数与端序结果。源文档明确说车速信号正来自一个不足 8 字节的帧,因此受此影响读不准。

    这份配置里的 ID、缩放能直接拿来用吗?

    不能直接当作已验证结果。来源说明指出这套 WIP 配置的偏移、缩放与标签尚未与保留抓包逐条核对,且改编自公开的前代 Subaru DBC;使用前需自行复核。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/painellope-brz-2017/CAN_Decoding/README.md(主来源:CAN 帧阅读方法、示例帧与配置属性说明)。
    • 项目 01 —— public-can-dbc-datasets/additional/painellope-brz-2017/SOURCE.md(快照范围、配置规模与「未逐条核对」的边界提示)。
    • 项目 01 —— public-can-dbc-datasets/additional/painellope-brz-2017/CAN_Decoding/CAN_Frame_Datalogs/fileIndex.md(保留抓包的用途与回放补零说明)。

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

    更新记录

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

  • Toyota SecOC 边界缺口:密钥在内存、同步不匹配只记日志、计数先于确认

    结论:Toyota 的 SecOC 链路在源码里是三段彼此独立的机制:密钥装载、同步计数器校验与 panda 安全钩子。它们各自都有明确的边界缺口——密钥只以 16 字节形式留在内存中,Params 的 DONT_LOG 标记并不等于加密;同步 MAC 不匹配时源码只写一条 carlog.error(),不停止组帧;三个消息计数在调用 add_mac() 后、返回候选帧前就递增,不等待 sendcan、SPI、panda TX 或 ECU 的接受回执。发布版对这类车型设 dashcamOnly,MCU 侧也不持有车辆认证密钥。以下为固定快照的静态阅读,未获取车辆密钥、未连接 ECU、未发送 CAN。

    能力门与密钥生命周期

    Toyota SecOC 平台把认证要求写进 CarParams,并把安全参数传给 panda。ToyotaSecOCPlatformConfig.init() 设置 TSS2/NO_DSU/SECOC 标志和专用 DBC;CarInterface._get_params() 置 secOcRequired 与 Toyota safety 参数,发布版把这类车型设成 dashcamOnly。Car.__init__() 从缓存文件或 Params 读取键,做长度与十六进制解析后交给 CarState/CarController;其中的 secOcKeyAvailable 仅是本地装载标志。

    具体地,card 可以从设备本地缓存文件中的 SecOCKey 导入 32 个字符到 Params,再用 bytes.fromhex() 解成 16 字节。正确长度只能证明数据格式,secOcKeyAvailable=True 并不证明它匹配车辆;若 Params 里是非十六进制文本,bytes.fromhex() 在该分支没有局部异常处理,初始化可能直接失败。密钥在 Params 里注册为 DONT_LOG,这只约束常规日志取值,不是存储加密、进程隔离或密钥来源认证。

    层 载体 能证明什么 / 不能证明什么
    能力门 CarParams.secOcRequired + dashcamOnly 声明该车型需要 SecOC;发布版因此进入被动模式,安全配置被改为 NO_OUTPUT。
    密钥装载 设备本地缓存文件中的 SecOCKey → Params → 16 字节内存 长度与格式可校验;不证明匹配车辆,也不是加密存储。
    日志标记 SecOCKey 注册为 DONT_LOG 只约束常规日志取值,不等于进程隔离或来源认证。

    同步与认证:MAC 不匹配只记日志

    SECOC_SYNCHRONIZATION 在 DBC 中是 8 字节消息,含 Trip/Reset 计数和 Authenticator。CarState 每轮复制解析器缓存的当前值,未在此处对同步 MAC 或样本年龄作校验。控制器看到 Reset 与上次不同时,把 LKA、LTA2、ACC2 三个计数清零,再计算期望的同步 MAC。

    关键边界在于:不匹配时只有 carlog.error(),没有在该分支停止组帧或撤销控制资格。另有一个初始化细节——首次本地 Reset 初值为零,若同步消息也为零,本轮不会触发这次校验。解析器总线健康属于另一层,控制器在这里没有逐同步帧的年龄门。

    签名输出:计数先于链路确认递增

    add_mac() 用地址、控制载荷前四字节以及 Trip/Reset/消息计数构造 CMAC 输入,截断后与两组低位标记一起放进 8 字节 CAN 数据;不同命令流各有递增计数。CarController.update() 在 Reset 变化时归零三种本地计数,并分别签 LKA、LTA2、ACC2。

    递增时机是核心问题:计数在调用 add_mac() 之后、返回候选 CAN 帧之前增加,不等待 sendcan、SPI、panda TX hook 或 ECU 的接受回执。因此应用层的计数是「本地尝试序号」,不是「车辆已执行序号」;断流、重启、Reset 切换及报文丢失时的同步策略需要另行验证。

    环节 源码可见做法 缺口
    同步帧解析 CarState.update() 复制解析器缓存 未在此处校验 MAC 或样本年龄。
    同步 MAC 校验 Reset 变化时清零三计数并算期望值 不匹配只 carlog.error(),不停组帧。
    Reset 初值 首次本地 Reset 为 0 同步消息也为 0 时不触发本轮校验。
    命令计数 add_mac() 后立即递增 不等待 sendcan/SPI/panda/ECU 回执。

    panda safety 与覆盖范围

    Toyota safety 的 SecOC TX 白名单包含相应的 LKA/LTA2/ACC2 报文,继续约束消息地址、总线、长度、力矩/角度及纵向输出;例如 SecOC LTA2 的非零执行字段在当前钩子中被禁止。toyota_secoc 参数只有在 ALLOW_DEBUG 编译时才从安全参数开启,不能假定所有固件构建都允许相同模式。

    更重要的是责任边界:MCU 侧没有车辆 SecOC 密钥,也不在此代码中校验 AES-CMAC;认证通过与否由车辆 ECU 决定,安全钩子只负责本地发送约束。相邻测试里,通用车型 TX 回放会跳过 SecOC(需要真实键),panda safety 单测会检查 SecOC 地址与限幅,但不验证 ECU 的密码学接受——白名单与限幅通过并不证明车辆会接受签名帧。

    自制硬件与插件重构

    把车辆认证能力放在受信任、受限的签名服务中,而不是通用车型插件或日志进程:签名服务只对已授权的车型、命令与当前有效同步状态处理候选帧,记录键版本而不泄露键值;CAN 执行仍需独立的 ECU 安全限幅网关。输入契约至少应包含同步帧来源、解析器有效位、接收时间、Trip/Reset 代号和认证结果;MAC 失败、缺帧、过期或密钥不匹配都应进入明确的不可执行状态,不能只写日志。

    离线验收要覆盖:未配置键、非法十六进制键、错误键、同步 MAC 不匹配、Reset 为零或跳变、丢帧、重复或过期同步,以及三条命令流计数的重启行为;再在无车台架验证安全钩子与总线发送结果。在没有车辆密钥或 ECU 反馈时,只能确认本地编码与限幅,不应宣称 SecOC 车型已受支持或已可安全上路。

    常见问题

    SecOCKey 注册为 DONT_LOG 就等于密钥被加密了吗?

    不是。DONT_LOG 只约束常规日志取值,它不代表存储加密、进程隔离或密钥来源认证。密钥最终以 16 字节形式留在 CarState/CarController 内存中,正确长度也只证明数据格式,不证明匹配车辆。

    同步 MAC 不匹配会阻止发送控制帧吗?

    不会。源码在不匹配分支里只有一条 carlog.error(),没有停止组帧或撤销控制资格。此外首次本地 Reset 初值为零,若同步消息也为零,本轮根本不会触发这次校验。

    LKA/LTA2/ACC2 的计数是「车辆已执行」的序号吗?

    不是。计数在调用 add_mac() 后、返回候选 CAN 帧前就递增,不等待 sendcan、SPI、panda TX hook 或 ECU 回执,因此它只是本地尝试序号,不是车辆已执行的序号。

    panda safety 通过就能说明 SecOC 车型可用吗?

    不能。panda 只约束消息地址、总线、长度与力矩/角度/纵向限幅;MCU 不持有车辆密钥、也不校验 AES-CMAC。车型回放测试因无密钥会跳过 SecOC TX 用例,白名单与限幅通过并不证明车辆会接受签名帧。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_SECOC_KEY_FRESHNESS_SAFETY_BOUNDARY_DEEP_DIVE.md(取用了能力门与密钥生命周期、同步与认证边界、add_mac() 计数时机、panda safety 覆盖范围与插件重构建议)。

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

    更新记录

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

  • 桌面还是手机:CAN 数据记录工具的四个能力层级

    结论:桌面与手机的 CAN 数据记录工具并非同一品类,而是覆盖四个能力层级:CAN 物理 / 帧层、OBD 服务 / PID 层、厂商增强诊断层、维修决策层。桌面端多出 USB、串口与 Windows 平台上的 J2534 入口,手机端则受限于 BLE / Wi-Fi / 经典蓝牙,二者都不天然支持工程级总线分析。理解这条分层,就能解释为什么「支持 CAN」不等于「能诊断所有 ECU」,也能解释重卡诊断为何要单独看待。

    桌面与手机的入口差异

    公开资料显示,桌面诊断软件与手机应用在物理接口上并不对等。桌面端通常覆盖更完整的接口集合,手机端的连接方式则相对收敛:

    维度 桌面端(PC) 移动端(手机)
    操作系统 Windows 10 / 11、macOS 较新版本 iOS 与 Android
    接口形态 USB、串口、经典蓝牙、BLE、Wi-Fi BLE、Wi-Fi、MFi,Android 另有经典蓝牙
    专业总线入口 Windows 另支持 J2534 兼容设备 通常不提供
    典型场景 离线回放、报告与大屏分析 随车实时读数与一次诊断会话

    两个边界需要说清楚:其一,桌面端对 J2534 的支持通常限定在 Windows,不能外推到 macOS;其二,移动端一般不提供 USB 入口。因此「桌面能力更全」只在特定接口与平台组合下成立,跨平台购买时还需逐项核对授权是否分开。

    四个能力层级:帧、服务、增强、决策

    抛开平台,工具的能力可以按抽象层次排成四级:

    层级 数据表示 主要工作
    CAN 物理 / 帧层 总线、ID、时间戳、字节 采集、过滤、解码规则研究
    OBD 服务 / PID 层 服务号、PID、DTC、物理量 通用诊断与实时监测
    厂商增强诊断层 ECU、私有服务、车型包 多模块诊断、适配与保养
    维修决策层 故障解释、报告、配件 / 流程 判断下一步行动

    这个分层解释了为什么单靠通用 OBD2 适配器与故障码表,无法自然长成工程级 CAN 工具或维修厂诊断平台。原始 CAN 层先保留时间戳与原始帧,再用 DBC 或人工分析建立语义;OBD 服务层则围绕服务号与 PID 的请求和物理量换算。两者处于不同抽象层,不能把「支持 CAN」视为「已能诊断所有 ECU」。

    需要区分的是,原始帧类工具的定位是工程级分析与仿真,而不是给车主解释故障码;它们围绕时间戳、帧 ID、总线与载荷组织数据,用 DBC 把帧转成信号只是其中一步。选择时应先明确目标是「复盘一段总线」还是「读一次故障码」,两者对应的工具形态并不一样。

    原始 CAN 与诊断之外:数据可离线复盘

    桌面端的另一项结构差异是离线可复盘。公开资料中的开源 CAN 分析工具支持从多种日志格式(如 CSV、candump、Vector、PCAN)导入导出,围绕时间戳、帧 ID、总线、方向、长度与载荷组织帧,并借助 DBC 将帧 ID / 位段转成可解释信号。这类工具的定位是工程级总线分析与仿真,而不是给车主解释故障码。

    与之相对,一些桌面 OBD 工具的核心仍是「设备随附的诊断软件」定位:故障码、实时 PID、Mode 05 / 06 / 09、日志回放与 CSV。二者的差别在于:前者以原始帧为中心,后者以服务与物理量为中心。

    重卡与商用车是独立品类

    公开资料强调,重卡 / 商用车诊断的协议、故障语义与售后场景与轻型车不同,不应把轻型车排放诊断能力直接推到重卡。重卡类工具通常依赖专用蓝牙接口,面向 DPF 再生、降额等场景,并可能提供双向命令;另有相邻的维修资料类产品,提供故障码、接线图与维修资料,属于诊断之后的知识层,并不等同于直接采集车辆数据。

    对选型者而言,这意味着:如果目标车辆是商用车,通用 OBD App 的能力清单参考价值有限,需要单独核对协议与售后链路。从能力层级看,重卡工具的重心通常落在「厂商增强诊断层」与「维修决策层」,依赖专用接口而非通用适配器,其数据入口与售后链路都与轻型车不同。

    常见问题

    桌面端一定比手机端能力更强吗?

    不能一概而论。桌面端在 USB、串口与 Windows 的 J2534 入口上更完整,适合离线回放与大屏分析;但 J2534 通常限 Windows,且桌面与移动授权常需分别购买。要按具体接口与平台组合核对。

    「支持 CAN」就等于能诊断所有 ECU 吗?

    不等于。原始 CAN 层只保留时间戳与原始帧,需要 DBC 或人工分析才能建立语义;OBD 服务层则只覆盖标准服务与 PID。能否读到某个 ECU,取决于车型协议、总线拓扑与适配器能力。

    重卡诊断能用轻型车 OBD 工具替代吗?

    不建议。重卡的协议、故障语义与售后场景与轻型车不同,公开资料明确不应把轻型车排放诊断能力直接推到重卡,通常需要专用接口与面向 DPF、降额等场景的功能。

    桌面工具的离线回放有什么价值?

    它可以围绕时间戳、帧 ID、总线与载荷复盘一段采集,并用 DBC 把原始帧转成可解释信号,是对比多份日志、验证解码规则的重要手段,也是移动端一次会话不擅长的场景。

    延伸阅读

    参考资料

    • 项目 01 —— car-scanner-research/桌面与原始CAN.md(取用桌面与移动接口差异、四个能力层级、原始 CAN 分析定位与重卡品类边界;未引用任何逆向材料)。
    • 项目 01 —— car-scanner-research/逐产品拆解.md(取用移动端接口集合口径,用于对比桌面端)。

    说明:本文仅取用公开资料对桌面与移动诊断工具的能力分层与接口口径,未安装任何安装包、未连接总线、未进行通信抓包,也未核验各商品宣称的接口兼容与平台支持。文中所有层级、接口与边界均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

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

  • 日产 Leaf ZE1:0x1DA 与 0x1D4 的 CRC 同多项式、两种算法

    结论:在一份以日产 Leaf ZE1 命名的 CAN 数据库与配套研究文档里,0x1DA 与 0x1D4 两个帧使用同一个 CRC 多项式 0x85(MSB-first),但算法细节不同:0x1DA 校验时把帧 ID 字节 0xDA 拼进输入并输出异或 0xBF;0x1D4 生成校验时不拼帧 ID、也不做输出异或,只对 b0 至 b6 求 CRC。第三帧 0x11A 则根本没有 CRC 字节,b7 是多路复用(mux)载荷。需要强调:源文档自己的来源说明写明这些 CRC 结论属于「上游声明、未在本归档独立核验」,且该车型的精确年款、配置与固件均未确认。

    本文整理自该研究文档与一份 ZE1 命名的 DBC 快照。文中所有结论的边界,都以下文「证据等级与边界」一节为准,不做拔高。

    车辆与适用范围

    素材包含两部分:一份以 Leaf ZE1 命名的 DBC(含 48 条消息、257 条信号行),以及作者围绕 0x1DA、0x1D4 的 CRC 处理所写的研究文档。文档称 CRC 结论曾用 4 帧已知良好的参考帧校验,但那 4 帧来自第三方 VCU 样机与日产逆变器的采集,并非本归档内独立复核。

    项 内容
    车型 日产 Leaf(DBC 以 ZE1 命名,即 Leaf-CAN_ZE1.dbc)
    年款 / 市场版本 源文档未确认;精确年款、配置与固件 applicability 均未建立
    ECU / 改装状态 涉及逆变器状态帧与扭矩请求帧;文档语境为第三方 VCU 搭配日产逆变器的样机
    采集跨度 CRC 结论基于文档所述 4 帧参考帧;未给出完整日志规模
    适用范围 仅限该 DBC 快照与文档所声明的帧;不得外推至其他年款或固件

    总线与寻址

    本文素材没有给出该车的物理层速率或 11 位 / 29 位寻址结论,也没有 CAN FD 的说明。文档讨论的是帧级 CRC 与字段布局,工作对象是 0x1DA、0x1D4、0x11A 三个 8 字节帧。下表只列文档明确涉及的内容,其余标注为源文档未给出。

    项 内容
    物理层速率 源文档未给出
    寻址 源文档未给出 11 位 / 29 位结论
    CAN FD 源文档未提及
    帧长 所涉三个帧均为 8 字节载荷
    校验字段位置 0x1DA 与 0x1D4 的 CRC 在 b7;0x11A 无 CRC,b7 为 mux 载荷

    已解码信号

    下表汇总文档给出的 CRC 参数、帧结构与 DBC 片段中的字段。凡未标注独立复核的,均沿用「上游声明」边界。位宽写法如 23|12 表示起始位 23、宽 12 位;@0- 表示 Motorola 字节序、有符号。

    信号 位置(ID / 位域) 解码 证据
    CRC_1D4(发送校验) 0x1D4 b7(DBC 56|8) poly 0x85、init 0x00、无输出异或、输入为 b0 至 b6(不拼帧 ID) 上游声明,未独立核验
    0x1DA 线上校验 0x1DA b7 poly 0x85、init 0x00、输出异或 0xBF、输入为 [0xDA, b0..b6] 上游声明;按文档所述对 4 帧参考帧吻合
    时钟选择 clock 0x1DA b6 低 2 位 clock = b6 与 0x03 上游声明
    HCM_CLOCK 0x1D4 38|2 2 位计数,对应 b4 滚动(见下) DBC 片段
    MotorAmpTorqueRequest 0x1D4 23|12 @0- 比例 0.25,范围 0 至 1024 Nm DBC 片段
    ChargeStatus 0x1D4 48|8 MODEMASK 取值 DBC 片段
    StatusOfHighVoltagePowerSupply 0x1D4 34|1 1 位状态 DBC 片段
    Relay_Plus_Output_Status 0x1D4 46|1 1 位状态 DBC 片段
    JoystickGearPosition 0x11A 4|4 4 位 DBC 片段
    CarOnOffStatus 0x11A 13|3 3 位 DBC 片段
    Multiplexor M(mux) 0x11A 48|8(b6) 选择器,逐帧 0、1、2、3 循环 DBC 片段与文档
    HeartbeatVCM 0x11A 24|8(b3) 取值在 85 与 170 之间(文档记 b1 应为 0x40) DBC 片段
    ECOselected 0x11A 12|1 1 位 DBC 片段
    0x11A 的 mux 载荷 0x11A b7 mux0 至 3 对应 0x6B、0xEE、0xE4、0x61 文档表

    读取方法与注意事项

    接收侧校验。对 0x1DA,文档的做法是:用 [0xDA, b0..b6] 求 poly 0x85、init 0x00、xorOut 0xBF 的结果,与收到的 b7 比较,不等即判为坏帧;文档还给出一种运行时策略——连续坏帧达到 10 次则关闭 CAN 回退。

    发送侧构造(文档语境)。0x1D4 每 10 毫秒发送一次:b0、b1 为静态 0x6E,b2、b3 为 0x00,b4 是滚动计数器,b5 为静态充电状态 0x44,b6 为静态 0x01,b7 填入按上文规则算出的 CRC。文档强调 b4 的计数器必须按 0x87 → 0xC7 → 0x07 → 0x47 循环,且 0x11A 的 b1 必须是 0x40,否则逆变器会持续拒帧。

    第三帧无 CRC。0x11A 是每 10 毫秒的心跳:b0 至 b5 为静态字节,b6 逐帧循环 0、1、2、3 作 mux 选择器,b7 随 mux 取对应值,没有校验字节。文档把 b7 明确称为「启动 / mux 载荷数据」,并指出它「不是 CRC 字节」。

    操作提示。以上帧属于车辆逆变器通信;任何在真实总线上发送或改写这些帧的操作都会影响实车,风险自负。本文只转述源文档的算法描述,不构成操作指引;源文档未提供安全访问绕过方法,也不建议尝试。

    证据等级与边界

    第一层边界来自来源说明本身:该归档明确写着,DBC 与其中若干信号「解析器兼容性与信号准确性需要独立复核」,且文中标注了诸如 SG_: 这样的畸形语法与形如 4294967256 这类不合理的无符号物理下限;CRC 结论是上游声明,未在本归档独立验证;精确车型年款、配置与固件 applicability 未确认。许可方面,检查的快照中也没有发现通用仓库许可证,仅作为私有离线研究副本保留。

    第二层边界来自文档自己的措辞:它把结论表述为「已验证并工作」,但依据的 4 帧参考帧来自第三方样机,不是本归档的实测;文档另记录了三类被否定的旧做法(例如错误的 0x1D29 多项式),不应被当作可用方案。

    因此,本文给出的 CRC 参数、计数器循环与字段布局,只能视为「这份 ZE1 命名 DBC 与这份文档所声明的范围」,不能外推到其他 Leaf 年款、其他固件或其他逆变器组合。需要真值时应以实车采集与独立复核为准。

    常见问题

    0x1DA 和 0x1D4 的 CRC 到底差在哪?

    差在两处:0x1DA 把帧 ID 字节 0xDA 拼进输入、并对结果异或 0xBF;0x1D4 不拼帧 ID、也不做输出异或,只对 b0 至 b6 求 CRC。两者共用同一个 MSB-first 多项式 0x85。

    0x1D4 的 b4 计数器为什么必须按 0x87 → 0xC7 → 0x07 → 0x47 循环?

    这是源文档记录的要求:计数器不按该顺序滚动时,逆变器会拒帧并给出状态「100 000」。文档把「计数器未按 10 毫秒循环」列为导致拒帧的可能原因之一。

    逆变器状态「100 000」和「000 000」分别是什么意思?

    按文档,状态「100 000」表示帧被拒绝,「000 000」表示帧被接受。文档还列出可能导致拒帧的原因,包括 0x1D4 的 CRC 错误、0x1D4 计数器未循环、0x11A 未发送或 mux 未循环,以及 0x11A 的 b1 不是 0x40。

    0x11A 有没有 CRC 字段?

    没有。文档明确说明 0x11A 不含 CRC,其 b7 是随 mux 选择器变化的启动 / 载荷数据,而非常规校验字节。

    这些结论能直接套到别的 Leaf 上吗?

    不能。来源说明写明 CRC 结论为上游声明、未在本归档独立核验,且精确年款、配置与固件 applicability 未确认。任何外推都需要以实车采集和独立复核为前提。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/kristianehr-leaf-ze1/docs/CRC_ALGORITHM_DEFINITIVE.md(本项目车型档案主来源,取用了 0x1DA / 0x1D4 / 0x11A 的 CRC 参数与帧结构)。
    • 项目 01 —— public-can-dbc-datasets/additional/kristianehr-leaf-ze1/docs/NISSAN_LEAF_1DA_CRC.md(取用了 0x1DA 的校验参数与 clock 定义)。
    • 项目 01 —— public-can-dbc-datasets/additional/kristianehr-leaf-ze1/SOURCE.md(取用了适用范围与「未独立核验」等边界说明)。

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

    更新记录

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