[C/C++]Hex文件和Bin文件的关系

背景

从学习单片机以来,在Keil下的烧写都是把.hex文件烧写到单片机内部Flash,对于.hex文件的格式和烧写流程都没有深究。直到需要了解IAP(In Application Programming,即脱离JLink等烧写器进行在线升级)的时候,才发现.hex文件不能作为被直接下载的文件格式,只能用.bin文件代替。下面简单说下这两个文件之间的关联。

Hex文件的样子

这里参考了另一篇文章的内容。
Hex文件打开后每一行称为一个“记录(record)”,每行记录按照同样的结构包含了5个域(且每行以冒号开头):
记录的域的结构
每个域的含义
类型域的说明
根据以上图片知道,一个hex文件最后一行中的记录类型应该是’01’、表示文件结束。
为此写了个简单的程序并用VSCode打开生成的hex:
只有简单的几个常量数组
在这里插入图片描述
可以看到最后一行的记录类型域是’01’、表示文件结束。

这里插一句:第一行的记录类型域是’04’,表示“扩展线性地址记录”;倒数第二行的’05’表示“线性地址开始记录”,现在还不懂是什么意思…
在这里插入图片描述

Bin文件的样子

bin文件是最干净、没有地址信息等额外信息的文件,直接就是可以跑在单片机中机器码(包括程序和数据)。从下面可以看到C源码中**“A char string for see how ASCII char stored in hex and bin”**和另外的字符串被直接放在bin文件的最后(左边白色是bin文件的数据、右边是部分对应的ASCII码,其中控制字符和非ASCII码都显示为"."):
对应的bin文件

两个文件大小对比

hex比bin大
这个简单的程序生成的hex比bin大一倍多(3KB vs 1KB)。
因为hex包含很多额外信息(从截图来看,一行记录最多只能包含16字节的有效数据,也就是hex文件要给bin文件中每16字节增加5字节的信息和1字节的冒号…咦?那不至于两倍多?可能还有别的占存储空间的地方?不清楚…)。
编译另外一个程序得到的结果也是如此(22KB vs 8KB):
在这里插入图片描述
对于hex比bin大很多的原因,这篇文章提到(但这个理解是错误的!):
在这里插入图片描述
该作者的意思是“hex文件把C源码中的每个十六进制数的都当做字符串来处理”——但实际并不是如此,下图可以看出我C源码中的int数组,每个int元素都直接存进了hex文件,它们并没有转化为这些数字对应的ASCII码(如’23’对应的ASCII码应该是’32 33’)
int数组
hex文件的实际数据
bin文件的实际数据

什么时候用hex什么时候用bin呢?

还是引用这里的描述

Hex文件和Bin文件的存在价值:
从上面的介绍中,我们发现Hex文件中每行的内容,就像我们发送串口数据的数据帧,并且最后一行还指示出文件结束了。我们得出hex文件的两个优点:

1. 使用ASCII文本保存固件信息,方便查看一些固件内容;
2. 通过文件每行的校验和与最后一行的文件结束标志,在文件的传输与保存过程中能够发现固件是否完整。

Hex文件有更好的可读性,最重要的是hex文件能够保证固件在保存与传输时的完整性。因此hex文件更适用于保存与传输。而Bin文件是纯二进制文件,内部只包含程序编译后的机器码和变量数据。当文件损坏时,我们也无法知道文件已损坏。不过Bin文件作为固件的最终形式,在使用串口下载程序或者远程升级时,是不可替代的。

最后有一个很好的问题:既然hex和bin在内容上相差了一些额外的信息、而且bin的数据才是单片机最终可见的数据,那hex的额外信息什么时候去掉的呢?
答案是:是在使用JLink或者SWD烧录器给烧录代码时。烧录器上的程序把这些信息去除的。那么可以这样说:烧录hex文件仅在有烧录器的情况使用,否则如果是通过串口或普通的通讯接口,则只能使用bin文件。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值