天天看點

S-Record格式分析代碼

//========================================================================

//TITLE:

//    S-Record格式分析代碼

//AUTHOR:

//    norains

//DATE:

//    Wednesday  30-April-2008

//Environment:

//    NULL

//========================================================================

    MOTOROLA S-Record的格式并不複雜,相關的描述可以參考我另一篇文章《S-Record格式詳解》:http://blog.csdn.net/norains/archive/2008/04/25/2326306.aspx。本文主要是在代碼層次對S-Record進行分析。

    和以往相同,為了友善使用,将S-Record的分析代碼封裝為一個CSrecParse類。

    以下為CSrecParse類代碼:   

//   

// SrecParse.h: interface for the CSrecParse class.

//

//   

#pragma once

#include <string>

#include <vector>

#ifdef UNICODE

    typedef std::wstring TSTRING;

#else

    typedef std::string TSTRING;

#endif

class CSrecParse

{

public:

    enum Type

    {

        S0 = 0,

        S1,

        S2,

        S3,

        S4,

        S5,

        S6,

        S7,

        S8,

        S9

    };

public:

    //Interface

    bool SetFile(const TSTRING & strFile);

    bool GetNextData(CSrecParse::Type &type, DWORD &dwAddr,std::vector<BYTE> &vctData, bool &bChkSum);

public:

    CSrecParse(void);

    ~CSrecParse(void);

    void Reset(void);

protected:

    DWORD HexToDec(const char *pChar,int iLen = -1);

private:

    std::string::size_type m_stPos;

    std::string m_strContent;

};

//   

// SrecParse.cpp

//

//  

#include "stdafx.h"

#include "SrecParse.h"

CSrecParse::CSrecParse(void):

m_stPos(0)

{

}

CSrecParse::~CSrecParse(void)

{

}

//----------------------------------------------------------

//Description:

// Set the S-Record file to parse

//

//----------------------------------------------------------

bool CSrecParse::SetFile(const TSTRING & strFile)

{

 HANDLE hFile = CreateFile(&strFile[0],GENERIC_READ,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

 if(INVALID_HANDLE_VALUE == hFile)

 {

  return false;

 }

 DWORD dwFileSize = GetFileSize(hFile,NULL);

 if(m_strContent.capacity() < dwFileSize)

 {

  m_strContent.resize(dwFileSize);

 }

 DWORD dwFileRead = 0;

 ReadFile(hFile,&m_strContent[0],dwFileSize,&dwFileRead,NULL);

 CloseHandle(hFile);

 return true;

}

//----------------------------------------------------------

//Description:

// Get the next data. If you want to get the first data,you should call Reset() before calling the function.

//

//Parameter:

// type : [out] The data type

// dwAddr : [out] The address

// vctData : [out] The buffer for store the data.

// bChkSum : [out] The checksum is right or not.

//

//----------------------------------------------------------

bool CSrecParse::GetNextData(CSrecParse::Type &type, DWORD &dwAddr,std::vector<BYTE> &vctData, bool &bChkSum)

{

 m_stPos = m_strContent.find("S",m_stPos); 

 if(m_stPos != std::string.npos)

 {

  std::string strCvrt(10,0);

  std::vector<BYTE> vctStore;

  DWORD dwSum = 0;

  //The type

  strCvrt[0] = m_strContent[m_stPos + 1];

  strCvrt[1] = '/0';

  type = static_cast<CSrecParse::Type>(atoi(&strCvrt[0]));

  if(type == S5)

  {

   //Doesn't support the S5 type in current

   return false;

  }

  //The length, include <address>,<data>,<checksum> field;

  strCvrt[0] = m_strContent[m_stPos + 2];

  strCvrt[1] = m_strContent[m_stPos + 3];

  strCvrt[2] = '/0';

  int iLength = static_cast<int>(HexToDec(&strCvrt[0])) * 2; //Plus 2 to convert to the string length.

  dwSum += static_cast<int>(HexToDec(&strCvrt[0]));

  if(type == S0)

  {

   //Address

   dwAddr = 0;

   //The data

   for(int i = 0; i < iLength - 6; i += 2)

   {

    strCvrt[0] = m_strContent[m_stPos + 8 + i];

    strCvrt[1] = m_strContent[m_stPos + 9 + i];

    strCvrt[2] = '/0';

    BYTE uData = static_cast<BYTE>(HexToDec(&strCvrt[0]));

    vctStore.push_back(uData);

    dwSum += uData;

   }

   vctData = vctStore;

   //The checksum

   strCvrt[0] = m_strContent[m_stPos + iLength + 2];

   strCvrt[1] = m_strContent[m_stPos + iLength + 3];

   strCvrt[2] = '/0';

   bChkSum = (static_cast<BYTE>(HexToDec(&strCvrt[0])) == ( 0xFF - (dwSum & 0xFF)));

   m_stPos ++;

   return true;

  }

  else

  {

   //S1,S2,S3,S7,S8,S9

   //The address

   int iLenAddr = 0;

   switch(type)

   {

    case S1:

    case S9:

     iLenAddr = 2 * 2;//Plus 2 to convert to the string length.

     break;

    case S2:

    case S8:

     iLenAddr = 3 * 2;//Plus 2 to convert to the string length.

     break;

    case S3:

    case S7:

     iLenAddr = 4 * 2;//Plus 2 to convert to the string length.

     break;

   }

   for(int i = 0; i < iLenAddr; i++)

   {

    strCvrt[i] = m_strContent[m_stPos + 4 + i];  

   }

   strCvrt[iLenAddr] = '/0';

   dwAddr = HexToDec(&strCvrt[0]);

   for(int i = 0; i < iLenAddr; i += 2)

   {

    dwSum += HexToDec(&strCvrt[i],2);

   }

   //The data 

   int iCount = iLength - iLenAddr - 2; //The length of 2 is checksum.

   std::string::size_type stPosBegin = m_stPos + 3 + iLenAddr + 1;

   for(int i = 0; i < iCount; i += 2)

   {

    strCvrt[0] = m_strContent[stPosBegin + i];

    strCvrt[1] = m_strContent[stPosBegin + i + 1];

    strCvrt[2] = '/0';

    BYTE uData = static_cast<BYTE>(HexToDec(&strCvrt[0]));

    vctStore.push_back(uData);

    dwSum += uData;

   }

   vctData = vctStore;

   //The checksum.

   strCvrt[0] = m_strContent[m_stPos + iLength + 2];

   strCvrt[1] = m_strContent[m_stPos + iLength + 3];

   strCvrt[2] = '/0';

   bChkSum = (static_cast<BYTE>(HexToDec(&strCvrt[0])) == ( 0xFF - (dwSum & 0xFF)));

  }

 }

 else

 {

  return false;

 }

 m_stPos ++;

 return true;

}

//----------------------------------------------------------

//Description:

// Reset the indext to call GetNextData() to get the first data.

//

//----------------------------------------------------------

void CSrecParse::Reset(void)

{

 m_stPos = 0;

}

//----------------------------------------------------------

//Description:

// Hex convert to decade.

//

//Parameter:

// pChar : [in] The string to convert. If iLen is -1,it must be with the NULL terminate end.

// iLen : [in] The length of the pChar buffer. The default value is -1;

//

//----------------------------------------------------------

DWORD CSrecParse::HexToDec(const char *pChar,int iLen)

{

 DWORD val = 0;  

 int iCount = 0;

 while(*pChar)  

 {  

  if(*pChar >= 'a' && *pChar <= 'f')  

  {

   val = val * 16 + *pChar - 'a' + 10;  

  }

  else if(*pChar >= 'A' && *pChar <= 'F')

  {

   val = val * 16 + *pChar - 'A' + 10;

  }

  else if(*pChar >= '0' && *pChar <= '9')  

  {

   val = val * 16 + *pChar - '0';  

  }

  else

  {

   break;  

  }

  pChar++;  

  if(iLen != -1)

  {

   iCount ++;

   if(iCount >= iLen)

   {

    return val;

   }

  }

 }  

 return   val;

}

    該類的使用非常簡單,現在以一個很基本的代碼作為示例:

  CSrecParse parse;

  //設定需要分析的檔案路徑

    parse.SetFile(&strFile[0]);

    //資料的類型 

    CSrecParse::Type type;

    //資料的位址

    DWORD dwAddr;

    //存儲資料的緩存

    std::vector<BYTE> vctData;

    //ChkSum位是否正确

    bool bChkSum;

    std::vector<BYTE> vctStore;

    while(parse.GetNextData(type,dwAddr,vctData,bChkSum) == true)

    {

    if(type == CSrecParse::S5)

        {

            //S5格式暫時不支援

            break;

        }

        else

        {

          //...

          //根據分析回來的資料去做相應處理

        }

    }

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/norains/archive/2008/04/30/2349903.aspx