目录

1.hex文件分析

2.hex文件和bin文件的区别

3.基于qt开发hex转bin工具


前言:很多MCU代码编译器都会生成hex文件,hex文件的用途很多。有些直接把它放进U盘,然后给MCU自举升级,在MCU读取hex文件的时候需要将hex里的数据转换之后才能写到自身的flash里,给自身升级。当然,也可以先把hex转换成bin文件,再放进U盘给MCU自举升级,这样MCU从bin里读到的数据可以直接写到flash里,从而提高大大提高升级速度。

1.hex文件分析

下面截取从hex文件截图了几行:


        第一行:02000040800F2  即: 0x02 0x00 0x00 0x04 0x08 0x00 0xF2,都是一个个的十六进制数。一行数据中不同的颜色代表不同的信息域:

以上面的数据行格式分析下面一行:

各个域的信息分别为:

数据长度:0x01
                     数据地址:0x0000
                     数据类型:0x00
                     数据:0807002001010008CB020008C3020008
                     校验值:0x15

其中,数据类型有以下几类:

00:数据记录
01:文件结束记录
02:扩展段地址记录
03:开始段地址记录
04:扩展线性地址记录
05:开始线性地址记录

扩展段地址记录和扩展线性地址记录是用来干什么的呢?

行格式里的数据地址用两个字节保存,最大值0xFFFF,只能表示64k;一般很多的MCU里的flash都超过64k,为了保存高地址的数据,就有了扩展段地址扩展线性地址

当读取这行的数据类型是0x04(扩展线性地址)时,那么,这行的数据就是随后数据的基地址。例如:

第一行的数据类型是0x04(扩展线性地址),它的数据0x0800,就是第二行数据的基地址。第二行的数据类型是0x00(数据记录),它的地址是0x0000,那么它的数据0807002001010008CB020008C3020008要写入flash的地址为(0x0800<<16)|0x0000 ,也就是写入flash的0x0800 0000这个地址。第三行的数据的写入地址为0x0800 0010,该基地址保留到下一个扩展记录为止。

当读取这行的数据类型是0x02(扩展段地址)时,例如:

第一行的数据类型是0x02(扩展段地址) ,它的数据是0x1200;那么,第二行的数据00000000472105014B21050100000000要写flash的地址为(0x1200<<2)+0x2460,也就是写入flash的0x0001 4460这个地址第三行也是以0x1200为基地址,同样的计算出真正写入的地址。

如果用Notepad+编辑器打开hex文件,它会把不同的数据域标记不同的颜色,而且,如果最后的校验值是的对话,标注为绿色,若校验值错误,标注为黄色。

到此,我们已经大概知道怎么解读hex文件了。下面可以开始尝试把它应用起来。

2.hex文件和bin文件的区别

第一点:

hex文件和bin文件都是进行MCU开发时生成的烧录文件,hex文件是携带了数据和其数据对应在MCU flash存放的地址;bin文件纯属数据,那么怎么知道它的数据该怎么保存在flash里呢?bin里的数据是没有地址,但是它的数据时连续的,只要确定数据的写入起始地址,那么所有数据就在这个起始地址开始递增写入就行了。当我们用上位机Flash Loader Demo烧录芯片,用的烧录文件就是bin文件,烧录的时候是要先配置flash起始烧录的地址。

第二点:

hex文件的数据需要经过转换才能写入flash,这个转换过程可以发生在烧录器里、烧录的上位机里或者是MCU自举升级时先转换在写flash。bin文件数据可以直接复制到相应的flash位置上,不需要再经过任何处理。

第三点:

同一个工程编译出来的hex文件肯定比bin文件大,所以bin文件具有节省内存、便于传输的优点。为什么hex文件会比bin文件大呢?看下面例子:

char hex[9] = "12487936";//占用9字节
char bin[4]={0x12,0x48,0x79,0x36};//只占用4字节

hex文件里的数据时可以打印显示出来的,而bin文件是二进制数据。

接下来我们尝试怎么把hex文件转换成bin文件。

3.基于qt开发hex转bin工具

如果用keil工具进行编译,keil提供了直接生成bin文件的插件,在配置里加入:

这样就能直接生成bin文件,文件名为UPDATA.bin。而接下来要做的是,基于qt自己编写一个exe程序,通过读入hex文件转换生成bin文件。

1.新建一个Qt控制台应用:

2.先看main函数:

#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <stdlib.h>
#include <QByteArray>
#include <QDataStream>typedef struct{unsigned char datalen;//数据字节unsigned short addr;//地址域unsigned char datatype;//类型unsigned char databuf[16];//数据记录unsigned char checkout;//校验和
}HexFormatForLine ;bool ReadHexLineData(HexFormatForLine* out,const QByteArray & ba);//false: 校验错误 true:校验成功
char HexToBin(HexFormatForLine* ba,QDataStream & out);//return 0: ok  1:hex文件结束 2:hex文件有误int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QString filepath=QString(argv[1]);//获取hex文件路径QFile hexfile(filepath);QFile outfile;outfile.setFileName(QString(argv[2]));//获取bin文件的保存路径if(outfile.open(QIODevice::WriteOnly)==false){qDebug("创建bin文件失败!");a.exit(0);}QDataStream out(&outfile);if(hexfile.open(QIODevice::ReadOnly)==false){qDebug("打开hex文件失败!");outfile.close();a.exit(0);}QByteArray alinedata;HexFormatForLine HexDataStr;while(!hexfile.atEnd()){//循环处理,至hex文件读完/*若: alinedata =QByteArray::fromHex(":12345678");则: alinedara ={0x12,0x23,0x45,0x78};*/alinedata = QByteArray::fromHex(hexfile.readLine());//从hex文件中读取一行bool ret = ReadHexLineData(&HexDataStr,alinedata);//将一行数据解读到HexDataStr结构体if(!ret){qDebug("校验出错,hex文件有误.");outfile.remove();//删除输出的bin文件hexfile.close();//关闭输入文件a.exit(0);}ret=HexToBin(&HexDataStr,out);//将解读后的数据写入bin文件if(ret!=0){break;}}qDebug() <<"hex2bin ok.";hexfile.close();outfile.close();a.exit(0);
}

编程要点:

  • 通过argv参数获取hex文件的路径和配置bin文件的保存路径
  • QFile文件读写操作
  • 利用fromHex函数将hex里的字符串转换成16进制编码的数组。
  • 在while循环里,每一次循环读取hex文件的一行数据进行处理,ReadHexLineData函数将一行数据里的每一个域解析并保存在HexDataStr结构体里面。 然后将该结构体传入HexToBin函数处理。

3.下面提供ReadHexLineData和HexToBin函数:

bool ReadHexLineData(HexFormatForLine* out,const QByteArray & ba)//false: 校验错误 true:校验成功
{unsigned char i,checkoutCal=0;//计算校验值for(i=0;i < ba.size()-1;i++){checkoutCal += (unsigned char)ba.at(i);}checkoutCal = 0x100-checkoutCal;//获取个部分域的值out->datalen =(unsigned char)ba.at(0);out->addr = ((unsigned char)ba.at(1)<<8)|(unsigned char)ba.at(2);out->datatype = (unsigned char)ba.at(3);memset(out->databuf,0,sizeof(out->databuf));for(i = 0;i<out->datalen;i++){out->databuf[i] = (unsigned char)ba.at(4+i);}out->checkout = (unsigned char)ba.at(4+i);
#if  0 //调试时打开qDebug("datalen=%X",out->datalen);qDebug("addr=%X",out->addr);qDebug("datatype=%X",out->datatype);qDebug("checkout=%X",out->checkout);qDebug("checkoutCal=%X",checkoutCal);
#endif//比较读取的校验值和计算的校验值是否一致if(checkoutCal == out->checkout){return true;}return false;
}char HexToBin(HexFormatForLine* ba,QDataStream & out)//return 0: ok  1:hex文件结束 2:hex文件有误
{static unsigned int ExStageAddr = 0x00;//扩展段地址static unsigned int ExLineAddr = 0x00;//扩展线性地址static unsigned int absoluteAddrLocal = 0x00;//本地记录绝对地址unsigned int absoluteAddrCurrent = 0x00;//计算当前记录的绝对地址unsigned int Bytesskipped = 0;//被跳过的字节数switch(ba->datatype){case 0x00://数据记录//计算出当前记录的绝对地址if(ExStageAddr != 0){absoluteAddrCurrent = (ba->addr+ExStageAddr);}else if(ExLineAddr != 0){absoluteAddrCurrent = (ba->addr|ExLineAddr);}else{absoluteAddrCurrent = ba->addr;}//hex文件第一条数据记录时,将本地绝对地址absoluteAddrLocal同步等于当前记录的绝对地址absoluteAddrCurrentif(absoluteAddrLocal == 0){absoluteAddrLocal = absoluteAddrCurrent;}Bytesskipped = absoluteAddrCurrent-absoluteAddrLocal;//比较当前记录的绝对地址absoluteAddrCurrent和本地的绝对地址absoluteAddrLocal是否有偏差break;case 0x01://文件结束记录return 1;break;case 0x02://扩展段地址记录ExStageAddr = (ba->databuf[0]<<8|ba->databuf[1])<<2;ExLineAddr = 0x00;return 0;//return okbreak;case 0x04://扩展线性地址记录ExLineAddr = (ba->databuf[0]<<8|ba->databuf[1])<<16;ExStageAddr = 0x00;return 0;//return okbreak;default:return 2;break;}for(unsigned int i = 0;i < Bytesskipped;i++){//被跳过的地址,填充0out <<(unsigned char)0x00;}if(Bytesskipped!=0){qDebug() <<Bytesskipped;}absoluteAddrLocal += Bytesskipped;//本地绝对地址absoluteAddrLocal累加for(unsigned int i = 0;i < ba->datalen;i++){out <<ba->databuf[i];}absoluteAddrLocal += ba->datalen;//本地绝对地址absoluteAddrLocal累加return 0;//return ok
}

将上面两块代码复制在工程,选择Release,点击build,编译出exe程序。这里不能点击run,因为点击run默认不会写argv参数。我们需要argv参数提供hex文件路径和bin文件的保存路径(这里可以在代码里加入一个默认路径,这样,若argv为空则使用默认路径)。

4.将生成的exe文件复制到单独的文件夹:

在电脑左下角搜索qt,找到Qt 5.4 for Desktop (MinGW 4.9 32 bit) 工具,点击打开,切换到刚才保存exe文件的目录,输入windeployqt hex2bin.exe,这个就可以把exe需要的库文件复制到exe保存路径下:

红框里的文件可以删除来节约空间:

5.接下来把需要转换的hex文件也放进这个文件夹,同时增加了run_hex2bin.bat文件,这个是为了调用hex2bin.exe,bat里面的内容是:

hex2bin.exe  ./UPDATA.hex ./UPDATA.bin

点击run_hex2bin.bat,就会运行hex2bin.exe文件,然后生成的bin文件就会保存在该目录下。

6.前面提到过用keil自带的插件可以生成bin文件,那么现在可以在keil工程配置那里,after build之后凋用我们自己做的hex2bin.exe来将hex文件转换成bin文件。当然前提要把hex2bin.exe文件及其需要的dll文件全部复制到keil工程文件uvproj所在的目录下。再进行如下配置:

将keil工程编译一次,在对比用fromelf和自己做的hex2bin.exe生成的bin文件是否完成一致,我试过是一样的。

qt工程源码:https://download.csdn.net/download/weixin_42653531/12629575

hex文件分析+Qt5制作Hex文件转Bin文件的工具(含源码+工具下载)相关推荐

  1. Html制作抖音网红时钟罗盘【含源码免费下载】

    需要源码 文末公众号回复[时钟]即可获得源码 废话不多说 直接看效果 由于代码过长 所以下文代码展示为部分代码 html代码 <!DOCTYPE html> <html lang=& ...

  2. Qt+mpv制作windows/linux 下的动态壁纸软件(含源码)

    mpv是啥? mpv之前是mediaplayer,windwos之前好像都有预装这个,都来经过发展,现在是一个对跨平台开发很友好的播放器工具. Qt是啥? 制作桌面应用程序的开发语言及工具,基于C++ ...

  3. 【博主推荐】HTML制作一个美观的个人简介网页(附源码)

    文章目录 HTML制作一个美观的个人简介网页 模块1(个人信息)示例图 模块2(基本资料)示例图 模块3(项目经验)示例图 模块4(专业技能)示例图 模块5(工作经历)示例图 模块6(自我评价)示例图 ...

  4. H5类似易企秀/编辑器/页面制作/开发/生成工具/软件/源码/授权

    代码地址如下: http://www.demodashi.com/demo/14960.html 项目简介 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具 ...

  5. 智能家居硬件小制作(含源码)《手势识别控制器》基于PAJ7620手势模块、L298N驱动板、arduino

    智能家居硬件小制作(含源码)<手势识别控制器>基于PAJ7620手势模块.L298N驱动板.arduino 目录 智能家居硬件小制作(含源码)<手势识别控制器>基于PAJ762 ...

  6. 【SemiDrive源码分析】【X9芯片启动流程】12 - freertos_safetyos目录Cortex-R5 DIL2.bin 之 sdm_display_init 显示初始化源码分析

    [SemiDrive源码分析][X9芯片启动流程]12 - freertos_safetyos目录Cortex-R5 DIL2.bin 之 sdm_display_init 显示初始化源码分析 一.s ...

  7. 【SA8295P 源码分析】16 - TouchScreen Panel (TP)线程函数 tp_recv_thread() 源码分析

    [SA8295P 源码分析]16 - TouchScreen Panel (TP)线程函数 tp_recv_thread 源码分析 一.TP 线程函数:tp_recv_thread() 二.处理&am ...

  8. 最新中国福彩分析大数据分析大师拥有双色球数据展示微信小程序源码支持双色球数据分析多个接口

    demo软件园每日更新资源,请看到最后就能获取你想要的: 1.最新中国福彩分析大数据分析大师拥有双色球数据展示微信小程序源码支持双色球数据分析多个接口 福彩大数据分析小程序,数据来自于中国福利彩票 拥 ...

  9. Python制作经典游戏案例-水果忍者(附源码等文件)

    目录 前言 代码展示 总结 前言 大家好,我是辣条哥,今天给大家分享一款我以前特爱玩的游戏,水果大战,今天我就教大家使用python把这款游戏制作出来.我们先来看效果 点击跳转文末 相关的一些音乐文件 ...

  10. 性能优化-Android之ANR分析解决 traces.txt文件分析 CPU占用过高 解决ANR文件没有导出权限问题

    (由于公司项目特殊情况,需要使用一些小厂的三防功能手机,不能使用我们平时用的这些民用手机) 前期测试的时候是用民用手机测试的,有六七种机型(小米,华为,中兴,oppo),使用过程中均没有出现ANR的情 ...

最新文章

  1. umijs多环境配置_umi 项目多环境打包配置
  2. C# 笔记 .net与C#简单说明
  3. 成功解决Redirection is not supported
  4. 安卓学习之--如何关闭所有的activity
  5. 让软件不在添加删除程序_功能强大却鲜为人知的四款软件,一但发现就无法自拔...
  6. matlab中如何提取等高线,在Python或MATLAB中从等高线图中提取数据
  7. php 函数有命名空间吗_解析 ThinkPHP 的命名空间
  8. 强化学习《基于策略价值 - Actor-Critic》
  9. 零点是结束,也是开始。
  10. aqara (737) -(a俩)_绿米与万科合作?Aqara线下服务商500家,合作有保障
  11. 50个知名的开源网站
  12. RFID和NFC的区别
  13. 【kali】34 WEB渗透——扫描工具w3af_console
  14. 智能眼镜的两种显示方式
  15. PPT模板下载100套欧美风云盘下载
  16. 论文笔记2.5D lightweight RIU-Net for automatic liver and tumor segmentation from CT
  17. [渝粤教育] 西南科技大学 法律文书写作 在线考试复习资料
  18. Html+Vue实现五子棋游戏(单机版)
  19. 为什么终结符只有综合属性?
  20. 记录kafka consumer 消费失败

热门文章

  1. (1) Kubernetes基本概念和术语
  2. ubuntu的一些技巧
  3. ios UISegmentedControl的使用简介
  4. 数字逻辑电路课程设计报告
  5. win7下u盘安装ubuntu组成双系统
  6. MFC使用ADO对象开发数据库应用程序
  7. php 添加数据sql语句,PHP添加/修改/删除SQL语句
  8. yolov3-tiny 训练一个检测器(2)
  9. 从二元函数的泰勒展开到应用Hessian矩阵检测边缘
  10. L4Linux的版本比较