Canmetry
打开工作台

CAN 信号计算器:解码和编码 DBC 信号

粘贴一段报文数据,按 DBC 的写法描述各个信号,就能看到每个信号的原始值、物理值,以及它占用的具体位。改动任意一个数值,报文数据会跟着变。

DBC 信号

字节之间用空格隔开,例如 00 00 40 1F

信号定义

原始值范围 0 到 65535

位布局

76543210
0
1
2
3
4
5
6
7
  • Engine_Speed
  • Coolant_Temp
  • Throttle_Pos
  • Gear
  • 点击某一位可以翻转它。M 和 L 标出信号的两端。

解码结果

信号原始值十六进制物理值单位
Engine_Speed1F40hrpm
Coolant_Temp5Ah°C
Throttle_Pos80h%
Gear5h

CAN 信号计算器怎么用

四步完成,数据不会离开你的浏览器。

  1. 描述信号

    选好字节序和数值类型,再按 DBC 里的写法填入起始位、长度、系数、偏移和单位。

  2. 粘贴报文数据

    以十六进制输入一帧的数据字节。空格、逗号和 0x 前缀都可以,CAN FD 最多 64 字节也支持。

  3. 查看结果

    表格给出每个信号的原始值、十六进制和物理值,位布局显示它们各自占用哪些位。

  4. 编辑并写回

    输入新的原始值或物理值,或者直接点击某一位,报文数据会随之更新。添加更多信号,就能一次看清整条报文。

CAN 信号的数值是怎么算出来的

一帧 CAN 报文里只有字节。信号定义告诉你该取哪些位、按什么顺序取,以及怎样把得到的整数换算成工程值。

  1. 1. 取出位

    起始位、长度和字节序在报文数据里选定一段位。bit 0 是字节 0 的最低位。

  2. 2. 读成原始整数

    选中的位被读成一个整数。有符号信号的最高位是符号位,整数按二进制补码解读。

  3. 3. 换算成物理值

    原始整数乘以系数再加上偏移,得到以该信号单位表示的值。

# 0x1F40, factor 0.25, offset 0
raw = 0x1F40        # 8000
physical = raw * 0.25 + 0  # 2000
# 3000 rpm back to bytes
raw = round((3000 - 0) / 0.25)  # 12000
bytes = 0x2EE0                   # E0 2E, Intel

有符号信号有什么不同

12 位有符号信号的范围是 -2048 到 2047。最高位为 1 时,要从无符号读数里减去 2^12:0xF9C 按无符号是 3996,3996 - 4096 得到 -100。

Intel 与 Motorola 字节序

同一个 DBC 起始位,在两种字节序下含义不同。解码结果不对时,多半就是这两者搞混了。

Intel:起始位是 LSB

位从字节 0 的最低位开始编号,信号向高位生长,一个字节填满后进入下一个字节。即小端。

Motorola:起始位是 MSB

起始位是最高有效位。信号沿着所在字节往 bit 0 方向走,再跳到下一个字节的 bit 7。即大端,在 DBC 里写作 @0。

CAN 信号术语解释

读 DBC 文件和使用 CAN 工具时会遇到的词。

信号(Signal)
打包在一帧里的一个有名字的值,比如发动机转速或车门开关状态。一帧通常带有多个信号。
报文(Message)
DBC 里描述的一帧:一个 ID、一个长度,以及它携带的信号。
CAN ID
帧的标识符,标准帧 11 位,扩展帧 29 位。接收方靠它判断这是哪一条报文。
数据域与 DLC
数据域(payload)是帧里的数据部分。DLC 是它的长度码:经典 CAN 为 0 到 8 字节,CAN FD 最多 64 字节。
起始位(Start bit)
信号从哪一位开始。Intel 的起始位是最低有效位,Motorola 的起始位是最高有效位。
长度(Length)
信号占用的位数,1 到 64。
字节序(Byte order)
Intel(小端,@1)或 Motorola(大端,@0)。它决定跨多个字节的信号怎样拼起来。
原始值(Raw value)
信号各位里存的整数,还没有经过任何换算。
系数与偏移(Factor / Offset)
从原始值到物理值的线性换算:物理值 = 原始值 × 系数 + 偏移。
物理值(Physical value)
换算之后的工程值,带有信号的单位,比如 rpm 或 °C。
有符号与无符号
原始值是否可以为负。有符号信号使用二进制补码。
多路复用(Multiplexing)
有些 DBC 信号只在复用信号取某个值时才有效。本计算器把每个信号都当作始终存在。

DBC 文件里信号是怎么定义的

每个信号对应一行 SG_。从左往右读,就得到计算器需要的全部输入。

BO_ 416 EngineData: 8 ECU
 SG_ Engine_Speed : 16|16@1+ (0.25,0) [0|16383.75] "rpm" Gateway
部分含义
Engine_Speed信号名
16|16起始位 | 位数
@1字节序:1 是 Intel,0 是 Motorola
+数值类型:+ 为无符号,- 为有符号
(0.25,0)系数和偏移
[0|16383.75]物理值的最小值和最大值,仅作说明,不参与计算
"rpm"单位
Gateway接收节点

信号上方的 BO_ 行给出报文 ID 和长度,例如 BO_ 416 EngineData: 8 ECU。DBC 用十进制存 ID,所以 416 就是 0x1A0。

手算三个信号

把它们载入计算器,就能对照着看每一步。

@1+ 16|16 (0.25,0)

00 00 40 1F 00 00 00 00

带系数的转速

Intel,起始位 16,16 位。字节 40 1F 读作 0x1F40,也就是原始值 8000。系数 0.25,结果是 2000。

@0+ 7|12 (0.1,0)

12 34 00 00 00 00 00 00

跨字节的信号

Motorola,起始位 7,12 位。字节 0 整个(12)加上字节 1 的高半字节(3),组成 0x123,即 291。系数 0.1,结果是 29.1。

@1- 0|12 (0.1,0)

9C FF 00 00 00 00 00 00

负数

Intel,起始位 0,12 位,有符号。字节 9C FF 得到 0xF9C,按无符号是 3996。最高位为 1,所以减去 4096 得到 -100,系数 0.1 时就是 -10.0。

解码 CAN 信号常见的错误

几乎所有算错的值,都能追到下面这几条之一。

  • 字节序选错

    Motorola 的起始位指向最高有效位,Intel 的起始位指向最低有效位。把 Motorola 信号当成 Intel 输入,会选中别的位,得到一个看似合理却错误的数。

  • Motorola 的位号按一维算

    Motorola 的位号在每个字节内部编号,而信号按网络顺序跨字节延伸。只给出一维位序号的工具,可能和 DBC 的起始位对不上,请用位布局核对。

  • 忽略符号

    把有符号信号按无符号读,-100 会变成 3996。数值突然跳到量程顶端时,先检查数值类型。

  • 漏掉偏移

    温度常常存成实际值加 40。不加偏移,每个读数都会高出 40 度。

  • 报文数据太短

    用到第 9 个字节的信号没法从 8 字节的数据里读出。请核对 DLC,这条报文可能是 CAN FD 帧。

CAN 信号计算器常见问题

原始值和物理值有什么区别?

原始值是位里存放的整数。物理值等于 原始值 × 系数 + 偏移,是 DBC 对外给出的工程值,比如转速或摄氏度。

为什么算出来的值不对?

最常见的原因是字节序选错了。Motorola 的起始位指向 MSB,Intel 的起始位指向 LSB,同一个数字选中的位并不相同。还要看有没有符号:有符号信号最高位为 1 就是负数。

跨两个字节的信号怎么读?

按 DBC 选字节序(@1 是 Intel,@0 是 Motorola),起始位原样照抄。位布局会显示每个字节用了哪些位,可以确认信号覆盖的字节是不是你预期的。

支持 CAN FD 报文吗?

支持,最多可以粘贴 64 字节。最长 64 位的信号都按精确整数处理,包括超过 2^53、普通 JavaScript 数字会取整的数值。

能从物理值反推出字节吗?

可以。修改物理值,计算器会把最接近的原始值写进报文数据,其他位保持不变。如果数值超出该信号能表示的范围,会取边界值并提示你。

会上传数据吗?

不会。计算都在浏览器里完成,报文数据和信号定义不会离开页面。

支持多路复用的信号吗?

暂时不支持。每个信号都按始终存在来解码。对于多路复用的报文,只填写当前复用值下生效的那些信号。

怎样把物理值换成原始值?

先减去偏移,再除以系数,最后取最接近的整数:原始值 = round((物理值 - 偏移) / 系数)。在表格里修改物理值就是这样算的,并且会把位写进报文数据。

信号最长可以多长?

按 DBC 格式,1 到 64 位。原始值按精确整数处理,所以 64 位信号也不会丢精度。