Intel HEX 文件每行以:开头,含字节数、地址、记录类型、数据和校验和;地址可16/32位,校验和为所有字段字节和的8位补码;仅类型00为有效数据,需处理04扩展地址,用substr切片解析,建议稀疏存储。

Intel HEX 文件的结构到底长什么样
Intel HEX 不是文本协议,而是带校验的 ASCII 编码二进制数据表示法。每一行以 : 开头,后面紧接固定字段:字节数、地址、记录类型、数据、校验和。比如 :10010000214601360121470136007EFE09D2190140 这一行里,10 是数据长度(16 字节),0100 是地址(0x0100),00 是数据记录类型,最后两个字节 40 是校验和。
关键点在于:地址是 16 位或 32 位,取决于是否出现 04(扩展线性地址)或 05(开始线性地址)记录;校验和不是 CRC,而是所有字节(不含起始冒号和自身)取反加 1 后的低 8 位——但实际只需累加所有字节再取低 8 位的补码(即 ~(sum & 0xFF) & 0xFF)。
用 C++ 逐行解析并提取有效数据块
别用正则匹配整行,直接按字符位置切片更稳。每行至少 11 个字符(:020000040000FA 是最短的有效扩展地址行),先跳过空格和换行,再检查首字符是否为 :。
- 用
std::string::substr()提取字段:第 1–2 字符转为字节数(len),第 3–6 为地址(注意高低位顺序),第 7–8 为记录类型 - 记录类型为
00才是真实数据;01是文件结束;04要更新当前 32 位基地址(取其后 4 字符左移 16 位) - 数据段从第 9 位开始,每 2 字符一组,用
std::stoi(x, nullptr, 16)转为uint8_t - 校验和在末尾 2 字符,必须与前面所有字节(含 len/addr/type/data)的累加和校验一致,否则整行丢弃
地址重叠、空洞与写入缓冲区的处理逻辑
HEX 文件常有不连续地址(例如只烧录 Flash 的某几段),不能假设地址递增。解析时应把每段 00 记录视为独立内存块,存成 {base_addr, std::vector 结构。
常见坑:
- 没处理
04记录就直接拼地址,导致高位全零(如 0x00010000 变成 0x00000100) - 多个记录写入同一地址范围,后写覆盖前写——除非你明确需要“最后定义优先”,否则应检测重叠并报错
- 申请缓冲区时按最大地址 + 数据长度分配,但嵌入式场景往往只关心非零区域,建议用
std::map稀疏存储,避免浪费内存
如何验证解析结果是否正确
最简单的办法是把解析出的数据重新打包成 HEX 行,再用开源工具(如 srec_cat 或 objcopy -I ihex -O binary)转成 bin 对比 SHA256。但更实用的是运行时校验:
- 对每个
00记录,手动重算校验和并与原值比对,不等就立刻std::cerr - 解析完所有行后,遍历所有数据块,检查是否有未闭合的
01(文件结束标记缺失),或出现非法记录类型(如06) - 如果目标是固件烧录,务必确认最高地址块是否包含复位向量(ARM 是 0x00000004 处的初始 SP 值),否则解析没错,但芯片根本跑不起来
地址计算和校验和逻辑最容易手滑写错,建议这两处单独抽成函数并加单元测试,哪怕只测 3 行典型样本(标准数据行、扩展地址行、文件结束行)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










