查看完整版本: uuprog开发教程:打开(加载)hex,bin文件

liyf 发表于 2014-12-1 06:29:32

uuprog开发教程:打开(加载)hex,bin文件

   对于编程器软件来说支持hex,bin文件的加载是必须的,也是必不可少的。具体怎么解码hex文件请参考hex文件格式说明之类的资料,这里不做详细解说,我们采用现成的hex文件读写模块。bin文件就简单多了,直接以二进制读取到内存即可。
通过调用系统默认的打开文件对话框实现:

手动配置好过滤条件hex和bin。实现代码如下:
void CUUProgDlg::OnFileOpen()
{
      // TODO: Add your command handler code here
      CFile ldfile;
      CString m_sFileExt;
      
      SetAppLog("加载文件开始...");
      CFileDialog mDlg(TRUE,".HEX",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"HEX文件(*.HEX)|*.HEX|BIN文件(*.bin)|*.bin||",this);
      if(mDlg.DoModal() == IDOK)
      {
                m_sFilename = mDlg.GetPathName();
                m_sFileExt = mDlg.GetFileExt();
                m_sFileExt.MakeUpper();
                //加载文件
                if(!m_sFilename.IsEmpty())
                {
                        SetAppLog("加载文件:"+m_sFilename);
                        if(ldfile.Open(m_sFilename,CFile::shareCompat|CFile::modeRead,NULL))
                        {
                              int nFileSize;
                              nFileSize=ldfile.GetLength();
                              if(m_sFileExt=="HEX")
                              {
                                        char* pFileBuf=(char*)GlobalAlloc(GMEM_FIXED,nFileSize+1);
                                        memset(pFileBuf,0,nFileSize+1);
                                        ldfile.Read(pFileBuf,nFileSize);
                                        nFileSize = HexToBin(pFileBuf,pProgBuff);
                                        GlobalFree(pFileBuf);
                              }
                              else
                              {
                                        if(nFileSize>0x10000)nFileSize=0x10000;
                                        memset(pProgBuff,0xff,0x10000);
                                        ldfile.Read(pProgBuff,nFileSize);
                              }
                              ldfile.Close();
                              SetLoadFileName(m_sFilename);
                              SetAppLog("加载完成:"+Int2Str(nFileSize)+"字节");
                        }
                        else
                        {
                              SetAppLog("加载文件失败");
                              AfxMessageBox("加载指定的文件出错");
                        }
                }
      }      
      
      else
      {
                SetAppLog("取消加载文件");
      }
}
首先通过定一个字符型指针变量,然后在内存中开辟块文件大小+1的区块,再用hextobin函数转换成字节型数据流。为什么要先把文件加载到内存在转换呢?自己想一下就明白了。
下面就是hextobin(),有两个参数,前面是char*,后面是byte*
int HexToBin(char* pHex,BYTE* pBin)//pBin指向的缓存必须不小于64k
{                                                                   //pHex指向的缓存必须以0结尾
      CString strHex;
      CArray<BYTE,BYTE>* pByteArray=NULL;
      CArray<CArray<BYTE,BYTE>*,CArray<BYTE,BYTE>*> arByteRec;
      strHex=pHex;
      int nEnd;
      BYTE byteTmp;
      int n=0,m=0;
      nEnd=strHex.Find(":00000001");
      if(nEnd<0)//先判断文件结尾处
      {
                AfxMessageBox("*.Hex文件转换失败(未找到\":00000001\"记录)!");
                return -1;
      }
      
      while(n<nEnd)//先把所有字符转换成字节
      {
                if(pHex==':')//发现':'就新增一条记录
                {
                        pByteArray=new CArray<BYTE,BYTE>;
                        arByteRec.Add(pByteArray);//增加一条记录
                        n++;
                }
                else if(pHex==0x0d)//检查是不是换行
                {
                        n++;
                }
                else if(pHex==0x0a)
                {
                        n++;
                }
                else//字符转换成字节
                {
                        if(CharToByte(&pHex,&byteTmp))
                        {
                              if(pByteArray==NULL)
                                        return -1;
                              pByteArray->Add(byteTmp);//增加一个字节
                              n++;
                              n++;
                        }
                        else
                        {
                              AfxMessageBox("*.Hex文件转换失败(错误的字符)!");
                              return -1;
                        }
                }
      }
      int nRec=arByteRec.GetSize();
      int nAddr=0;//buf中的偏移地址
      BYTE* pBuf;
      int nLength=0;//数据块长度
      int nByte=0;
      memset(pBin,0xff,0xffff);//先把每个单元置成FFH
      for(n=0;n<nRec;n++)//分析每条记录
      {
                pByteArray=arByteRec.GetAt(n);
                if(pByteArray->GetSize()<5)
                {
                        AfxMessageBox("*.Hex文件转换失败(错误的记录)!");
                        return -1;
                }
                if(pByteArray->GetAt(3)==0)//判断是不是数据记录
                {
                        nByte=(int)pByteArray->GetAt(0);
                        if(nByte>(pByteArray->GetSize()-4))//记录中数据长度不符合
                        {
                              AfxMessageBox("*.Hex文件转换失败(错误的记录)!");
                              return -1;
                        }
                        ((BYTE*)&nAddr)=pByteArray->GetAt(2);//装入地址
                        ((BYTE*)&nAddr)=pByteArray->GetAt(1);
                        
                        pBuf=&pBin;
                        for(m=0;m<nByte;m++)//把数据都拷贝到pBin
                        {
                              pBuf=pByteArray->GetAt(4+m);
                              nLength++;
                        }
                }
                else if(pByteArray->GetAt(3)==2)
                {
                        AfxMessageBox("*.Hex文件转换失败(不支持大于64k)!");
                        return -1;
                }
                else if(pByteArray->GetAt(3)==4)
                {
                        AfxMessageBox("*.Hex文件转换失败(不支持大于64k)!");
                        return -1;
                }
                else
                {
                        AfxMessageBox("*.Hex文件转换失败(错误的记录)!");
                        return -1;
                }
               
      }
      return nLength;      
}
这里采用的是全局型函数,方便其他窗口调用
文件保存就是打开的逆过程,下面就是保存部分:
void CUUProgDlg::OnFileSaveAs()
{
      // TODO: Add your command handler code here
      CString filename;
      CFile savefile;
      CString m_sFileExt;
      int filesize;

      SetAppLog("保存开始...");
      filesize = GetMinLength(pProgBuff,m_dDeviceSize);
      if (filesize ==0)
      {
                SetAppLog("缓冲区无数据,取消保存");
                AfxMessageBox("缓冲区无数据,不需保存");
                return;
      }
      CFileDialog mDlg(FALSE,".HEX",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"HEX文件(*.hex)|*.hex|BIN文件(*.bin)|*.bin||",this);
      if(mDlg.DoModal() == IDOK)
      {
                filename = mDlg.GetPathName();
                m_sFileExt = mDlg.GetFileExt();
                m_sFileExt.MakeUpper();
                SetAppLog("保存为:"+filename);
                //保存文件代码
                if (m_sFileExt=="HEX")
                {
                }
                else
                {
                        if(savefile.Open(filename,CFile::shareCompat|CFile::modeCreate|CFile::modeWrite,NULL))
                        {
                              //m_editBuf2.GetData(m_Pro.m_pReadBuf,0x10000);
                              savefile.Write(pProgBuff,filesize);
                              savefile.Close();
                        }
                }
                SetAppLog("保存完成:"+Int2Str(filesize)+"字节");
      }      
      else
      {
                SetAppLog("取消保存");
      }

      
}我们这里只实现了bin文件的保存,hex处理部分没有代码,暂时无法实现。
实现hex,bin的识别主要通过文件后缀名实现的,通过if语句实现不同的处理。

hdzl 发表于 2014-12-1 08:29:21

这是用VC编的?

liyf 发表于 2014-12-1 09:55:52

hdzl 发表于 2014-12-1 08:29
这是用VC编的?

整个工程都是用vc6++

dwl65 发表于 2014-12-1 21:29:52

观摩中~~~~:lol

cdk005 发表于 2014-12-10 13:35:40

功能这么强大。:lol

bywqdq 发表于 2015-1-12 09:31:20

现在学vc好吗,还是学c#,我会一点qt

bywqdq 发表于 2015-1-12 09:33:59

能不能提供一些vc学习的资料,好快速的入门

liyf 发表于 2015-1-12 10:10:13

bywqdq 发表于 2015-1-12 09:33
能不能提供一些vc学习的资料,好快速的入门

这个比较难推荐了,个人的基础不同,接受能力不同,学习的方法不同等等,你可以看看我店里提供的学vc的教程和资料,有些是我自己整理的,当然是以我的学习角度整理
页: [1]
查看完整版本: uuprog开发教程:打开(加载)hex,bin文件