當前位置:法律諮詢服務網 - 中國稅務 - 如何解析HEX

如何解析HEX

hex文件是用ASCII來表示二進制的數值,十六進制數組成的指令或者數據,每壹行就是壹個hex記錄。由於單片機執行的只能是二進制指令和數據,而hex文件是十六進制數,所以燒錄器的工作必然有壹個進制轉換機制。

hex文件的內容都是有規律的編碼,我們可以對它進行解析,以第壹行 :020000040800F2 為例:

1) 每壹行都以 :(0x3A)開頭

2) 第1個字節0x02 ,表示數據區的字節個數

3) 第2、3字節0x00, 0x00 ,表示偏移地址或無用填0

4) 第4個字節0x04, 表示本行記錄的數據類型

‘00’ Data Record ? :用來記錄數據, HEX文件的大部分記錄都是數據記錄

‘01’ End of File Record ? :用來標識文件結束,放在文件的最後,標識HEX文件的結尾

‘02’ Extended Segment Address Record? :用來標識擴展段地址的記錄

‘03’ Start Segment Address Record :段地址 STM32不用

‘04’ Extended Linear Address Record? :用來標識擴展線性地址

‘05’ Start Linear Address Record :程序啟動運行的地址

5) 第5、6個字節0x08, 0x00即是數據

6) 第7個字節0xF2是校驗字節,校驗和的算法為:計算從0x3A 以後(不包括0x3A)的所有各字節的和模256的余。即各字節二進制算術和,不計超過256的溢出值,然後用0x100減去這個算數累加和,得出得值就是此行得校驗和。

7) 每條數據最後還有<0x0d> (回車鍵)、 <0>(換行鍵)

<0x3a>? [數據長度-1Byte] [數據地址-2Byte] [數據類型-1Byte] [數據-nByte] [驗證碼-1Byte] <0x0d><0>

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

第壹行,是Extended Linear Address Record,裏面的數據,也就是基地址是0x0004,

第二行是Data Record,裏面的地址值是0x0000。那麽數據18F09FE518F09FE518F09FE518F09FE5要寫入FLASH中的地址為(0x0004 << 16) | 0x0000,也就是寫入FLASH的0x40000這個地址。

第三行的數據的寫入地址為0x40010。當壹個HEX文件的數據超過7k的時候,文件中就會出現多個Extended Linear Address Record。

----------------------------------------------------

:020000040008F2

:10000400FF00A0E314209FE5001092E5011092E5A3

:00000001FF ?

-----------------------------------------------------

對上面的HEX文件進行分析:

第1條記錄的長度為02,LOAD

OFFSET為0000,RECTYPE為04,說明該記錄為擴展段地址記錄。數據為0008,校驗和為F2。從這個記錄的長度和數據,我們可以計算出壹個基地址,這個地址為(0x0008

<< 16)。後面的數據記錄都以這個地址為基地址。

第2條記錄的長度為10(16),LOAD

OFFSET為0004,RECTYPE為00,說明該記錄為數據記錄。數據為FF00A0E314209FE5001092E5011092E5,***16個BYTE。這個記錄的校驗和為A3。此時的基地址為0X80000,加上OFFSET,這個記錄裏的16BYTE的數據的起始地址就是0x80000

+ 0x0004 = 0x80004.

第3條記錄的長度為00,LOAD OFFSET為0000,TYPE = 01,校驗和為FF。說明這個是壹個END OF FILE RECORD,標識文件的結尾。

在上面這個例子裏,實際的數據只有16個BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址為0x0004.

計算從(0x3a)以後的所有各字節的和模256的余。

即各字節二進制算術和,不計超過256的溢出值,然後用0x100減去這個算數累加和,得出的值就是此行校驗碼。舉壹個簡單的例子,

如第壹行020000040800F2

0x02+0x00+0x00+0x00+0x04+0x08+0x00 = 0x0E

0x100 –?0x0E = 0xF2

for (i = 0; i < pHexFileFormat->DataSize; i++)

{

tempCheckSum += pHexFileFormat->bData[i];

}

tempCheckSum = 0x100 - tempCheckSum;

if (tempCheckSum != pHexFileFormat->CheckSum)

{

//Error

}

#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;}//必須以":"號開始

//獲取Type

QString 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));

//獲取count

p->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;}

//獲取address

p->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;

//獲取data

for(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;

}

  • 上一篇:如何查詢組織機構代碼?
  • 下一篇:2022誌願者服務日活動流程內容
  • copyright 2024法律諮詢服務網