HEX文件格式解析(转)

Hex格式文件有两种,一种是Intel的Intel HEX,另一种是Motorola(摩托罗拉)的SREC(又称MOT)。


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

Hex文件是可以烧写到单片机中,被单片机执行的一种文件格式,生成Hex文件的方式由很多种,可以通过不同的编译器将C程序或者汇编程序编译生成hex。

一般Hex文件通过记事本就可以打开。可以发现一般Hex文件的记录格式如下:

在这里插入图片描述

Intel HEX 由任意数量的十六 进 制 记录组 成。每 个记录 包含5 个 域, 它们按以下格式排列:

每一组字母 对应 一 个 不同的域,每一 个 字母 对应 一 个 十六 进 制 编码 的 数 字。每一 个 域由至少 两个 十六 进制 编码数 字 组 成, 它们构 成一 个 字 节 ,就像以下描述的那 样:

(1):(冒号)每个Intel HEX 记录 都由冒 号开头 ;

(2)LL 是 数 据 长 度域, 它 代表 记录当 中 数 据字 节 (dd) 的 数量 ;

(3)aaaa 是地址域, 它代表 记录当 中 数据的起始地址;

(4)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)

(5)dd 是数 据域 , 它 代表一 个 字 节 的 数 据. 一 个记录 可以有 许 多 数 据字 节 . 记录当 中 数 据字 节 的 数 量必 须 和数 据 长 度域(ll) 中指定的 数字相符.

(6)cc 是校验 和域 , 它 表示 这个记录 的校 验 和. 校 验 和的 计 算是通 过将记录当 中所有十六 进 制 编码数 字 对 的 值相加, 以256 为 模 进 行以下 补 足.

表示为:“:[1字节长度][2字节地址][1字节记录类型][n字节数据段][1字节校验和] ”


(TT)具体根据记录类型分析如下:

(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=FCH;

当一 个扩展 线 性地址记录被读 取, 存 储于数据域的扩展线性地址被保存,它被应于

从 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


SREC
SREC全称Motorola S-record,一种文件格式,由摩托罗拉创建的,该文件使用ASCII HEX文件格式表达二进制信息。这种格式也叫做SRECORD, SREC, S19, S28, S37。通常用于微控制器编程,EPROMs和其他可编程的逻辑器件。在通常的应用中,编译器或汇编器将程序的源代码(如C语言或汇编语言)转换成机器代码,并将其输出到一个HEX文件。然后这个HEX文件被程序员烧写到ROM中,或者转移到目标系统用于装载和执行。
//SREC格式

//第一行数据
S0 0F 0000 636B3631302D6C2E73686578 0C
//行数据
S2 08 010000 FFFFFFFF FA
S3 15 08640000 6C0264086C0264086C0264086C026408 16
S5 03 0002 FA
S7 05 08640214 78

SREC文件一行为单位,分为5个部分。分别是记录类型域、字节数域、地址域、数据域、校验域。

第一部分类型域是SREC文件的起始标志,代表该行的类型,必须已S开始,值可以是从S0到S9;

HEX文件格式解析(转)_第1张图片
第二部分字节数域是每行记录的长度,地址域、数据域、校验域三个域的长度,单位为字节数。

第三部分地址域,该域的长度取决于第一部分类型域。

第四部分数据域,该自动长度=字节数域的值-地址域长度-1(校验域长度)

第五部分校验域,该域长度为1byte(16-bit),校验方法是:除了类型域的值其他十六进制值每两个一组相加结果末两位为0xFF。


读取代码:
QT语言

#include
#include
#include
#include
#include
#include
#include
#include

static char pq=9;  //规范代码

/****16进制的数据类型*****/
const QString HexTypeTable[6] =
{
    "00","01","02","03","04","05",
};

/****配套数据类型使用的枚举变量*****/
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};   //定义字符串的类型格式

/****函数声明*********/
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);


/****计算字符串长度*****/
int mystrlen(const char *StrDest)
{
    int i;
    i=0;
    while((*StrDest++)!='\0')
    {
        i++;
    }//这个循环体意思是从字符串第一个字符起计数,只遇到字符串结束标志'\0’才停止计数
    return i;
}

/****16进制转换10进制*****/
int HexToDec(char *src)
{
    //将src中的无符号十六进制字符串转为十进制数
    //如src="001A",则返回26
    //字符串src需要以'\0'作为结束标志
    int value=0,srclen=mystrlen(src);
    int i;
    for(i=0;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;//返回转换后的数值
}


/****字符串效验*返回效验的十进制数用来与字符串后两位做比较****/
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);    //转换成10进制运算后,再转换成十六进制

       printf(" %d",HexToDec(stype.toLatin1().data()));
       tempsum+=HexToDec(stype.toLatin1().data());
       i+=2;
   } while (i<(mystrlen(dest)-2));

   /***HEX计算公式(0x100-(16进制数据和后两位))再取后两位=字符串后两位*****/
   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()"<0)
     {
         src.insert(src.size()-2,zero);  //末尾位加零
         src.remove(0,1);    //删除起始位
     }
     return src;
 }


 /***0613*****字符串以十六进制的形式转换成十进制相加,然后转换成十六进制的字符串形式输出*****/
 QString QStringToAdd(QString dest,QString src)
 {
     QString ResultDate;
     QString ZERO="0";

     int num1,num2,ans;
     int count;
     bool ok;
     num1=dest.toInt(&ok,16);  //转换成10进制
     num2=src.toInt(&ok,16);
     ans=num1+num2;
     ResultDate=QString::number(ans,16);

     /**判断结果字符串与输入的两个字符串的最大差值,用于给结果字符串补零***/
     (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();//十进制转换成Qstring的形式输出  toUpper() //转换成大写字母
 }


/****文件格式类型判断,有错误打印,返回值为基地址******/
StringType FormatHexjudge(QByteArray src) //QString *resultBaseAddres
{
    QByteArray resultString=":00000001FF";
    static uint32_t count_num=0;
    count_num++;
    /******验证一下传入的数据***********/

    char *pcdata = src.data();

    //printf("Length of src:%d\n",mystrlen(src));   //打印传入数据大小
    while(*pcdata)
    {
        //printf("%c",*pcdata);  //打印原始数据
        ++pcdata;
    }
    //printf("\n");

    if(src.left(1)!=":")
    {//不是以":"开始
            StringTypeLine.Firstsymbolis=DATA_Flase;
            printf("Format FirstSymbol wrong!\n");
            system("Pause");
    }
    else
    {
       StringTypeLine.Firstsymbolis=DATA_Ture;
    }
    if(strlen(src)<11)
    {//字符串长度小于11
            printf("Format length wrong!\n");
            system("Pause");
     }
    else
    {
        StringTypeLine.StringSizeis=DATA_Flase;
    }
    if(strcmp(src,resultString)==0)
    {//结束标志
            StringTypeLine.StringResultis=DATA_Ture;
            printf("End of file\n");

    }
    else
    {
        StringTypeLine.StringResultis=DATA_Flase;
    }

    if(src.right(2)!= AnalyseHEX(src))    //字符效验
    {
        StringTypeLine.StringCrcis=DATA_Flase;  //字符效验失败
        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()));     //读出来的效验值

        system("Pause");  //如果效验值错误,暂停界面
    }
    else
    {
        StringTypeLine.StringCrcis=DATA_Ture;    //字符效验正确
        //printf("\nFormat Effect Vaild!!!!!\n");
        while(mystrlen(src)-2>pq)   //打印完所有的数据
        {
          QString st = src.mid(pq,2);
          pq+=2;

          printf("%c%c ",*st.toLatin1().data(),*(st.toLatin1().data()+1));
        }
    }

     /****判断数据类型****/

    QString stringtype = src.mid(7,2);
    //printf("\nstringtype: %c%c\n",*stringtype.toLatin1().data(),*(stringtype.toLatin1().data()+1));

    if(stringtype==HexTypeTable[RECORD_DATA])
    {  //00正常数据类型

        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 用来标识文件结束
       StringTypeLine.StringType=RECORD_END_OF_FILE;
       printf("RECORD_END_OF_FILE\n ");

    }
    else if (stringtype==HexTypeTable[RECORD_EXTENDED_LINEAR_ADDRESS])  //TODO:只需要判断一次
    {  //04 扩展线性地址记录

        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 扩展段地址记录
        StringTypeLine.StringType=RECORD_EXTENDED_SEGMENT_ADDRESS;
        printf("RECORD_EXTENDED_SEGMENT_ADDRESS\n");

    }
    else if(stringtype==HexTypeTable[RECORD_START_LINEAR_ADDRESS])
    {  //05 开始线性地址记录
        StringTypeLine.StringType=RECORD_START_LINEAR_ADDRESS;
        printf("RECORD_START_LINEAR_ADDRESS\n");

    }
    else if(stringtype==HexTypeTable[RECORD_START_SEGMENT_ADDRESS])
    {  //03 开始段地址记录
       StringTypeLine.StringType=RECORD_START_SEGMENT_ADDRESS;
       printf("RECORD_START_SEGMENT_ADDRESS\n");

       system("Pause");    //如果遇到03则暂停,预留处理03的代码  (0613/还未遇到)
    }
    return StringTypeLine;
}


/******判断基地址**如果数据类型为04调用*******/
QString BaseAddjudge(QByteArray src)
{
  QString resultBaseAddres;
  QString stringtype = src.mid(7,2);         /****判断数据类型****/
  if (stringtype==HexTypeTable[RECORD_EXTENDED_LINEAR_ADDRESS])  //TODO:只需要判断一次RECORD_EXTENDED_LINEAR_ADDRESS
  {  //04 扩展线性地址记录
      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 扩展段地址记录

      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数据类型的方式下需要左移一位
  }
  return resultBaseAddres;
}


/****新字符串拼接*****/
QString FormatTranQARRYbyte(QByteArray src)
{
    char count=9;
    char newcount=10;
    QString ResultDate;
    static QString resultBaseAddress="00000000";             //static 修饰只初始化一次 //0x08000000
    QString space=" ";

    StringTypeLine=FormatHexjudge(src);

    if(StringTypeLine.StringCrcis==DATA_Ture)   //如果效验码正确
    {
        if(StringTypeLine.StringType==RECORD_EXTENDED_LINEAR_ADDRESS)       //如果是扩展性数据类型 04
        {
                resultBaseAddress=BaseAddjudge(src);            //接收扩展地址
                qDebug()<<"resultBaseAddress"<count)   //打印完所有的数据
        {
          ResultDate.insert(newcount,src.mid(count,2));
          newcount=newcount+3;

          ResultDate.insert(newcount,space);
          count=count+2;
        }

        if(StringTypeLine.StringType==RECORD_DATA)    //当数据类型为00的时候才打印
        {
         printf("\n");
         qDebug()<<"ResultDate  "<

C#语言
头文件

#ifndef CHEX_H
#define CHEX_H
 
#include 
 
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;
}

你可能感兴趣的:(数据结构)