HEX文件


Intel HEX 文件是由一行行符合Intel HEX 文件格式的文本所 構 成的ASCII 文本文件。在Intel HEX 文件中,每一行包含一 個 HEX 記錄 。 這 些 記錄 由 對應 機器 語 言 碼 和/ 或常量 數 據的十六 進 制 編碼數 字 組 成。Intel HEX 文件通常用於 傳輸將 被存於ROM 或者EPROM 中的程序和 數 據。大多 數 EPROM 編 程器或模 擬器使用Intel HEX 文件。

Hex文件是可以燒寫到單片機中,被單片機執行的一種文件格式,生成Hex文件的方式由很多種,可以通過不同的編譯器將C程序或者匯編程序編譯生成hex。

一般Hex文件通過記事本就可以打開。可以發現一般Hex文件的記錄格式如下:

Intel HEX 由任意數量的十六 進 制 記錄組 成。每 個記錄 包含5 個 域, 它們按以下格式排列:

 

每一組字母 對應 一 個 不同的域,每一 個 字母 對應 一 個 十六 進 制 編碼 的 數 字。每一 個 域由至少 兩個 十六 進制 編碼數 字 組 成, 它們構 成一 個 字 節 ,就像以下描述的那 樣:

:(冒號)每個Intel HEX 記錄 都由冒 號開頭 ;
LL 是 數 據 長 度域, 它 代表 記錄當 中 數 據字 節 (dd) 的 數量 ;
aaaa 是地址域, 它代表 記錄當 中 數據的起始地址;
TT是代表HEX 記錄類 型的域 , 它 可能是以下 數 據 當 中的一 個:
    00 – 數 據 記錄(Data Record)
    01 – 文件結 束 記錄(End of FileRecord)
    02 – 擴展段地址 記錄(ExtendedSegment Address Record)

03 – 開始段地址 記錄(Start Segment Address Record)
    04 – 擴展 線 性地址 記錄(Extended Linear Address Record)

05 – 開始線性地址 記錄(Extended Segment Address Record)
dd 是數 據域 , 它 代表一 個 字 節 的 數 據. 一 個記錄 可以有 許 多 數 據字 節 . 記錄當 中 數 據字 節 的 數 量必 須 和數 據 長 度域(ll) 中指定的 數字相符.
cc 是校驗 和域 , 它 表示 這個記錄 的校 驗 和. 校 驗 和的 計 算是通 過將記錄當 中所有十六 進 制 編碼數 字 對 的 值相加, 以256 為 模 進 行以下 補 足.

表示為:“:[1字節長度][2字節地址][1字節記錄類型][n字節數據段][1字節校驗和] ”

 

具體根據記錄類型分析如下:

(1)數據記錄”00”

Intel HEX文件由任意數 量以回車換行符結束的數據記錄組成數據記錄外觀如下:
    :10246200464C5549442050524F46494C4500464C33
其中:10 是這個記錄當中 數 據字 節 的 數量.即0x10 ;
     2462 是數據 將 被下 載 到存 儲 器 當中的地址.即0x2462 ;

00 是記錄類型( 數 據 記錄).即0x00 ;
464C…464C是 數據.分別代表0x46,0x4C... ;
33 是這個記錄的校 驗和即0x33;計算方法如下:256D-(10H+24H+62H+00H+46H+4CH+55H+49H+44H+20H+50H+52H+4FH+46H+49H+4CH+45H+00H+46H+4CH)/100H=33H;

(2)文件結束(EOF)”01”

Intel HEX文件必須以文件結束(EOF) 記錄結束這個記錄的記錄類的值必須是01.EOF 記錄 外 觀總是如下:
   :00000001FF
其中:00 是記錄當中 數 據字 節 的 數量.
   0000 是數據被下載到存儲器當中的地址. 在文件結束記錄當中地址是沒有意義,被忽略的.0000h 是典型的地址;
   01 是記錄類型 01( 文件 結 束 記錄)
   FF 是 這個記錄 的校 驗 和, 計算方法如下: 256D-(00H+00H+00H+01H)=FFH;

(3)擴展線性地址記錄(HEX386) ”04”

由於每行標識數據地址的只有2Byte,所以最大只能到64K,為了可以保存高地址的數據,就有了Extended Linear AddressRecord。如果這行的數據類型是0x04,那么,這行的數據就是隨后數據的基地址。

擴展線性地址記錄也叫作32位地址記錄或HEX386記錄.這些記錄含數據的高16位擴展線性地址記錄總是有兩個數據字節,外觀如下:
    :02000004FFFFFC

其中:02 是這個記錄當中 數 據字 節 的 數量.
0000 是地址域, 對於 擴 展 線 性地址 記錄 , 這個 域 總是0000.
04 是記錄類型 04( 擴 展 線 性地址 記錄)
FFFF 是地址的高16 位.
FC 是這個記錄的校 驗 和, 計算如下: 256D-(02H+00H+00H+04H+FFH+FFH)/100H=FFH;

當一 個擴展 線 性地址記錄被讀 取, 存 儲於數據域的擴展線性地址被保存,它被應於

從 Intel HEX 文件 讀取 來 的 隨 后的 記錄 . 線 性地址保持有效, 到 它 被另外一 個擴址記錄 所改 變。

通 過 把 記錄當 中的地址域 與 被移位的 來 自 擴 展 線 性地址 記錄 的地址 數 據相加

 獲 得 數 據 記錄 的 絕對 存 儲器地址。

以下的例子演示了這個過 程:

:0200000480007A    //數據記錄的絕對存儲器地址高16位為0x8000               

:100000001D000A00000000000000000000000000C9

:100010000000000085F170706F0104005D00BD00FC

第一行,是Extended Linear Address Record,里面的數據,也就是基地址是0x8000,第二行是DataRecord,里面的地址值是0x0000。那么數據1D000A00000000000000000000000000(共16個字節)要寫入FLASH中的地址為 (0x8000<< 16)| 0x0000,也就是寫入FLASH的0x80000000這個地址;第三行的數據寫入地址為0x80000010.當一個HEX文件的數據超過64k的時候,文件中就會出現多個Extended Linear Address Record。

(4)擴展段地址記錄(HEX86)“02“

擴展段地址記錄也叫HEX86 記錄 , 它包括4-19 位數據地址段. 擴展段地址記總是有兩

個數 據字節 , 外觀如下:
:020000021200EA
其中:02 是記錄當中 數 據字 節 的 數量;
0000 是地址域. 對於 擴 展段地址 記錄 , 這個 域 總是0000;
02 是記錄類型 02( 擴 展段地址 記錄);
1200 是地址段;
EA 是這個記錄的校 驗 和;

當一 個擴 展段地址 記錄 被 讀 取, 存 儲 於 數 據域的 擴 展段地址被保存, 它 被 應 用於 從 Intel HEX 文件 讀 取 來的 隨 后的 記錄 . 段地址保持有效, 直到 它 被另外一 個擴 展地址 記錄 所改 變。

通 過 把 記錄當 中的地址域 與 被移位的 來 自 擴 展段地址 記錄 的地址 數 據相加 獲 得 數 據 記錄 的 絕對 存 儲器地址。
    以下的例子演示了這個過 程..
來自 數 據 記錄地址域的地址          2462
擴展段地址 記錄數據域             +  1200
                               ---------
絕對存 儲 器地址                   00014462


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

//追加一段

 

 

int ParseIHexPerLine(const char *buf,const char *path,int line)
{
	unsigned int nbytes=0,addr=0,type=0,i,val,line_chksum;
	unsigned char data[1024];	
	unsigned char cksum;
	const char *s=buf;			
	if(*s!=':') //第一個為冒號
	{  
		fprintf(stderr,"%s:%s: format violation (1)/n",path,line);
		return(1);  
	}
	++s;
	//接下來的8個字節為數據大小、地址等
	if(sscanf(s,"%02x%04x%02x",&nbytes,&addr,&type)!=3)
	{  
		fprintf(stderr,"%s:%s: format violation (2)/n",path,line);
		return(1);  
	}
	s+=8;
	//讀到的類型
	if(type==0) //為數據段
	{
		if(!(nbytes>=0 && nbytes<1024))
		{
			perror("nbyte per line unsupport/n");
			return(-1);
		}
		
		cksum=nbytes+addr+(addr>>8)+type;
		//
		for(i=0; i<nbytes; i++)
		{
			val=0;
			if(sscanf(s,"%02x",&val)!=1)
			{  
				fprintf(stderr,"%s:%s: format violation (3)/n",path,line);
				return(1);
			}
			s+=2;
			data[i]=val;
			cksum+=val;
		}
		//
		line_chksum=0;
		if(sscanf(s,"%02x",&line_chksum)!=1)
		{  
			fprintf(stderr,"%s:%s: format violation (4)/n",path,line);
			return(1);  
		}
		if((cksum+line_chksum)&0xff)
		{  
			fprintf(stderr,"%s:%s: checksum mismatch (%u/%u)/n",
					cksum,line_chksum);  
			return(1);  
		}
		if(WriteRAM(addr,data,nbytes)) 
			return(1);  
	}
	else if(type==1)
	{
		// EOF marker. Oh well, trust it. 
		return(-1);
	}
	else
	{
		fprintf(stderr,"%s:%s: Unknown entry type %d/n",type);
		return(1);
	}
	return(0);
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM