找回密码
 注册
搜索
查看: 900|回复: 1

[讨论] Intel HEX文件格式

[复制链接]
发表于 2007-7-27 20:27:47 | 显示全部楼层 |阅读模式
原文地址
http://bbs.netpu.net/viewthread.php?tid=1690

说明:
以前做格式转换的时候翻译的一篇文章。那时候对这些东西了解不够深入,所以翻译的不好。大概3、4年没有接触这方面的信息,所以即便有错误,现在也无法修正了。整理电脑的时候无意中看到,贴出来,但愿不会遭到嘲笑。欢迎批评指正。


问题:
什么是Intel HEX文件格式?

回答:

Intel HEX文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX文件通常用于传输将被存于ROM或者EPROM中的程序和数据。大多数EPROM编程器或模拟器使用Intel HEX文件。

记录格式
Intel HEX由任意数量的十六进制记录组成。每个记录包含5个域,它们按以下格式排列:
:llaaaatt[dd...]cc
每一组字母对应一个不同的域,每一个字母对应一个十六进制编码的数字。每一个域由至少两个十六进制编码数字组成,它们构成一个字节,就像以下描述的那样:
: 每个Intel HEX记录都由冒号开头.
ll 是数据长度域,它代表记录当中数据字节(dd)的数量.
aaaa 是地址域,它代表记录当中数据的起始地址.
tt 是代表HEX记录类型的域,它可能是以下数据当中的一个:
00 – 数据记录
01 – 文件结束记录
02 – 扩展段地址记录
04 – 扩展线性地址记录
dd 是数据域,它代表一个字节的数据.一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域(ll)中指定的数字相符.
cc 是校验和域,它表示这个记录的校验和.校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行以下补足.

数据记录
Intel HEX文件由任意数量以回车换行符结束的数据记录组成.数据记录外观如下:
:10246200464C5549442050524F46494C4500464C33
其中:
10 是这个记录当中数据字节的数量.
2462 是数据将被下载到存储器当中的地址.
00 是记录类型(数据记录)
464C…464C是数据.
33 是这个记录的校验和.

扩展线性地址记录(HEX386)
扩展线性地址记录也叫作32位地址记录或HEX386记录.这些记录包含数据地址的高16位.扩展线性地址记录总是有两个数据字节,外观如下:
:02000004FFFFFC
其中:
02 是这个记录当中数据字节的数量.
0000 是地址域,对于扩展线性地址记录,这个域总是0000.
04 是记录类型 04(扩展线性地址记录)
FFFF 是地址的高16位.
FC 是这个记录的校验和,计算方法如下:
01h + NOT(02h + 00h + 00h + 04h + FFh + FFh).
当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被应用于从Intel HEX文件读取来的随后的记录.线性地址保持有效,直到它被另外一个扩展地址记录所改变.
通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址.
以下的例子演示了这个过程..
来自数据记录地址域的地址                              2462
扩展线性地址记录的数据域                      + FFFF
                                  ------------
绝对存储器地址                               FFFF2462

扩展段地址记录(HEX86)
扩展段地址记录也叫HEX86记录,它包括4-19位数据地址段.扩展段地址记录总是有两个数据字节,外观如下:
:020000021200EA
其中:
02 是记录当中数据字节的数量.
0000 是地址域.对于扩展段地址记录,这个域总是0000.
02 是记录类型 02(扩展段地址记录)
1200 是地址段.
EA 是这个记录的校验和,计算方法如下:
01h + NOT(02h + 00h + 00h + 02h + 12h + 00h).
当一个扩展段地址记录被读取,存储于数据域的扩展段地址被保存,它被应用于从Intel HEX文件读取来的随后的记录.段地址保持有效,直到它被另外一个扩展地址记录所改变.
通过把记录当中的地址域与被移位的来自扩展段地址记录的地址数据相加获得数据记录的绝对存储器地址.
以下的例子演示了这个过程..
来自数据记录地址域的地址                             2462
扩展段地址记录数据域                      +  1200
                                 ---------
绝对存储器地址                    00014462

文件结束(EOF)记录
Intel HEX文件必须以文件结束(EOF)记录结束.这个记录的记录类型域的值必须是01.EOF记录外观总是如下:
:00000001FF
其中:
00 是记录当中数据字节的数量.
0000 是数据被下载到存储器当中的地址.在文件结束记录当中地址是没有意义被忽略的.0000h是典型的地址.
01 是记录类型 01(文件结束记录)
FF 是这个记录的校验和,计算方法如下:
01h + NOT(00h + 00h + 00h + 01h).

Intel HEX文件例子:
下面是一个完整的Intel HEX文件的例子:
:10001300AC12AD13AE10AF1112002F8E0E8F0F2244
:10000300E50B250DF509E50A350CF5081200132259
:03000000020023D8
:0C002300787FE4F6D8FD7581130200031D
:10002F00EFF88DF0A4FFEDC5F0CEA42EFEEC88F016
:04003F00A42EFE22CB
:00000001FF



有高手能根据上面的Intel HEX文件格式编写一个 C 程序,判断这个文件是不是一个正确的Intel HEX文件吗 ??
 楼主| 发表于 2007-7-31 23:01:34 | 显示全部楼层
/*******************************************************
函数: AnalyseHEX()
功能: 分析一条HEX记录(把Intel HEX记录的文本转换成IntelHEX结构)
参数: hex[]是记录的 文本一行内容 ,转换后的结果保存在IntelHEX结构中
返回: 0-转换成功,1-HEX记录文本中有错误
*******************************************************/
char toint(char hex)
{
        if(hex>='0' && hex<='9') return hex&0x0f ; /* 数字去高位 */
        if((hex>='a' && hex<='z') || (hex>='A' && hex<='Z')) return (hex|0x20)-0x57 ;
        return hex ;
}

bool AnalyseHEX(char hex[])
{
    unsigned char i ;
    unsigned char j ;
    unsigned char t ;
    unsigned char n ;
    unsigned char cc ;
    unsigned int x ;
   
        printf("%s,%d\n",hex,strlen(hex));

    if(hex[0]!=':')        return 1 ;                         /*检查冒号*/
    t=(toint(hex[1])<<4)+toint(hex[2]);        /*检查长度*/
    /* if(t>16)        return 1 ; */
    n=2*t+9 ;  /* 字符串总的长度,不包括'\0' ?????????????? */
    if(n!=strlen(hex))        return 1 ;
    IntelHEX.ll=t ; /* 有效数字个数 */
    cc=t ;   /* 对所有值求和以便求补 */
   
    t=(toint(hex[3])<<4)+toint(hex[4]);        /*提取地址*/
    cc+=t ;
    x=(unsigned int)t ;/*提取地址高位*/
    x<<=8 ;            /* 高位加权 */
    t=(toint(hex[5])<<4)+toint(hex[6]);
    cc+=t ;         
    x+=(unsigned int)t ;/*提取地址低位*/
    IntelHEX.aaaa=x ;  /* 地址 */
   
    t=(toint(hex[7])<<4)+toint(hex[8]);        /*提取记录类型*/
    if((t==0)||(t==1)) { /* 非扩展地址 */
        cc+=t ;
        IntelHEX.tt=t ;
    }
    else {
        return 1 ; /* 怎么不允许地址扩展?? */
    }
    /*提取数据*/
    i=9 ; /* 有效数据的开始位置 */
    if(t==0) /* 有效数据时: */
    {
        j=0 ;
        n=IntelHEX.ll ;
        do  {
            t=(toint(hex[i++])<<4);
            t+=toint(hex[i++]);
            cc+=t ;
            IntelHEX.dd[j++]=t ;
        } while(--n!=0);
    }
    /*提取校验和*/
     t=(toint(hex[i++])<<4); t+=toint(hex[i++]); /* 校验和数值 */
    cc+=t ;
    IntelHEX.dd[j++]=t ;
    /*************************************************/
                printf("IntelHEX.dd:%d,%d\n",t,IntelHEX.dd[j-1]); // 为什么不显示??
        //        printf("cc:%d\n",cc);
        /*************************************************/
    /*检查校验*/
    if(cc==0) return 0 ;
    else  return 1 ;
}

看来还是自己顶下,有高手如能提出改进的 方法,非常欢迎讨论![em01]
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2025-1-24 13:09 , Processed in 0.049848 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表