Keil开发环境编程时对源程序进行编译链接后都可以成一个可执行文件即hex文件,但是有不完全是一个可执行文件。然后可以通过烧录工具烧写到对应的单片机的flash中,当然也还有其他方法可以进行烧录。大家在编程时是否对生成的hex文件有这样的疑问:
1、 当hex文件的大小大于单片机的flash时烧录工具还是可以把hex文件烧写到flash中呢;
2、 单片机运行的是二进制指令和数据,那么hex文件的内容是否都是二进制数呢;
3、 烧录工具是根据什么把程序指令和数据烧写到flash固定的位置呢。
我们就带着这三个疑问深入学习hex文件,想深入理解hex文件必须从内容入手。查看hex文件的很简单,用文本随便打开一个文件都可以看到hex文件的内容。例如:
:020000040800F2
:1000000080040020690100087101000873010008E4
:1000100000000000000000000000000000000000E0
:100020000000000000000000000000007501000852
:1000300000000000000000007701000879010008BE
``````````
``````````
``````````
:1005E0002001000800000000006CDC020000000098
:1005F00000000000010203040607080900000000D3
:04000005080000C12E
:00000001FF
上面就是一个hex文件内容首尾的一部分数据,从内容中很明显可以看出这不是二进制数据。Hex文件是用ASCII来表示二进制的数值,十六进制数组成的指令或者数据,每一行就是一个hex记录。由于单片机执行的只能是二进制指令和数据,而hex文件是十六进制数,所以烧录器的工作必然有一个进制转换机制。具体机制怎么实现暂时可以不管,知道是烧录器处理的就行了。从这里可以找出第二问题的答案。
hex文件的每一行数据记录都是以行为单位,每行从“:”(0x3a)开始,这从文件内容可以看出。以回车键结束(0x0d,0x0a),每行以换行结束。每行的数据都是由两个字符表示一个16进制字节,例如第一行,:020000040800F2中的“02”表示数为0x02,“F2”就表示为0xF2。如果数据位地址时,地址高位在前低位在后。
以上面内容的第二行数据为例,进行详细解析:
:1000000080040020690100087101000873010008E4
1、“:”表示一行的开始;
2、第1、2个字符1和0,即“0x10”表示本行包含的数据长度为16个;
3、第3、4、5、6个字符,固定这4位表示地址,即“0000”表示数据存储的起始地址,表示在0x0000地址开始存放本行包含的16个数据。
4、第7、8个字符,固定这2位表示本行包含数据数据的类型,即“00”表示本行包含的数据为实际烧写的数据。而数据的类型有如下几种:
“00”表示实际数据记录
“01”表示文件结束记录
“02”表示扩展段地址记录
“04”表示扩展线性地址记录
5、由前两个字符“10”可知本行的数据长度位16个字节,所有往后的32个字符就是本行包含的数据,每两个字符表示一个字节数据,总共有16个字节数据。跟最前两个字符决定的长度一致。但是这个数据的长度不是固定的,例如最后一行00000001FF,这行包含的数据长度0,没有数据。
6、最后两个字符为本行的校验码。
通过上面的几点分析可以总结出hex文件的每一行的格式:
<0x3a>[数据长度1Byte][数据地址2Byte][数据类型1Byte][数据nByte]
[验证码1Byte]<0x0d><0x0a>
校验的算法:
计算从(0x3a)以后的所有各字节的和模256的余。即各字节二进制算术和,不计超过256的溢出值,然后用0x100减去这个算数累加和,得出的值就是此行校验码。举一个简单的例子,如第一行020000040800F2
0x02+0x00+0x00+0x00+0x04+0x08+0x00 = 0x0E
0x100 – 0x0E = 0xF2.