简介:MatrixCreat V1.10 是一款面向汽车总线开发与测试人员的轻量转换工具,主要解决 DBC、LDF 与 Excel 之间的批量互转需求。内置可联网自动更新机制,用户无需深入配置细节,运行 exe 即可完成转换,适合快速处理 CAN/LIN 通信矩阵文件的工程师使用。压缩包共 7 个文件,约 2.83MB,包含主程序 MatrixCreat.exe,以及 DbcDemo.dbc、LinDemo.ldf、DbcDemo.h、LinDemo.h 等示例文件与两个演示用 xlsx,可帮助上手并验证转换效果。目前已有 4378 人学习下载,工具由作者持续维护,旧版本不再更新,是当前推荐使用的稳定版本。对需要频繁维护 DBC/LDF 与 Excel 同步的开发者而言,这份工具包能明显减少手工改表耗时,附带的样例也能快速熟悉转换规则。
1. DBC/LDF 与 Excel 互转:总线工程师为什么绕不开矩阵化
做整车网络开发的人,几乎每天都要面对 DBC 文件。它是 CAN 总线协议的标准描述文件——纯文本格式,里面装着报文 ID、信号起始位、字节序、缩放因子、偏移量、单位、值定义等全套参数;LDF 则是 LIN 总线的对应描述,结构相似但细节差异不少。可 DBC 直接打开就是满屏的 BO_、SG_、VAL_,想核对一条信号的位置、改一个偏移量,光靠眼睛盯文本效率极低。Excel 恰好互补:矩阵评审、公式校验、批量修改都顺手。MatrixCreat 这类转换工具就是把这两条路接起来:DBC 转 Excel、Excel 转 DBC、LDF 转 Excel、Excel 转 LDF,四条链路一次打通。不管你是整车网络工程师、ECU 测试还是总线仿真开发,把 DBC/LDF 转成 Excel 评审改完再转回去,早已是标准工作流。本文就按“格式原理 → 实操步骤 → 参数说明 → 踩坑记录 → 验证技巧”的顺序,把这套互转流程讲透。
2. 转换前先看懂载体:DBC 和 LDF 里到底存了什么
2.1 DBC 核心对象:报文行、信号行、值定义和属性扩展
在把 DBC 转成 Excel 之前,得先看懂 DBC 文件的骨架。一份完整的 DBC 文件通常包含版本(VERSION)、标准节点段(NS_)、位时序(BS_:)、节点列表(BU_:)、报文(BO_)、信号(SG_)、值描述(VAL_),有的还带注释(CM_)和属性定义(BA_DEF_ / BA_)。转换到 Excel 时,真正会落到表格里的主要是报文和信号两类对象:
VERSION "" NS_ : NS_DESC_ CM_ BA_DEF_ BA_ VAL_ BO_TX_BU_ SG_MUL_VAL_ BS_: BU_: Engine ECU Gateway BO_ 100 EngineData: 8 Engine SG_ EngineSpeed : 8|16@1- (0.25,0) [0|8000] "rpm" ECU SG_ EngineTemp : 24|8@1+ (1,-40) [-40|215] "degC" ECU VAL_ 100 EngineSpeed 0 "Error" 8000 "Max" ;这是一段经过精简但结构完整的 DBC 片段,逐行拆开看:
BU_: Engine ECU Gateway声明了三个网络节点:Engine、ECU、Gateway。Excel 的节点 Sheet 就用这一行生成。BO_ 100 EngineData: 8 Engine是一条报文:ID 为 100(十进制),报文名 EngineData,数据长度 8 字节,发送节点是 Engine。- 信号行是转换的核心。
SG_ EngineSpeed : 8|16@1- (0.25,0) [0|8000] "rpm" ECU拆开看:信号名 EngineSpeed,起始位 8,长度 16 位,@1 表示 Motorola 字节序(大端),减号表示有符号。缩放因子 0.25,偏移量 0,物理量程 0 到 8000,单位 rpm,接收节点 ECU。 SG_ EngineTemp : 24|8@1+ (1,-40) [-40|215] "degC" ECU同理,因子为 1,偏移为 -40,8 位无符号。VAL_是值描述:原始值 0 对应文本 "Error",8000 对应 "Max"。这一行在很多转换工具里处理得最差,后面避坑章节会单独讲。
此外,DBC 还允许报文信号做多路复用(Multiplexing),典型表现是SG_MUL_M_和SG_MUL_VAL_关键字。复用的意义是让一个报文在不同的复用模式下装载不同信号,DBC 里靠复用指示符区分。转成 Excel 时,如果工具没有保留复用关系,回写出去的 DBC 要么丢失复用信号,要么复用指示符消失,报文结构直接改变。所以拿到带M或m前缀标注的信号时,转换后务必在 Excel 里检查“多路复用”列是否完整。
这里要特别提醒:DBC 里的起始位是“原生位号”,不是你在 Excel 里随手写的 bit0。Motorola 字节序下,起始位指的是信号最高有效位(MSB)所在位置;Intel 字节序下,起始位就是最低有效位(LSB)所在位置。转换工具做的是原样映射,而不是帮你换算,这点新手最容易判错。
2.2 LDF 与 DBC 的三大差异:帧 ID、调度表、节点声明方式
LDF(LIN Description File)的结构和 DBC 并不相同,虽然它也定义信号、帧和节点,但组织方式和语义差别很大。以下是一段简化过的 LDF 示例,重点展示节点、信号、帧三块骨架:
LIN_description_file; LIN_protocol_version = "2.1"; LIN_language_version = "2.1"; Nodes { Master: MasterNode; Slaves: SlaveNode; } Signals { EngineSpeed: 0, 16@1- (0.25, 0) [0|8000] "rpm" SlaveNode; } Frames { EngineData: 0x30, MasterNode, 8 { EngineSpeed, 0; } }LDF 的核心结构包括节点(Nodes)、信号(Signals)、帧(Frames)、调度表(Schedule_Tables)和可选的信号编码段(Signal_encoding)。从转换角度看,有三个差异必须单独处理:
第一,帧 ID 的含义不同。LDF 的帧 ID 是 LIN 帧 ID,取值范围只有 0 到 0x3F,和 CAN 的 11 位 / 29 位 ID 完全是两回事。Excel 里如果用十进制存储,0x30 转出来变成 48,评审时对不上号是常态。所以 LDF 相关转换中 ID 列必须支持十六进制显示,最好保留原始文本格式。
第二,调度表是 LDF 独有的。DBC 没有调度概念,每条报文什么时候发由各自节点的应用层决定;LIN 则必须在调度表里定义帧的发送次序和周期。Excel 转回 LDF 时,如果工具没单独处理调度表,转换结果看起来信号都在,但总线上的帧时序已经乱了,节点实际收不到数据。
第三,节点声明方式不同。DBC 的 BU_ 只是列节点名,不做主从区分。LDF 必须显式声明 Master 和 Slaves,而且一个 LDF 只能有一个主节点。Excel 转 LDF 时,节点 Sheet 必须有一列标注主从角色,否则工具无法生成合法的 Nodes 段。
提示:做 LDF 转 Excel 时,优先选择保留多个 Sheet 的输出格式,调度表单独放一个 Sheet,宁可多一列也不少一段。
2.3 为什么用 Excel 做中间载体,而不是直接改文本
我做过不少矩阵评审,感受最深的一点是:客户和供应商手里未必都装 CANdb++ 这类工具,但 Excel 人人都有。转成 Excel 发过去,对方可以随时打开做批注、按信号名过滤、用条件格式标出超量程项,评审效率比对着文本高一个量级。反过来,Excel 里改完数据,再转回 DBC/LDF 参与编译和仿真,这就形成了完整的闭环。MatrixCreat 这类转换工具的通用做法,是把多个对象拆到不同 Sheet:节点 Sheet、报文 Sheet、信号 Sheet、值描述 Sheet,只要约定好列结构,双向转换就不会丢信息。
另一个实际原因是版本管理。DBC/LDF 是文本文件,多人并行修改时 git 冲突极其难处理;转成 Excel 后,可以按信号维度逐行 review,改完再转回文本提交版本库。虽然流程多了一步,但错误定位时间和沟通成本都明显下降,这在项目后期尤其值当。
3. DBC 转 Excel:列映射、值描述导出与批量处理
3.1 转换流程与对象范围选择
以常见的 DBC 转 Excel 操作为例,流程一般分五步:
- 打开 MatrixCreat,选择 DBC 转 Excel 功能,加载本地 DBC 文件。文件编码默认按 UTF-8 处理,如果 DBC 里中文注释显示乱码,改成 GBK 编码再导入。
- 指定输出 Excel 路径,建议输出到独立目录,避免覆盖源文件。
- 选择转换范围。全量转换适合小文件;文件超过几百条报文、上万条信号时,按网段拆分会更合理,否则生成的 Excel 动辄几十 MB,打开卡顿,Excel 加载项还容易被禁用。
- 选择要导出的扩展信息:值描述(VAL_)、注释(CM_)、属性定义是否包含。
- 执行转换并查看报告,过滤掉无法识别的行。
一个典型配置可以写成这样:
输入: Engine_BCM.dbc 输出: Engine_BCM.xlsx 对象范围: 全部报文/全部信号/全部节点 编码: UTF-8 导出值描述: 是 导出注释: 是 属性定义: 是参数说明:对象范围决定表格行数和 Sheet 数;只改信号属性时可以把值描述和注释关掉,Excel 会少两列,处理起来更快。导出属性定义则适合需要保留 DBC 里自定义属性(比如安全等级、唤醒策略)的场景,不要轻易关。
3.2 列映射:DBC 字段如何落到 Excel 表头
无论工具界面怎么变,DBC 转 Excel 的列映射基本是固定的。下面这张表是这套转换里最核心的对应关系,建议保存下来照着核对:
| DBC 字段 | 信号行示例 | Excel 导出列 | 说明 |
|---|---|---|---|
| 报文 ID | BO_ 100 | Message ID | 默认十进制 |
| 报文名 | EngineData | Message Name | |
| 报文长度 | 8 | Message Length | 单位字节 |
| 发送节点 | Engine | Transmitter | 来自 BO_ 行 |
| 信号名 | EngineSpeed | Signal Name | |
| 起始位 | 8 | Start Bit | 按 DBC 原生位号,不做换算 |
| 信号长度 | 16 | Signal Length | 单位 bit |
| 字节序 | @1 | Byte Order | Motorola 或 Intel |
| 有符号/无符号 | - | Value Type | signed / unsigned |
| 因子 | 0.25 | Factor | 物理量 = 原始值 × Factor + Offset |
| 偏移量 | 0 | Offset | |
| 最小值 | 0 | Min | |
| 最大值 | 8000 | Max | |
| 单位 | "rpm" | Unit | |
| 接收节点 | ECU | Receiver | 多节点用分号分隔 |
有几个细节值得注意:
- Byte Order 列建议导出为文本 "Intel" 或 "Motorola",不要用 0 和 1。Excel 会把 0 当数字,转回 DBC 时再转换一次容易出错,而且 0 到底代表什么含义在不同工具里并不统一。
- Receiver 列如果信号有多个接收节点,导出时保持和 DBC 一致的分号分隔格式,不要换行。
- Factor 和 Offset 两列是数值属性,Excel 里要注意不要被格式化成日期。尤其是 Offset 为 0 时,Excel 有时会自动转换成时间格式,转回 DBC 时数据全变。
- 起始位列只做直出。DBC 里写 8 就导出 8,不要“为了方便阅读”换算成 0。一旦手动换算,回写时方向一变就全错位。
3.3 值描述与注释:导成独立 Sheet 比挤在一个单元格靠谱
值描述和注释是 DBC 转 Excel 最容易出问题的地方。值描述本身是“值到文本”的映射关系,像VAL_ 100 EngineSpeed 0 "Error" 8000 "Max"这种一行里有多个键值对。如果工具只是把整行字符串拼到一个 Excel 单元格里,看起来方便,但回写时解析很脆弱,而且在 Excel 里很难检查某个具体值对应什么含义。
更稳妥的做法,是让工具把值描述拆成独立 Sheet,一行一个码值:
[值描述 Sheet] Message ID | Signal Name | Value | Description 100 | EngineSpeed | 0 | Error 100 | EngineSpeed | 8000 | Max这种结构的好处是显而易见的:可以直接用 Excel 的筛选功能查某个码值,还可以用数据透视表统计哪些信号带有值描述;回写 DBC 时,工具按这个 Sheet 重建 VAL_ 段的键值结构,而不是从逗号分隔的字符串里辛辛苦苦地拆。
注释(CM_)的处理类似。DBC 里的注释可能挂在报文下、信号下、节点下,转成 Excel 时不要简单合并到一个备注列,而是按“对象类型 + 对象名 + 注释内容”三列存放。这样回写时才能精确挂回原位置。
注意:值描述导出的关键判断标准是“是否保留原始值的数字格式”。如果 Excel 单元格里出现日期格式(例如输入 8000 被识别为日期),回写的 VAL_ 就废了,这也是很多导出 DBC 文件的隐藏损坏问题所在。
4. Excel 转 DBC/LDF:模板约定、字节序换算与调度表处理
4.1 Excel 模板的列结构约定
Excel 转 DBC 是上面流程的逆向。这一步对模板格式的要求更严格,因为 DBC 语法本身有一套完整校验:报文 ID 不能重复、信号长度不能超过 64 位、发送节点必须存在于节点列表、接收节点不能为空。Excel 里随便填,回写自然报错。
在没有现成模板的情况下,我一般会按下面的列结构建表:
| Excel 列 | 是否必需 | 填写约定 |
|---|---|---|
| Message ID | 是 | 十进制或带 0x 的十六进制 |
| Message Name | 是 | 不能包含空格 |
| Message Length | 是 | 0 到 8,CAN FD 可到 64 |
| Transmitter | 是 | 必须存在于节点 Sheet |
| Signal Name | 是 | 同一报文内不能重复 |
| Start Bit | 是 | DBC 原生位号 |
| Signal Length | 是 | 1 到 64 |
| Byte Order | 是 | Intel 或 Motorola |
| Value Type | 建议 | signed / unsigned |
| Factor | 建议 | 默认 1 |
| Offset | 建议 | 默认 0 |
| Min / Max | 可选 | 物理范围 |
| Unit | 可选 | |
| Receiver | 是 | 至少填一个 |
写成 Excel 时,有几个约定要提前统一:
- Message ID 整列建议设为整数格式,不要用文本。文本列里的数字一旦带前导空格或不可见字符,回写 DBC 时解析失败,表现是“Excel 转出的 DBC 打开报错”。
- 一个报文包含多个信号时,在 Excel 里是重复报文信息、每个信号占一行,而不是把信号写进同一个单元格。
- Signal Name 不区分大小写,但建议保持统一风格,回写后做矩阵比对时可读性好很多。
4.2 字节序与起始位:Excel 转 DBC 最容易错的两个参数
字节序和起始位是 Excel 转 DBC 的分水岭,错一个整个信号的值解析都会翻车。在 DBC 规范里,位编号是按字节从 0 到 7 排列的,下面这张表是 8 字节 CAN 报文里前两个字节的位号:
| 字节 | 位 7 | 位 6 | 位 5 | 位 4 | 位 3 | 位 2 | 位 1 | 位 0 |
|---|---|---|---|---|---|---|---|---|
| Byte 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Byte 1 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
Intel 字节序下,信号起始位就是 LSB 的位置。举例,一个 16 位信号占 Byte0 和 Byte1,起始位就是 0,长度 16,字节序选 Intel,对应的 DBC 片段是0|16@0。
Motorola 字节序下,起始位是 MSB 的位置,而且是按“高位在左”的编号方式。同样占 Byte0 和 Byte1 的 16 位信号,起始位是 7,长度 16,字节序选 Motorola,DBC 片段是7|16@1。
很多人在 Excel 里填写起始位时有个误区:觉得 Motorola 就是从字节起始位置算,填 8 或者 0。但 DBC 解析器认的是 7,不是 8。Excel 转 DBC 之前,建议做一个简单校验列:对 Motorola 格式的信号,起始位通常是奇数;Intel 格式的信号,起始位一般是 0 或 8 的倍数。这个规律虽然不绝对,但能过滤掉大部分低级错误。
4.3 Excel 转 LDF 的特殊处理:节点主从、调度表和编码段
Excel 转 LDF 比转 DBC 多出两块内容:节点主从声明和调度表。
节点 Sheet 需要额外两列:Node Type(Master/Slave)和 Node Capability。LDF 里 Master 节点是总线调度的发起者,Slaves 是被调度方,一个 LDF 文件只能有一个 Master。Excel 转 LDF 时,如果 Node Type 列出现多个 Master,工具应当报错:LDF 规范限制只有一个主节点,总线调度也必须由主节点统一发起。
调度表在 Excel 里建议这样组织:一张独立的 Schedule Sheet,列分别是 Frame Name、发送顺序号、周期时间。回写时,工具按这张表生成 LDF 的 Schedule_Tables 段。如果没有这张 Sheet,转出的 LDF 虽然语法合法,但缺少调度表,网段无法按既定时序发送帧。
信号编码段也是 LDF 与 DBC 的差异点。DBC 的 VAL_ 只做值到文本的映射,而 LDF 的 Signal_encoding 允许定义物理值范围的编码规则,并且可以附加数据格式。Excel 转 LDF 时,建议把编码信息放到值描述 Sheet 的扩展列里,至少保留编码名和类型,否则 LIN 信号的值语义会丢失。
5. 避坑记录:DBC/LDF 与 Excel 互转中的真实翻车现场
5.1 Excel 转出的 DBC 打开就报错,提示文件格式无效
现象:Excel 转 DBC 过程没有任何报错,生成的文件用 CANdb++ 打开却提示文件损坏或格式无效。
原因:最常见是 Excel 里 Message ID 或 Signal Length 列被存成了文本,且文本里藏着前导空格、全角字符或不可见换行。DBC 语法解析器按整数读取,遇到非数字字符直接判定文件头不对。另一个常见原因是 Offset 列被 Excel 自动转成了日期格式,回写时把偏移量写成了一串日期序列号。
解决:回写前先做一次数据清洗。把 ID、Length、Start Bit、Factor、Offset 这几列全选,设置单元格格式为“数值”,然后通过“查找替换”去掉空格。实在不放心,可以先转一个小文件测试,等确认格式无误再全量转换。
5.2 Motorola 信号整体偏位,读出来的值完全不对
现象:转换后的 DBC 里,Motorola 字节序信号的值全部错位,比如原来在 Byte2 的信号跑到 Byte3 去了。如果用原始二进制去解析,值对不上。
原因:DBC 的 Motorola 起始位定义是“信号 MSB 所在位号”,不是字节的起始位。很多人从 Excel 转 DBC 时按直觉填了 0 或 8,导致生成的 DBC 里信号起始位与你期望的字节位置错开。
解决:填 Start Bit 时不要自己换算,直接沿用原 DBC 或 LDF 里给的原生位号。如果是新加信号,Motorola 格式下从第 n 个字节开始,起始位 = n × 8 + 7。以 Byte3 为例,起始位是 31,不是 24。常见做法是在 Excel 里加一列公式,自动把字节索引换算成 Motorola 起始位,减少手敲错误。
Motorola 单字节信号: Byte0 -> Start Bit = 7 Byte1 -> Start Bit = 15 Byte3 -> Start Bit = 31 Intel 单字节信号: Byte0 -> Start Bit = 0 Byte1 -> Start Bit = 8 Byte3 -> Start Bit = 24对照着填,大部分偏位问题都能规避。
5.3 LDF 转 Excel 后帧 ID 显示成十进制,评审会上对不上
现象:LDF 里明文写的是0x30,转出的 Excel 里显示 48,客户拿着 LDF 原文件问你:这个帧 ID 不是 0x30 吗?
原因:工具默认把 ID 转成十进制,方便在 Excel 里做筛选排序,但 LIN 工程师习惯看十六进制。
解决:转换前检查工具是否提供“ID 进制”选项,选择保留十六进制输出;如果没有该选项,至少保证回写时能正确识别十进制值。我一般会强制把 ID 列设为文本格式并保留 “0x” 前缀,从根源上避免进制混用。
5.4 值描述回写后被 Excel 的日期格式吃掉
现象:打开转出的 DBC,发现某些信号的 VAL_ 段凭空多出几组日期,或者值描述里的数字变成了 1900 开头的序列值。
原因:值描述 Sheet 中 Value 列被 Excel 自动识别为日期格式,输入 0 或 8000 后显示成锚定日期。回写逻辑如果直接读单元格显示值,就把日期序列号写进了 VAL_ 段。
解决:在导入 Excel 模板时,先把整个值描述 Sheet 的所有列设为“文本”格式,再输入数据。回写后抽查几个带 VAL_ 的信号,确认原始值和文本描述一一对应。
5.5 DBC 文件编码不统一导致中文注释全部乱码
现象:Excel 里看注释正常,转回 DBC 后打开,中文注释变成乱码,甚至文件在 CANdb++ 里直接打不开。
原因:DBC 文件本身是文本格式,但不同工具链保存的编码不同——有的是 ANSI,有的是 UTF-8,还有带 BOM 的 UTF-8。MatrixCreat 默认按 UTF-8 读取,如果原文件是 GBK,注释就会解析失败。
解决:转换前先用编辑器查看文件编码。VS Code 或 Notepad++ 打开 DBC,右下角会显示编码类型,如果是 GBK,先用“转为 UTF-8”处理再导入。转换后检查乱码的最佳时机,是回写 DBC/LDF 之后再用工具打开一次,看注释是否完整。
6. 转换完别急着交付:CAN 工具和脚本双向校验一次
6.1 用 CANdb++ 做三项手工检查
转换之后,尤其是 Excel 回写生成的文件,第一道关永远是工具打开验证。CANdb++ 打开文件不报错只能说明语法成立,不能说明内容正确。我每次都会按三个顺序检查:先看报文数量,避免多出或丢失报文;再看 ID 是否重复,DBC 里两个报文共用一个 ID 会在仿真时出大问题;最后抽检 20% 的信号,看起始位、字节序、因子、偏移量四项是否和原始表一致。
这些检查看起来笨,但很有效。Excel 转 DBC 最常见的问题不是格式,而是手工编辑时某一行拖错了位置,工具没法替你发现。
6.2 用 Python 脚本做数值一致性比对
如果你的 DBC 文件有几百条报文、上千条信号,手工抽查就不够了。我一般用 Python 的 cantools 库加载转换前后的两个 DBC 文件,直接比对全部信号参数:
import cantools db1 = cantools.database.load_file('原始.dbc') db2 = cantools.database.load_file('转换后.dbc') diffs = [] for msg1, msg2 in zip(db1.messages, db2.messages): if msg1.frame_id != msg2.frame_id: diffs.append(f'帧ID差异: {msg1.name} {msg1.frame_id} -> {msg2.frame_id}') for s1, s2 in zip(msg1.signals, msg2.signals): sig_attr = ('start', 'length', 'byte_order', 'scale', 'offset') if tuple(getattr(s1, a) for a in sig_attr) != tuple(getattr(s2, a) for a in sig_attr): diffs.append(f'信号参数差异: {msg1.name}.{s1.name}') if diffs: print('\n'.join(diffs)) else: print('两个 DBC 的信号参数完全一致')说明:这个脚本只做信号级比对,不比对报文注释和值描述,适合验证核心参数有没有在 Excel 往返过程中丢失或变形。更严格的做法是把scale和offset的浮点比较做四舍五入到小数点后四位再比,因为浮点精度可能导致误报。
6.3 我现在的固定流程:改完强制走一遍双向比对
从那以后,我每次改 DBC/LDF 都强制走同一套流程:原始文件先备份;生成 Excel 后先做一次只读检查;改完回写;回写后立即用上面的脚本做一次信号级比对;最后用 CANdb++ 或 LIN 工具做一次打开验证。这套流程看着多一道工序,但实际节省的沟通成本远大于它花费的时间。希望帮到你。
本文还有配套的精品资源,点击获取