Hex格式文件有兩種,一種是Intel的Intel HEX,另一種是Motorola(摩托羅拉)的SREC(又稱MOT)。
Intel HEX 文件是由一行行符合Intel HEX 文件格式的文本所 構(gòu) 成的ASCII 文本文件。在Intel HEX 文件中,每一行包含一 個(gè) HEX 記錄 。 這 些 記錄 由 對(duì)應(yīng) 機(jī)器 語(yǔ) 言 碼 和/ 或常量 數(shù) 據(jù)的十六 進(jìn) 制 編碼數(shù) 字 組 成。Intel HEX 文件通常用于 傳輸將 被存于ROM 或者EPROM 中的程序和 數(shù) 據(jù)。大多 數(shù) EPROM 編 程器或模 擬器使用Intel HEX 文件。
Hex文件是可以燒寫(xiě)到單片機(jī)中,被單片機(jī)執(zhí)行的一種文件格式,生成Hex文件的方式由很多種,可以通過(guò)不同的編譯器將C程序或者匯編程序編譯生成hex。
一般Hex文件通過(guò)記事本就可以打開(kāi)。可以發(fā)現(xiàn)一般Hex文件的記錄格式如下:
Intel HEX 由任意數(shù)量的十六 進(jìn) 制 記錄組 成。每 個(gè)記錄 包含5 個(gè) 域, 它們按以下格式排列:
每一組字母 對(duì)應(yīng) 一 個(gè) 不同的域,每一 個(gè) 字母 對(duì)應(yīng) 一 個(gè) 十六 進(jìn) 制 編碼 的 數(shù) 字。每一 個(gè) 域由至少 兩個(gè) 十六 進(jìn)制 編碼數(shù) 字 組 成, 它們構(gòu) 成一 個(gè) 字 節(jié) ,就像以下描述的那 樣:
(1):(冒號(hào))每個(gè)Intel HEX 記錄 都由冒 號(hào)開(kāi)頭 ;
(2)LL 是 數(shù) 據(jù) 長(zhǎng) 度域, 它 代表 記錄當(dāng) 中 數(shù) 據(jù)字 節(jié) (dd) 的 數(shù)量 ;
(3)aaaa 是地址域, 它代表 記錄當(dāng) 中 數(shù)據(jù)的起始地址;
(4)TT是代表HEX 記錄類 型的域 , 它 可能是以下 數(shù) 據(jù) 當(dāng) 中的一 個(gè): 00 – 數(shù) 據(jù) 記錄(Data Record) 01 – 文件結(jié) 束 記錄(End of FileRecord) 02 – 擴(kuò)展段地址 記錄(ExtendedSegment Address Record) 03 – 開(kāi)始段地址 記錄(Start Segment Address Record) 04 – 擴(kuò)展 線 性地址 記錄(Extended Linear Address Record) 05 – 開(kāi)始線性地址 記錄(Extended Segment Address Record)
(5)dd 是數(shù) 據(jù)域 , 它 代表一 個(gè) 字 節(jié) 的 數(shù) 據(jù). 一 個(gè)記錄 可以有 許 多 數(shù) 據(jù)字 節(jié) . 記錄當(dāng) 中 數(shù) 據(jù)字 節(jié) 的 數(shù) 量必 須 和數(shù) 據(jù) 長(zhǎng) 度域(ll) 中指定的 數(shù)字相符.
(6)cc 是校驗(yàn) 和域 , 它 表示 這個(gè)記錄 的校 驗(yàn) 和. 校 驗(yàn) 和的 計(jì) 算是通 過(guò)將記錄當(dāng) 中所有十六 進(jìn) 制 編碼數(shù) 字 對(duì) 的 值相加, 以256 為 模 進(jìn) 行以下 補(bǔ) 足.
表示為:“:[1字節(jié)長(zhǎng)度][2字節(jié)地址][1字節(jié)記錄類型][n字節(jié)數(shù)據(jù)段][1字節(jié)校驗(yàn)和] ”
(TT)具體根據(jù)記錄類型分析如下:
(1)數(shù)據(jù)記錄”00”
Intel HEX文件由任意數(shù) 量以回車換行符結(jié)束的數(shù)據(jù)記錄組成數(shù)據(jù)記錄外觀如下: :10246200464C5549442050524F46494C4500464C33 其中:10 是這個(gè)記錄當(dāng)中 數(shù) 據(jù)字 節(jié) 的 數(shù)量.即0x10 ; 2462 是數(shù)據(jù) 將 被下 載 到存 儲(chǔ) 器 當(dāng)中的地址.即0x2462 ;
00 是記錄類型( 數(shù) 據(jù) 記錄).即0x00 ; 464C…464C是 數(shù)據(jù).分別代表0x46,0x4C… ; 33 是這個(gè)記錄的校 驗(yàn)和即0x33;計(jì)算方法如下:256D-(10H+24H+62H+00H+46H+4CH+55H+49H+44H+20H+50H+52H+4FH+46H+49H+4CH+45H+00H+46H+4CH)/100H=33H;
(2)文件結(jié)束(EOF)”01”
Intel HEX文件必須以文件結(jié)束(EOF) 記錄結(jié)束這個(gè)記錄的記錄類的值必須是01.EOF 記錄 外 觀總是如下: :00000001FF 其中:00 是記錄當(dāng)中 數(shù) 據(jù)字 節(jié) 的 數(shù)量. 0000 是數(shù)據(jù)被下載到存儲(chǔ)器當(dāng)中的地址. 在文件結(jié)束記錄當(dāng)中地址是沒(méi)有意義,被忽略的.0000h 是典型的地址; 01 是記錄類型 01( 文件 結(jié) 束 記錄) FF 是 這個(gè)記錄 的校 驗(yàn) 和, 計(jì)算方法如下: 256D-(00H+00H+00H+01H)=FFH;
(3)擴(kuò)展線性地址記錄(HEX386) ”04”
由于每行標(biāo)識(shí)數(shù)據(jù)地址的只有2Byte,所以最大只能到64K,為了可以保存高地址的數(shù)據(jù),就有了Extended Linear AddressRecord。如果這行的數(shù)據(jù)類型是0x04,那么,這行的數(shù)據(jù)就是隨后數(shù)據(jù)的基地址。
擴(kuò)展線性地址記錄也叫作32位地址記錄或HEX386記錄.這些記錄含數(shù)據(jù)的高16位擴(kuò)展線性地址記錄總是有兩個(gè)數(shù)據(jù)字節(jié),外觀如下: :02000004FFFFFC
其中:02 是這個(gè)記錄當(dāng)中 數(shù) 據(jù)字 節(jié) 的 數(shù)量. 0000 是地址域, 對(duì)于 擴(kuò) 展 線 性地址 記錄 , 這個(gè) 域 總是0000. 04 是記錄類型 04( 擴(kuò) 展 線 性地址 記錄) FFFF 是地址的高16 位. FC 是這個(gè)記錄的校 驗(yàn) 和, 計(jì)算如下: 256D-(02H+00H+00H+04H+FFH+FFH)/100H=FCH;
當(dāng)一 個(gè)擴(kuò)展 線 性地址記錄被讀 取, 存 儲(chǔ)于數(shù)據(jù)域的擴(kuò)展線性地址被保存,它被應(yīng)于
從 Intel HEX 文件 讀取 來(lái) 的 隨 后的 記錄 . 線 性地址保持有效, 到 它 被另外一 個(gè)擴(kuò)址記錄 所改 變。
通 過(guò) 把 記錄當(dāng) 中的地址域 與 被移位的 來(lái) 自 擴(kuò) 展 線 性地址 記錄 的地址 數(shù) 據(jù)相加
獲 得 數(shù) 據(jù) 記錄 的 絕對(duì) 存 儲(chǔ)器地址。
以下的例子演示了這個(gè)過(guò) 程:
:0200000480007A //數(shù)據(jù)記錄的絕對(duì)存儲(chǔ)器地址高16位為0x8000
:100000001D000A00000000000000000000000000C9
:100010000000000085F170706F0104005D00BD00FC
第一行,是Extended Linear Address Record,里面的數(shù)據(jù),也就是基地址是0x8000,第二行是DataRecord,里面的地址值是0x0000。那么數(shù)據(jù)1D000A00000000000000000000000000(共16個(gè)字節(jié))要寫(xiě)入FLASH中的地址為 (0x8000<< 16)| 0x0000,也就是寫(xiě)入FLASH的0x80000000這個(gè)地址;第三行的數(shù)據(jù)寫(xiě)入地址為0x80000010.當(dāng)一個(gè)HEX文件的數(shù)據(jù)超過(guò)64k的時(shí)候,文件中就會(huì)出現(xiàn)多個(gè)Extended Linear Address Record。
(4)擴(kuò)展段地址記錄(HEX86)“02“
擴(kuò)展段地址記錄也叫HEX86 記錄 , 它包括4-19 位數(shù)據(jù)地址段. 擴(kuò)展段地址記總是有兩
個(gè)數(shù) 據(jù)字節(jié) , 外觀如下: :020000021200EA 其中:02 是記錄當(dāng)中 數(shù) 據(jù)字 節(jié) 的 數(shù)量; 0000 是地址域. 對(duì)于 擴(kuò) 展段地址 記錄 , 這個(gè) 域 總是0000; 02 是記錄類型 02( 擴(kuò) 展段地址 記錄); 1200 是地址段; EA 是這個(gè)記錄的校 驗(yàn) 和;
當(dāng)一 個(gè)擴(kuò) 展段地址 記錄 被 讀 取, 存 儲(chǔ) 于 數(shù) 據(jù)域的 擴(kuò) 展段地址被保存, 它 被 應(yīng) 用于 從 Intel HEX 文件 讀 取 來(lái)的 隨 后的 記錄 . 段地址保持有效, 直到 它 被另外一 個(gè)擴(kuò) 展地址 記錄 所改 變。
通 過(guò) 把 記錄當(dāng) 中的地址域 與 被移位的 來(lái) 自 擴(kuò) 展段地址 記錄 的地址 數(shù) 據(jù)相加 獲 得 數(shù) 據(jù) 記錄 的 絕對(duì) 存 儲(chǔ)器地址。 以下的例子演示了這個(gè)過(guò) 程… 來(lái)自 數(shù) 據(jù) 記錄地址域的地址 2462 擴(kuò)展段地址 記錄數(shù)據(jù)域 + 1200 --------- 絕對(duì)存 儲(chǔ) 器地址 00014462
Intel HEX 文件例子: 下面是一個(gè) 完整的Intel HEX 文件的例子: :10001300AC12AD13AE10AF1112002F8E0E8F0F2244 :10000300E50B250DF509E50A350CF5081200132259 :03000000020023D8 :0C002300787FE4F6D8FD7581130200031D :10002F00EFF88DF0A4FFEDC5F0CEA42EFEEC88F016 :04003F00A42EFE22CB :00000001FF
SREC SREC全稱Motorola S-record,一種文件格式,由摩托羅拉創(chuàng)建的,該文件使用ASCII HEX文件格式表達(dá)二進(jìn)制信息。這種格式也叫做SRECORD, SREC, S19, S28, S37。通常用于微控制器編程,EPROMs和其他可編程的邏輯器件。在通常的應(yīng)用中,編譯器或匯編器將程序的源代碼(如C語(yǔ)言或匯編語(yǔ)言)轉(zhuǎn)換成機(jī)器代碼,并將其輸出到一個(gè)HEX文件。然后這個(gè)HEX文件被程序員燒寫(xiě)到ROM中,或者轉(zhuǎn)移到目標(biāo)系統(tǒng)用于裝載和執(zhí)行。 //SREC格式
//第一行數(shù)據(jù) S0 0F 0000 636B3631302D6C2E73686578 0C //行數(shù)據(jù) S2 08 010000 FFFFFFFF FA S3 15 08640000 6C0264086C0264086C0264086C026408 16 S5 03 0002 FA S7 05 08640214 78
SREC文件一行為單位,分為5個(gè)部分。分別是記錄類型域、字節(jié)數(shù)域、地址域、數(shù)據(jù)域、校驗(yàn)域。
第一部分類型域是SREC文件的起始標(biāo)志,代表該行的類型,必須已S開(kāi)始,值可以是從S0到S9;
第二部分字節(jié)數(shù)域是每行記錄的長(zhǎng)度,地址域、數(shù)據(jù)域、校驗(yàn)域三個(gè)域的長(zhǎng)度,單位為字節(jié)數(shù)。
第三部分地址域,該域的長(zhǎng)度取決于第一部分類型域。
第四部分?jǐn)?shù)據(jù)域,該自動(dòng)長(zhǎng)度=字節(jié)數(shù)域的值-地址域長(zhǎng)度-1(校驗(yàn)域長(zhǎng)度)
第五部分校驗(yàn)域,該域長(zhǎng)度為1byte(16-bit),校驗(yàn)方法是:除了類型域的值其他十六進(jìn)制值每?jī)蓚€(gè)一組相加結(jié)果末兩位為0xFF。
讀取代碼: QT語(yǔ)言
#include<stdio.h>
#include<stdlib.h>
#include<QDebug>
#include<QString>
#include<QByteArray>
#include<QDebug>
#include<QFile>
#include<QDataStream>static char pq=9; //規(guī)范代碼/****16進(jìn)制的數(shù)據(jù)類型*****/
const QString HexTypeTable[6] =
{"00","01","02","03","04","05",
};/****配套數(shù)據(jù)類型使用的枚舉變量*****/
typedef enum __tagHexType
{RECORD_DATA = 0,RECORD_END_OF_FILE,RECORD_EXTENDED_SEGMENT_ADDRESS,RECORD_START_SEGMENT_ADDRESS,RECORD_EXTENDED_LINEAR_ADDRESS,RECORD_START_LINEAR_ADDRESS,RECORD_HEX_MAX,
}emHexType;typedef enum Boolsymbol
{DATA_Flase = 0,DATA_Ture
}BoolTureFlase;//定義字符串的類型格式
typedef struct StringTypes
{char Firstsymbolis;char StringCrcis;char StringSizeis;char StringResultis;char StringType;//QString BaseAddress;
}StringType;static StringType StringTypeLine={DATA_Ture,DATA_Ture,DATA_Ture,DATA_Ture,RECORD_DATA}; //定義字符串的類型格式/****函數(shù)聲明*********/
QString AnalyseHEX(QByteArray dest);
int mystrlen(const char *StrDest);
int HexToDec(char *src);
QString QStringLeftBit(QString src,int num);
QString QStringToAdd(QString dest,QString src);
StringType FormatHexjudge(QByteArray src);
QString BaseAddjudge(QByteArray src);
void ReadWrite(QString filenameread,QString filenameWrite);/****計(jì)算字符串長(zhǎng)度*****/
int mystrlen(const char *StrDest)
{int i;i=0;while((*StrDest++)!='\0'){i++;}//這個(gè)循環(huán)體意思是從字符串第一個(gè)字符起計(jì)數(shù),只遇到字符串結(jié)束標(biāo)志'\0’才停止計(jì)數(shù)return i;
}/****16進(jìn)制轉(zhuǎn)換10進(jìn)制*****/
int HexToDec(char *src)
{//將src中的無(wú)符號(hào)十六進(jìn)制字符串轉(zhuǎn)為十進(jìn)制數(shù)//如src="001A",則返回26//字符串src需要以'\0'作為結(jié)束標(biāo)志int value=0,srclen=mystrlen(src);int i;for(i=0;i<srclen;i++){if(src[i]<='9'&&src[i]>='0'){value=value*16+(int)(src[i]-'0'); //'0'}else if(src[i]<='f'&&src[i]>='a'){value=value*16+(int)(src[i]-'a'+10);}else{value=value*16+(int)(src[i]-'A'+10);}}return value;//返回轉(zhuǎn)換后的數(shù)值
}/****字符串效驗(yàn)*返回效驗(yàn)的十進(jìn)制數(shù)用來(lái)與字符串后兩位做比較****/
QString AnalyseHEX(QByteArray dest)
{unsigned char i=1;int tempsum=0; //必須初始化,否則亂碼QString stype;QString ZERO="0";QString Date0x100="100";QString result;do{stype = dest.mid(i,2); //轉(zhuǎn)換成10進(jìn)制運(yùn)算后,再轉(zhuǎn)換成十六進(jìn)制printf(" %d",HexToDec(stype.toLatin1().data()));tempsum+=HexToDec(stype.toLatin1().data());i+=2;} while (i<(mystrlen(dest)-2));/***HEX計(jì)算公式(0x100-(16進(jìn)制數(shù)據(jù)和后兩位))再取后兩位=字符串后兩位*****/result=QString::number((HexToDec(Date0x100.toLatin1().data())-HexToDec(QString::number(tempsum,16).right(2).toLatin1().data())),16);if(result.size()<2){int count=2-result.size();//printf("count=2-result.right(2).size()=%d\n",count);while(count-->0){result.insert(0,ZERO);}}//qDebug()<<"result.right(2).toUpper()"<<result.right(2).toUpper();return result.right(2).toUpper();}/***0613*****字符串左移num位*****************/QString QStringLeftBit(QString src,int num) //{QString zero="0";while(num-->0){src.insert(src.size()-2,zero); //末尾位加零src.remove(0,1); //刪除起始位}return src;}/***0613*****字符串以十六進(jìn)制的形式轉(zhuǎn)換成十進(jìn)制相加,然后轉(zhuǎn)換成十六進(jìn)制的字符串形式輸出*****/QString QStringToAdd(QString dest,QString src){QString ResultDate;QString ZERO="0";int num1,num2,ans;int count;bool ok;num1=dest.toInt(&ok,16); //轉(zhuǎn)換成10進(jìn)制num2=src.toInt(&ok,16);ans=num1+num2;ResultDate=QString::number(ans,16);/**判斷結(jié)果字符串與輸入的兩個(gè)字符串的最大差值,用于給結(jié)果字符串補(bǔ)零***/(dest.size()-ResultDate.size()>src.size()-ResultDate.size())?count=dest.size()-ResultDate.size():count=src.size()-ResultDate.size();while(count-->0){ResultDate.insert(0,ZERO);}return ResultDate.toUpper();//十進(jìn)制轉(zhuǎn)換成Qstring的形式輸出 toUpper() //轉(zhuǎn)換成大寫(xiě)字母}/****文件格式類型判斷,有錯(cuò)誤打印,返回值為基地址******/
StringType FormatHexjudge(QByteArray src) //QString *resultBaseAddres
{QByteArray resultString=":00000001FF";static uint32_t count_num=0;count_num++;/******驗(yàn)證一下傳入的數(shù)據(jù)***********/char *pcdata = src.data();//printf("Length of src:%d\n",mystrlen(src)); //打印傳入數(shù)據(jù)大小while(*pcdata){//printf("%c",*pcdata); //打印原始數(shù)據(jù)++pcdata;}//printf("\n");if(src.left(1)!=":"){//不是以":"開(kāi)始StringTypeLine.Firstsymbolis=DATA_Flase;printf("Format FirstSymbol wrong!\n");system("Pause");}else{StringTypeLine.Firstsymbolis=DATA_Ture;}if(strlen(src)<11){//字符串長(zhǎng)度小于11printf("Format length wrong!\n");system("Pause");}else{StringTypeLine.StringSizeis=DATA_Flase;}if(strcmp(src,resultString)==0){//結(jié)束標(biāo)志StringTypeLine.StringResultis=DATA_Ture;printf("End of file\n");}else{StringTypeLine.StringResultis=DATA_Flase;}if(src.right(2)!= AnalyseHEX(src)) //字符效驗(yàn){StringTypeLine.StringCrcis=DATA_Flase; //字符效驗(yàn)失敗printf("\nSerialcount is wrong in Address=%d\n",count_num);printf("XiaoYan_cc:%c%c\n",*src.right(2).data(),*(src.right(2).data()+1));printf("\nXiaoYan_calcu_int:%d\n",AnalyseHEX(src).toInt());printf("XiaoYan_read_int:%d\n",HexToDec(src.right(2).data())); //讀出來(lái)的效驗(yàn)值system("Pause"); //如果效驗(yàn)值錯(cuò)誤,暫停界面}else{StringTypeLine.StringCrcis=DATA_Ture; //字符效驗(yàn)正確//printf("\nFormat Effect Vaild!!!!!\n");while(mystrlen(src)-2>pq) //打印完所有的數(shù)據(jù){QString st = src.mid(pq,2);pq+=2;printf("%c%c ",*st.toLatin1().data(),*(st.toLatin1().data()+1));}}/****判斷數(shù)據(jù)類型****/QString stringtype = src.mid(7,2);//printf("\nstringtype: %c%c\n",*stringtype.toLatin1().data(),*(stringtype.toLatin1().data()+1));if(stringtype==HexTypeTable[RECORD_DATA]){ //00正常數(shù)據(jù)類型StringTypeLine.StringType=RECORD_DATA;QString styadd = src.mid(3,4);/****只是分割字符串****/// printf("styadd:%c%c%c%c\n",*styadd.toLatin1().data(),*(styadd.toLatin1().data()+1),*(styadd.toLatin1().data()+2),*(styadd.toLatin1().data()+3));}else if (stringtype==HexTypeTable[RECORD_END_OF_FILE]){ //01 用來(lái)標(biāo)識(shí)文件結(jié)束StringTypeLine.StringType=RECORD_END_OF_FILE;printf("RECORD_END_OF_FILE\n ");}else if (stringtype==HexTypeTable[RECORD_EXTENDED_LINEAR_ADDRESS]) //TODO:只需要判斷一次{ //04 擴(kuò)展線性地址記錄StringTypeLine.StringType=RECORD_EXTENDED_LINEAR_ADDRESS;printf("RECORD_EXTENDED_LINEAR_ADDRESS \n");QString styadd = src.mid(3,4);QString styaddsub = src.mid(9,4); //字符串拼接styadd.insert(0,styaddsub);//printf("StyaddSub04:%c%c%c%c%c%c%c%c\n",*styadd.toLatin1().data(),*(styadd.toLatin1().data()+1),// *(styadd.toLatin1().data()+2),*(styadd.toLatin1().data()+3),*(styadd.toLatin1().data()+4),*(styadd.toLatin1().data()+5),*(styadd.toLatin1().data()+6),*(styadd.toLatin1().data()+7));//system("Pause");}else if(stringtype==HexTypeTable[RECORD_EXTENDED_SEGMENT_ADDRESS]){ //02 擴(kuò)展段地址記錄StringTypeLine.StringType=RECORD_EXTENDED_SEGMENT_ADDRESS;printf("RECORD_EXTENDED_SEGMENT_ADDRESS\n");}else if(stringtype==HexTypeTable[RECORD_START_LINEAR_ADDRESS]){ //05 開(kāi)始線性地址記錄StringTypeLine.StringType=RECORD_START_LINEAR_ADDRESS;printf("RECORD_START_LINEAR_ADDRESS\n");}else if(stringtype==HexTypeTable[RECORD_START_SEGMENT_ADDRESS]){ //03 開(kāi)始段地址記錄StringTypeLine.StringType=RECORD_START_SEGMENT_ADDRESS;printf("RECORD_START_SEGMENT_ADDRESS\n");system("Pause"); //如果遇到03則暫停,預(yù)留處理03的代碼 (0613/還未遇到)}return StringTypeLine;
}/******判斷基地址**如果數(shù)據(jù)類型為04調(diào)用*******/
QString BaseAddjudge(QByteArray src)
{QString resultBaseAddres;QString stringtype = src.mid(7,2); /****判斷數(shù)據(jù)類型****/if (stringtype==HexTypeTable[RECORD_EXTENDED_LINEAR_ADDRESS]) //TODO:只需要判斷一次RECORD_EXTENDED_LINEAR_ADDRESS{ //04 擴(kuò)展線性地址記錄QString styadd = src.mid(3,4);QString styaddsub = src.mid(9,4); //字符串拼接styadd.insert(0,styaddsub);printf("StyaddSub04:%c%c%c%c%c%c%c%c\n",*styadd.toLatin1().data(),*(styadd.toLatin1().data()+1),*(styadd.toLatin1().data()+2),*(styadd.toLatin1().data()+3),*(styadd.toLatin1().data()+4),*(styadd.toLatin1().data()+5),*(styadd.toLatin1().data()+6),*(styadd.toLatin1().data()+7));return styadd;}if (stringtype==HexTypeTable[RECORD_EXTENDED_SEGMENT_ADDRESS]) //TODO:只需要判斷一次RECORD_EXTENDED_LINEAR_ADDRESS{ //02 擴(kuò)展段地址記錄QString Basezer0 = "0000";QString styaddsub = src.mid(9,4); //字符串拼接Basezer0.insert(4,styaddsub);Basezer0=QStringLeftBit(Basezer0,1);printf("StyaddSub02:%c%c%c%c%c%c%c%c\n",*Basezer0.toLatin1().data(),*(Basezer0.toLatin1().data()+1),*(Basezer0.toLatin1().data()+2),*(Basezer0.toLatin1().data()+3),*(Basezer0.toLatin1().data()+4),*(Basezer0.toLatin1().data()+5),*(Basezer0.toLatin1().data()+6),*(Basezer0.toLatin1().data()+7));return Basezer0; //在02數(shù)據(jù)類型的方式下需要左移一位}return resultBaseAddres;
}/****新字符串拼接*****/
QString FormatTranQARRYbyte(QByteArray src)
{char count=9;char newcount=10;QString ResultDate;static QString resultBaseAddress="00000000"; //static 修飾只初始化一次 //0x08000000QString space=" ";StringTypeLine=FormatHexjudge(src);if(StringTypeLine.StringCrcis==DATA_Ture) //如果效驗(yàn)碼正確{if(StringTypeLine.StringType==RECORD_EXTENDED_LINEAR_ADDRESS) //如果是擴(kuò)展性數(shù)據(jù)類型 04{resultBaseAddress=BaseAddjudge(src); //接收擴(kuò)展地址qDebug()<<"resultBaseAddress"<<resultBaseAddress;}if(StringTypeLine.StringType==RECORD_EXTENDED_SEGMENT_ADDRESS) //如果是段數(shù)據(jù)類型 02{resultBaseAddress=BaseAddjudge(src);qDebug()<<"resultBaseAddress"<<resultBaseAddress;}ResultDate=resultBaseAddress; //第一個(gè)是地址ResultDate=QStringToAdd(ResultDate,src.mid(3,4)); //基地址和絕對(duì)地址相加if(StringTypeLine.Firstsymbolis==DATA_Ture) //如果字符串的第一個(gè)符號(hào)是“:”{ResultDate.insert(8,src.left(1)); //插入符號(hào)ResultDate.insert(9,space);}while(mystrlen(src)-2>count) //打印完所有的數(shù)據(jù){ResultDate.insert(newcount,src.mid(count,2));newcount=newcount+3;ResultDate.insert(newcount,space);count=count+2;}if(StringTypeLine.StringType==RECORD_DATA) //當(dāng)數(shù)據(jù)類型為00的時(shí)候才打印{printf("\n");qDebug()<<"ResultDate "<<ResultDate<<endl<<endl<<endl;}}return ResultDate;
}#if 0
/***按行讀取HEX文件并進(jìn)行處理*****/
void read(QString filename){QFile file(filename);if(!file.open(QFile::ReadOnly | QFile::Text)){qDebug() << " Could not open the file for reading";return;}QTextStream in(&file);while(!in.atEnd()){QString myText = in.readLine();QString str(myText);QByteArray bytes = str.toLatin1(); //Qstring 轉(zhuǎn) QByteArrayqDebug() << bytes;FormatTranQARRYbyte(bytes);printf("\n\n\n");}file.close();}/***按行讀取HEX文件并進(jìn)行處理*****/
void Write(QString filename)
{QFile file(filename);if(!file.open(QFile::WriteOnly | QFile::Text)){qDebug() << " Could not open the file for reading";return;}//QTextStream stream(&file);//stream.seek(file.size());QString resultString=":00000001FF\n";QString EnterResul="\n";QByteArray AER=":10246200464c5549442050524f46494c4500464c33";file.write(FormatTranQARRYbyte(AER).toUtf8());file.write(EnterResul.toUtf8());file.write(resultString.toUtf8());file.close();return;
}
#endif/***按行讀取HEX文件并進(jìn)行處理*****/
void ReadWrite(QString filenameread,QString filenameWrite){QString EnterResul="\n";QFile fileread(filenameread);if(!fileread.open(QFile::ReadOnly | QFile::Text)){qDebug() << " Could not open the file for reading";return;}QFile filewrite(filenameWrite);if(!filewrite.open(QFile::WriteOnly | QFile::Text)){qDebug() << " Could not open the file for reading";return;}QTextStream in(&fileread);while(!in.atEnd()){QString myText = in.readLine();QString str(myText);QByteArray bytes = str.toLatin1(); //Qstring 轉(zhuǎn) QByteArrayqDebug() << bytes;QString ResultText;ResultText=FormatTranQARRYbyte(bytes);if(StringTypeLine.StringType==RECORD_DATA) //只將數(shù)據(jù)類型為 00 的字符串寫(xiě)入{filewrite.write(ResultText.toUtf8()); //寫(xiě)入數(shù)據(jù)filewrite.write(EnterResul.toUtf8()); //寫(xiě)入回車}printf("\n");}fileread.close();filewrite.close();}/**0613生成成功**/
int main()
{QString filename = "C:/Users/Administrator/Desktop/HEX2/VCU_S32K14X.hex";//QString filename = "C:/Users/Administrator/Desktop/HEX2/Projec.hex";QString filewritename = "C:/Users/Administrator/Desktop/HEX2/Pro1.hex";//QByteArray AER=":020000040800F2";// QByteArray AER=":105CC00010831C46234618465DF8044B704708B500";//FormatTranQARRYbyte(AER);ReadWrite(filename,filewritename);}
C#語(yǔ)言 頭文件
#ifndef CHEX_H
#define CHEX_H#include <QFile>const quint8 MIN_HEX_LINE_COUNT_LENGHT = 12;typedef enum __tagHexErrorCode
{HEX_NO_ERROR = 0,HEX_FORMAT_ERROR,HEX_VERIFY_ERROR,HEX_LENGHT_ERROR,HEX_USERPAPR_EEROR,
}EHexErrorCode;typedef enum __tagHexType
{RECORD_DATA = 0,RECORD_END_OF_FILE,RECORD_EXTENDED_SEGMENT_ADDRESS,RECORD_START_SEGMENT_ADDRESS,RECORD_EXTENDED_LINEAR_ADDRESS,RECORD_START_LINEAR_ADDRESS,RECORD_HEX_MAX,
}emHexType;typedef struct __tagHexLineData
{emHexType type;quint8 count;quint32 address;quint8 data[80];quint8 checksum;quint8 datalen;
}stHexLineData;class CHex
{
public:CHex();EHexErrorCode getHexLineData(QByteArray bydata,stHexLineData *p);
private:char ConvertHexChar(char ch);
};#endif // CHEX_H
源文件
#include "chex.h"const QString HexTypeTable[6] =
{"00","01","02","03","04","05",
};CHex::CHex()
{}char CHex::ConvertHexChar(char ch)
{if((ch >= '0') && (ch <= '9'))return (ch-0x30);else if((ch >= 'A') && (ch <= 'F'))return ((ch-'A')+10);else if((ch >= 'a') && (ch <= 'f'))return ((ch-'a')+10);else return (-1);
}EHexErrorCode CHex::getHexLineData(QByteArray bydata,stHexLineData *p)
{quint8 i = 0;quint8 cs_temp = 0;QString str(bydata);char *pcdata = bydata.data();quint32 linelen = str.size();if((linelen < MIN_HEX_LINE_COUNT_LENGHT)) {return HEX_LENGHT_ERROR;}if(*pcdata != 0x3A) {return HEX_FORMAT_ERROR;}//必須以":"號(hào)開(kāi)始//獲取TypeQString stype = str.mid(7,2);for(i = 0; i < RECORD_HEX_MAX; i++){if(stype == HexTypeTable[i]){p->type = (emHexType)i;break;}}if(i == RECORD_HEX_MAX) {qDebug("HEX_FORMAT_ERROR");return HEX_FORMAT_ERROR;}cs_temp += (ConvertHexChar(*(pcdata + 7)) << 4) | ConvertHexChar(*(pcdata + 8));//獲取countp->count = (ConvertHexChar(*(pcdata + 1)) << 4) | ConvertHexChar(*(pcdata + 2));cs_temp += p->count;if(p->count != (((linelen - 2) / 2) - 5)) {qDebug("HEX_FORMAT_ERROR");return HEX_FORMAT_ERROR;}//獲取addressp->address = (ConvertHexChar(*(pcdata + 3)) << 12) | (ConvertHexChar(*(pcdata + 4)) << 8) | (ConvertHexChar(*(pcdata + 5)) << 4) | ConvertHexChar(*(pcdata + 6));cs_temp += (p->address >> 8) & 0xFF;cs_temp += p->address & 0xFF;//獲取datafor(i = 0; i < p->count; i++){p->data[i] = (ConvertHexChar(*(pcdata + 2*i + 9)) << 4) | ConvertHexChar(*(pcdata + 2*i + 10));cs_temp += p->data[i];}p->checksum = (ConvertHexChar(*(pcdata + 2*i + 9)) << 4) | ConvertHexChar(*(pcdata + 2*i + 10));if(p->checksum != ((0x100 - cs_temp) & 0xFF)){qDebug("HEX_VERIFY_ERROR");return HEX_VERIFY_ERROR;}p->datalen = p->count;return HEX_NO_ERROR;
}
總結(jié)
以上是生活随笔 為你收集整理的HEX文件格式解析(转) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。