HEX文件格式+DELPHI源码
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
:020000040000FA , 我把它看做 0x02 0x00 0x00 0x04 0x00 0x00 0xFA
第一个 0x02 为数据长度。
紧跟着后面的 0x00 0x00 为地址。
再后面的 0x04 为数据类型,类型共分以下几类:
'00' Data Record '01' End of File Record '02' Extended Segment Address Record '03' Start Segment Address Record '04' Extended Linear Address Record '05' Start Linear Address Record
:1000100018F09FE5805F20B9F0FF1FE518F09FE51D
第一行,是 Extended Linear Address Record,里面的数据,也就是基地址 是 0x0004,第二行是 Data Record,里面的地址值是 0x0000。那么数据 18F09FE518F09FE518F09FE518F09FE5 要写入 FLASH 中的地址为 (0x0004 << 16) | 0x0000,也就是写入 FLASH 的 0x40000 这个地址。同样,第三行的数据 的写入地址为 0x40010。当一个 HEX 文件的数据超过 64k 的时候,文件中就会 出现多个 Extended Linear Address Record。
HEX 文件以行为单位。每行以字符 ‘:’ (0x3a)开头,以回车换行符 0x0d, 0x0a 为 结束。每行开始和结束之间的所有内容,都是以字符形式表现的。例如数据如果是 0x1A ,那么转换到 HEX 格式的行里面就是 0x31 0x41。如果数据是 16bit 的,例如 地址,则先显示高位,后显示底位。例如 0x1234,转换成 HEX 格式文件后变成 0x31 0x32 0x33 0x34,显示出来以后就是 1234。将数据部分内容每 2 个字符看做一 个字节得 HEX 数据,例如:
//将两个字符转化为一个字节量 void CharToByte(char* pChar,BYTE* pByte) {
char h,l; h=pChar[0];//高位 l=pChar[1];//低位 if(l>='0'&&l<='9')
l=l-'0'; else if(l>='a' && l<='f')
//:号表示一行的开始 if (fgetc(myFile) == ':') {
//一行的头两个字符表示该行包含的数据长度 data[0] = fgetc(myFile); data[1] = fgetc(myFile); CharToByte(data,&dataLen); //一行的第、个字符表示数据存储起始地址的高位 data[0] = fgetc(myFile); data[1] = fgetc(myFile);
“:”表示一行的开始。 “:”后的第 1,2 个字符“10”表示本行包含的数据的长度,这里就是 0x10 即 16 个。 第 3,4,5,6 个字符“0000”表示数据存储的起始地址,这里表示从 0x0000 地址开始存储 16 个数据,其中高位地址在前,低位地址在后。 第 7,8 个字符“00”表示数据的类型。该类型总共有以下几种: 00 ----数据记录 01 ----文件结束记录 02 ----扩展段地址记录 04 ----扩展线性地址记录 这里就是 0x00 即为普通数据记录。 自后的 32 个字符就是本行包含的数据,每两个字符表示一个字节数据,总共 有 16 个字节数据跟行首的记录的长度相一致。 最后两个字符表示校验码。 每个 HEX 格式的最后一行都是固定为: :00000001FF
具体程序如下,该程序在 VC2005 下采用控制台项目编译,需要在 release 下 编译,在 debug 模式中会提示一个 dll 文件无法找到,这可能是 VC 自身的错 误。 // hextobin.cpp : 定义控制台应用程序的入口点。 //
#i nclude "stdafx.h" #i nclude <malloc.h> #i nclude <memory.h> typedef unsigned char BYTE;
Intel HEX 文件是记录文本行的 ASCII 文本文件,在 Intel HEX 文件中,每一行是 一个 HEX 记录,由十六进制数组成的机器码或者数据常量。Intel HEX 文件经常 被用于将程序或数据传输存储到 ROM、EPROM,大多数编程器和模拟器使用 Int el HEX 文件。
很多编译器的支持生成 HEX 格式的烧录文件,尤其是 Keil c。但是编程器能够 下载的往往是 BIN 格式,因此 HEX 转 BIN 是每个编程器都必须支持的功能。
然后,接着 0x04 后面的两个 0x00 0x00 就是数据。最后一个 0xFA 是校验码。
HEX 文件的每一行都是这样的格式:
<0x3a> [数据长度 1Byte] [数据地址 2Byte] [数据类型 1Byte]
[数据 nByte] [校验 1Byte]
<0x0d> <0x0a>
在例如:
:1000000018F09FE518F09FE518F09FE518F09FE5C0
++len; fgetc(myFile); } rewind(myFile); //因为是每两个字符表示一个字节,所以最大的数据个数要少于文件字符个数 的一半
outBuf = (BYTE*)malloc(len/2); memset(outBuf,0xff,len/2); while (!feof(myFile)) {
:1000100018F09FE5805F20B9F0FF1FE518F09FE51D 这行中的 0x1D
校验和的算法为:计算从 0x3A 以后(不包括 0x3A)的所有各字节的和模 256 的余。即各字节二进制算术和,不计超过 256 的溢出值,然后用 0x100 减去这个算 数累加和,得出得值就是此行得校验和。
以上的信息其实就足够进行 HEX 转 BIN 格式的程序的编写。首先我们只处理 数据类型为 0x00 及 0x01 的情况。0x02 表示对应的存储地址超过了 64K,由于 我的编程器只针对 64K 以下的单片机,因此在次不处理,0x04 也是如此。
我的编程思路是从文件中一个一个读出字符,根据“:”判断一行的开始,然后 每两个字符转换成一个字节,并解释其对应的意义。然后将数据从该行中剥离出来 保存到缓冲区中,并最终输出到文件中。
printf("不支持扩展段地址记录!"); return 0; } //当数据类型为时,表示本行包含的是扩展线性地址记录 if (dataType == 0x04) { printf("不支持扩展线性地址记录!"); return 0; } } } fclose(myFile); printf("请输入保存的 BIN 格式文件名:"); scanf_s("%s",fileName); if (fopen_s(&myFile,fileName,"w") != 0) { printf("打开文件%s 失败!",fileName); } for (i=0;i<totalLen;i++) { fputc(outBuf[i],myFile); } return 0; }
CharToByte(data,&adressHigh); //一行的第、个字符表示数据存储起始地址的低位 data[0] = fgetc(myFile); data[1] = fgetc(myFile); CharToByte(data,&adressLow); //一行的第、个字符表示数据类型 data[0] = fgetc(myFile); data[1] = fgetc(myFile); CharToByte(data,&dataType); //当数据类型为时,表示本行包含的是普通数据记录 if (dataType == 0x00) {
End of File Record 行是每一个 HEX 文件的最后一行。例如: :00000001FF 这样的一行数据内容是固定的,数据长度为 0,地址为 0。
校验值:每一行的最后一个值为此行数据的校验和。例如:
:1000000018F09FE518F09FE518F09FE518F09FE5C0 这行中的 0xC0
HEX 格式文件以行为单位,每行由“:”(0x3a)开始,以回车键结束(0x0d, 0x0a)。行内的数据都是由两个字符表示一个 16 进制字节,比如”01”就表示数 0 x01;”0a”,就表示 0x0a。对于 16 位的地址,则高位在前低位在后,比如地址 0x010a,在 HEX 格式文件中就表示为字符串”010a”。下面为 HEX 文件中的一 行: :10000000FF0462FF051EFF0A93FF0572FF0A93FFBC
Biblioteka Baidu
按照上面的数据行格式分析如下:
<0x3a> [数据长度 1Byte] [数据地址 2Byte] [数据类型 1Byte]
10 00 00
00
[数据 nByte] [校验 1Byte]
<0x0d> <0x0a>
18F09FE518F09FE518F09FE518F09FE5 C0
每行中的数据并不是一定有的,第二个字节数据长度为 0,那么这行就没 有数据。
for (i=0;i<dataLen;i++) {
data[0] = fgetc(myFile); data[1] = fgetc(myFile); CharToByte(data,&byteData); outBuf[adressHigh*256+adressLow+i] = byteData; } totalLen += dataLen; } //当数据类型为时,表示到了最后一行 if (dataType == 0x01) { printf("文件结束记录!"); } //当数据类型为时,表示本行包含的是扩展段地址记录 if (dataType == 0x02) {
scanf_s("%s",fileName); printf("\n"); if (fopen_s(&myFile,fileName,"r") != 0) {
printf("打开文件%s 失败!",fileName); } //将文件长度计算出来用于申请存储数据的缓冲区 while (!feof(myFile)) {
由于每行标识数据地址的只有 2Byte,所以最大只能到 64K,为了可以保 存高地址的数据,就有了 Extended Linear Address Record。如果这行的数据类 型是 0x04,那么,这行的数据就是随后数据的基地址。例如:
:020000040004F6
:1000000018F09FE518F09FE518F09FE518F09FE5C0
l=l-'a'+0xa; else if(l>='A' && l<='F')
l=l-'A'+0xa;
if(h>='0'&&h<='9') h=h-'0';
else if(h>='a' && h<='f') h=h-'a'+0xa;
else if(h>='A' &&h <='F') h=h-'A'+0xa;
*pByte=(BYTE)h*16+l; } int _tmain(int argc, _TCHAR* argv[]) {
char fileName[100]; char data[2]; BYTE *outBuf; FILE *myFile; int len; int i; BYTE adressHigh; BYTE adressLow; BYTE dataLen; BYTE dataType; BYTE byteData; int totalLen; totalLen = 0; len = 0; adressHigh = 0; adressLow = 0; dataLen = 0; dataType = 0; printf("请输入 HEX 格式文件名:");