3、刷写文件格式:S19/HEX/BIN 文件解析
做 ECU 刷写,第一关就是看懂刷写文件。你拿到的 .s19、.hex 或者 .bin,里面到底存了什么?说白了,就是地址 + 数据 + 校验。我刚开始接触这行时,也对着这些文件发懵,后来被一个校验错误坑过一次,才老老实实把格式吃透。
今天咱们就把这三种格式掰开揉碎,看看它们怎么描述地址、怎么组织数据、校验和又是怎么算的。
3.1 三种格式的定位差异
先给个总览,你心里有个谱:
| 格式 | 存储方式 | 是否含地址 | 可读性 | 典型用途 |
|---|---|---|---|---|
| S19 (SREC) | ASCII 文本 | 是 | 高 | NXP/Infineon 等 MCU 刷写 |
| HEX (Intel HEX) | ASCII 文本 | 是 | 高 | Intel/ARM 架构,通用烧录 |
| BIN | 二进制 | 否 | 低 | Bootloader 直接烧录,固件镜像 |
BIN 文件最简单——它就是内存的原始镜像,从起始地址开始,一个字节挨着一个字节。没有地址信息,没有校验,纯粹的数据流。所以刷 BIN 时,你必须知道它该烧到哪个地址,否则就乱套了。
S19 和 HEX 则自带地址和校验,刷写工具能自动解析。我个人习惯在开发阶段用 S19 或 HEX,量产时才转成 BIN 给产线用。
3.2 S19 格式深度解析
S19 也叫 Motorola S-record,在汽车电子圈用得特别多。每行都以大写字母 S 开头,后面跟一个数字表示记录类型。
先看一个真实例子:
S214A0000102030405060708090A0B0C0D0E0F1A
我来拆解一下:
- S2 — 记录类型。S2 表示 24 位地址(3 字节),这是最常用的类型。
- 14 — 本行数据长度(十六进制),这里是 20 字节。注意:这个长度包括地址 + 数据 + 校验和,但不包括类型和长度本身。
- A00010 — 地址,3 字节,即 0x00A00010。
- 010203...0F — 数据,16 字节。
- 1A — 校验和。
S19 常见的记录类型:
- S0 — 文件头,通常包含文件名或注释。
- S1 — 16 位地址的数据记录。
- S2 — 24 位地址的数据记录(最常用)。
- S3 — 32 位地址的数据记录。
- S5 — 数据记录计数。
- S7/S8/S9 — 结束记录,对应 32/24/16 位起始地址。
我在项目中遇到过一个问题:某个供应商给的 S19 文件用了 S3 记录(32 位地址),但我们的刷写工具只支持 S2。结果刷到一半就报地址越界。后来我加了个格式检测,提前拦截不兼容的文件。
3.3 Intel HEX 格式解析
Intel HEX 以冒号 : 开头,每行结构也很清晰:
:10A000000102030405060708090A0B0C0D0E0F1A
拆解一下:
- 10 — 数据长度,16 字节。
- A000 — 地址,2 字节,即 0xA000。
- 00 — 记录类型。00 表示数据记录。
- 010203...0F — 数据,16 字节。
- 1A — 校验和。
Intel HEX 的记录类型:
| 类型码 | 含义 | 说明 |
|---|---|---|
| 00 | 数据记录 | 普通数据,地址为 16 位 |
| 01 | 文件结束 | 最后一行,无数据 |
| 02 | 扩展段地址 | 指定段地址(很少用) |
| 04 | 扩展线性地址 | 指定高 16 位地址,常用 |
| 05 | 起始地址 | 指定程序入口地址 |
校验和算法:所有字节(包括长度、地址、类型、数据)加起来,取低 8 位,然后取补码(0x100 - 结果)。比如上面那行:0x10 + 0xA0 + 0x00 + 0x00 + 0x01 + ... + 0x0F = 0xE6,0x100 - 0xE6 = 0x1A。
3.4 BIN 格式与地址映射
BIN 文件没有地址信息,所以刷写时必须配合一个起始地址。比如你有一个 256KB 的 BIN 文件,起始地址是 0x08000000,那么文件中的第 0 字节就对应 0x08000000,第 1 字节对应 0x08000001,以此类推。
我曾经犯过一个低级错误:把 BIN 文件烧到了错误的偏移地址,结果 ECU 启动后完全没反应。后来花了半天才定位到是地址偏移搞错了。所以我现在每次刷 BIN 前,都会用 hexdump 工具看一眼文件头,确认内容是否合理。
- S19:每行自带地址,支持 16/24/32 位地址,适合分段刷写。
- HEX:每行自带地址 + 扩展地址机制,适合大地址空间。
- BIN:纯数据,地址由外部指定,适合连续地址空间。
3.5 知识结构图:刷写文件解析流程
下面这张图展示了从拿到刷写文件到最终烧录的核心流程:
3.6 校验和计算实战
校验和是刷写文件的最后一道防线。我见过太多因为校验和错误导致刷写失败、ECU 变砖的案例。下面给出三种格式的校验和计算代码片段,你可以在刷写工具中直接使用。
S19 校验和计算(C 语言):
uint8_t s19_checksum(const uint8_t *line, int len) {
uint8_t sum = 0;
// 从长度字节开始,到数据结束
for (int i = 2; i < len - 2; i += 2) {
uint8_t byte = hex_to_byte(line[i], line[i+1]);
sum += byte;
}
return 0xFF - sum; // 取反
}
Intel HEX 校验和计算(C 语言):
uint8_t hex_checksum(const uint8_t *line, int len) {
uint8_t sum = 0;
// 从长度字节开始,到数据结束
for (int i = 1; i < len - 2; i += 2) {
uint8_t byte = hex_to_byte(line[i], line[i+1]);
sum += byte;
}
return 0x100 - sum; // 补码
}
3.7 避坑指南
最后分享几个我踩过的坑:
- 地址对齐问题: 有些 MCU 要求刷写地址按 4 字节或 8 字节对齐。如果 S19 文件里有非对齐地址,刷写工具要自动填充或报错。
- 空区域处理: S19 和 HEX 文件可能只包含非空区域。刷写时要注意,未覆盖的区域是保持原值还是擦除。我曾经因为没处理空区域,导致旧数据残留,ECU 行为异常。
- 文件编码: S19 和 HEX 是 ASCII 文本,但有些工具会输出带 BOM 的 UTF-8 文件。解析时最好跳过 BOM,否则第一行会解析失败。
- 校验和溢出: 有些工具算校验和时用 8 位加法,有些用 16 位。确保你的算法跟刷写工具一致,否则校验永远过不了。
嗯,格式解析这块就这些。你只要把地址、数据、校验和这三个要素搞清楚,S19、HEX、BIN 在你眼里就是透明的。下次拿到刷写文件,先看一眼格式,再算一遍校验和,心里就有底了。