结论:这份解码计划的证据底是 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 一家的确认缺失,而不是整条总线的结论。
延伸阅读
- Polaris Sportsman 的 J1939 档案:12 个 PGN 与 250 kbit/s —— 同集团另一套 J1939 实现的对照
- Talaria 电摩 CAN 档案:250 kbit/s 的 15 个 ID —— 两轮小总线的另一形态
- KTM TBI mapswitch:31 条 BO_ 里只有 4 条真实帧 —— 如何从抓包里剔除永不出现的定义
- 车载信号为什么会说谎:TTL、源时间与 500 ms 新鲜度阈值 —— 变化流对数据质量的直接影响
- 车型 CAN 数据库
参考资料
- 项目 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 初稿
发表回复