QT5.13.1 单片机的HEX文件转BIN文件

1.理论知识

1.1 示例文件展示 

        以下为同一个MCU程序的HEX文件(分为ASCII码查看和二进制查看)和BIN文件内容

         文件大小:bin为41K,hex为116K

sss
HEX文件,ASCII码显示
HEX文件,二进制显示
BIN文件,二进制显示

1.2 Hex文件讲解

        HEX文件内容分析    

1)数据长度

    表示有效数据的字节数,即0x0800,共2个字节(是ASCII的两个字节,实际二进制的4个字节)

2)数据类型

        00:数据记录
        01:文件结束记录
        02:扩展段地址记录
        03:开始段地址记录
        04:扩展线性地址记录,即表示后面的数据是地址偏移量
        05:开始线性地址记录

        第一行为0x04,即偏移量,也就是说第二行数据的实际地址是0x08040000,

        而第三行原本地址为0x0001的,偏移以后实际为0x08040001

3)数据地址

        为每行数据的地址,对于数据类型为0x00的行,相邻上下两行的地址差值为0x0010,即16个数,正好对应数据长度为0x10.

4)校验

        CheckSum = 0x100 - (Sum & 0xFF)

        以第一行“:020000040804EE”为例

       Sum= 02 + 00 +00 + 04 + 08 +04 = 0x12,

        CheckSum = 0x100 - (0x12&0xFF)=0xEE,正好跟最后一个字节对应。

1.3 HEX与BIN的关系

        从示例图可以看出,ASCII类型HEX第二行的实际数据的16个字节,正好与BIN文件第一行完全对应。

        而每行的分割字符为0X0D和0x0A,即“\r\n”

        这么看只要把数据类型为0的行中的冒号、数据长度、数据地址、数据类型、校验都干掉,只保留真实数据,然后把ASCII码每2字节转为1字节即可。

        具体步骤:

        ①把HEX提取到QByteArray中。

        ②把QByteArray中的所有数据提取到QStringList中,里面每行为一个QString元素。提取的分割字符为0x0D0A。

        ③根据规则只要其中的32个字符。

        ④把这每行的32个字符两两转换为一个字节,并存入新的QByteArray

        ⑤保存QByteArray结果到bin文件中

2 关键代码

    QString path=QFileDialog::getOpenFileName(this,"请选择新程序bin文件","../",tr("bin (*.hex)"));
    LE_HexFile->setText(path);
    if(path.isEmpty()==false){//如果非空
        QFile Frimware(path);

        if (!Frimware.open (QFile::ReadOnly)){
            printf("Frimware.open_Wrong!\n"); //打开文件
            qDebug() <<  "Frimware.open_Wrong!\n";
            return;
        }

        QDataStream BinFileData(&Frimware);

        BinFileData.readRawData(pBuff,static_cast<int>(Frimware.size()));
        Array_Hex = QByteArray(pBuff,static_cast<int>(Frimware.size()));
        qDebug()  << "文件总字节数:"<<Array_Hex.size();


        //把Array_Hex中的数据,提取bin数据后存入extractedData
        QByteArray extractedData;
        QString dataString(Array_Hex);
        QStringList lines ;
        lines = dataString.split("\r\n", QString::SkipEmptyParts);

        quint32 expectedAddress = 0x0000; // Starting address
        for (const QString &line : lines) {
            // 冒号(1byte)+长度 (2 bytes), 地址 (4 bytes), CMD (2 bytes), Data (length * 2 bytes), 和校验 (2 bytes)
            bool ok;
            int length = line.mid(1, 2).toInt(&ok, 16);
            qDebug()<<"lenth:"<<length;
            quint32 address = line.mid(3, 4).toUInt(&ok, 16);
            quint32 mode = line.mid(7, 2).toUInt(&ok, 16);
            if(mode==0){
                if (address == expectedAddress ) {
                    QString dataPart = line.mid(9, length*2);                   
                    QByteArray dataBytes = hexStringToByteArray(dataPart);
                    extractedData.append(dataBytes);
                    expectedAddress += 16;
                }
                else {
                    qWarning() << "无效地址:" << address<<"length:"<<length<<line;
                }
            }else{
                qDebug()<<"无效数据";
            }
        }
        Array_HexToBin = extractedData;

        //把extractedData每16个字节一行写入到TE_HexFile中进行显示。
        qDebug()  << "HEX转BIN文件总字节数:"<<extractedData.size();
        QString temp_string;
        for (int i=0;i<extractedData.size();i++) {
            if((i%16)==0){
                temp_string = QString::fromLatin1("%1")
                        .arg(static_cast<quint8>(extractedData.at(i)), 2, 16, QLatin1Char('0')).toUpper();
            }else if(((i+1)%8)==0){
                temp_string += QString::fromLatin1(" %1   ")
                        .arg(static_cast<quint8>(extractedData.at(i)), 2, 16, QLatin1Char('0')).toUpper();
            }else{
                temp_string += QString::fromLatin1(" %1")
                        .arg(static_cast<quint8>(extractedData.at(i)), 2, 16, QLatin1Char('0')).toUpper();
            }
            if((((i+1)%16)==0)||((i+1)==extractedData.size())){
                TE_HexFile->append(temp_string);
            }
        }

        if(ChecBox_AutoSave->checkState()==Qt::Checked){
            save_bin(extractedData,path);

            if(ChecBox_AutoOpen->checkState()==Qt::Checked){
                open_folder(path);
            }
        }
    }

3 完成效果   

 

功能1:自动保存到HEX文件目录,勾选此选项后,打开HEX以后自动会在HEX文件目录生成一个bin文件,文件名为HEX文件名基础上添加时间。

功能2:保存完毕自动打开BIN目录,勾选此选项后,手动或自动保存完HEX以后,会自动打开BIN所在目录。

功能3:可以手动选择要保存的路径和名称,然后保存bin文件

4 结论

生成的文件与KEIL自动生成的BIN对比完全一样。

5 源码地址

https://download.csdn.net/download/Running_A/89535727

吐槽一下CSDN审核源码的人员,效率太低了,12号上传的,19号才审核完!!!

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值