1.头文件hex2bin.h
// hex2bin.h
#ifndef HEX2BIN_H
#define HEX2BIN_H
#include <QString>
#include <QList>
#include <QByteArray>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
struct Section {
uint32_t startAddr;
uint32_t endAddr;
QByteArray data;
};
enum IntelCommand : uint8_t {
UNKNOWN = 0xFF,
DATA = 0x00,
EOF_RECORD = 0x01,
EXT_SEGMENT_ADDR= 0x02,
SEGMENT_ADDR = 0x03,
EXTEND_ADDR = 0x04,
LINEAR_ADDR = 0x05,
};
bool ry_hex2bin(const QString& hexFilePath, const QString& binFilePath, quint32& startAddress);
#endif // HEX2BIN_H
2.源代码hex2bin.cpp
C++
// hex2bin.cpp
#include "hex2bin.h"
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QList>
#include <algorithm>
static bool parseHexLine(const QString& line, uint32_t& address, uint8_t& type, QByteArray& data, uint8_t& checksum)
{
if (line.length() < 11 || line[0] != ':') {
return false;
}
bool ok;uint32_t byteCount = line.mid(1, 2).toUInt(&ok, 16);
if (!ok) return false;
address = line.mid(3, 4).toUInt(&ok, 16);
if (!ok) return false;
type = static_cast<uint8_t>(line.mid(7, 2).toUInt(&ok, 16));
if (!ok) return false;
data.clear();
for (uint32_t i = 0; i < byteCount; ++i) {
QString byteStr = line.mid(9 + i * 2, 2);
uint8_t byteVal = static_cast<uint8_t>(byteStr.toUInt(&ok, 16));
if (!ok) return false;
data.append(static_cast<char>(byteVal));
}
checksum = static_cast<uint8_t>(line.right(2).toUInt(&ok, 16));
if (!ok) return false;
return true;
}
static uint8_t calculateChecksum(const QString& line)
{
uint8_t sum = 0;
for (int i = 1; i < line.length() - 2; i += 2) {
bool ok;
uint8_t val = static_cast<uint8_t>(line.mid(i, 2).toUInt(&ok, 16));
if (!ok) break;
sum += val;
}
return static_cast<uint8_t>(0x100 - sum);
}
bool ry_hex2bin(const QString& hexFilePath, const QString& binFilePath, quint32& startAddress)
{
QFile file(hexFilePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "无法打开.hex文件:" << hexFilePath;
return false;
}
QTextStream in(&file);
QList<Section> sections;
Section currentSection;
bool firstSection = true;
uint32_t extendAddress = 0;
uint32_t segmentAddress = 0;
while (!in.atEnd()) {
QString line = in.readLine().trimmed();
if (line.isEmpty()) continue;
uint32_t address;
uint8_t type;
QByteArray data;
uint8_t checksum;
if (!parseHexLine(line, address, type, data, checksum)) {
qDebug() << "无效的HEX行:" << line;
continue;
}
if (calculateChecksum(line) != checksum) {
qDebug() << "校验失败:" << line;
continue;
}
switch (type) {
case IntelCommand::EXTEND_ADDR: {
if (data.size() >= 2) {
extendAddress = (static_cast<uint32_t>(static_cast<uint8_t>(data[0])) << 8 |
static_cast<uint8_t>(data[1])) << 16;
}
break;
}
case IntelCommand::SEGMENT_ADDR: {
if (data.size() >= 2) {
segmentAddress = (static_cast<uint32_t>(static_cast<uint8_t>(data[0])) << 12 |
static_cast<uint8_t>(data[1]) << 4);
}
break;
}
case IntelCommand::DATA: {
uint32_t physicalAddress = extendAddress + segmentAddress + address;
if (firstSection) {
startAddress = physicalAddress;
currentSection.startAddr = physicalAddress;
currentSection.endAddr = physicalAddress;
firstSection = false;
} else if (physicalAddress != currentSection.endAddr + 1) {
sections.append(currentSection);
currentSection.startAddr = physicalAddress;
currentSection.endAddr = physicalAddress;
currentSection.data.clear();
}
currentSection.data.append(data);
currentSection.endAddr = physicalAddress + data.size() - 1;
break;
}
case IntelCommand::EOF_RECORD: {
if (!currentSection.data.isEmpty()) {
sections.append(currentSection);
}
file.close();
break;
}
default:
break;
}
}
file.close();
if (sections.isEmpty()) {
qDebug() << "未找到有效数据段";
return false;
}
// 合并所有段,生成BIN
uint32_t minAddr = sections[0].startAddr;
uint32_t maxAddr = sections.last().endAddr;
int binSize = maxAddr - minAddr + 1;
QByteArray binData(binSize, 0xFF);
foreach (const Section& sec, sections) {
int offset = sec.startAddr - minAddr;
memcpy(binData.data() + offset, sec.data.constData(), sec.data.size());
}
QFile outFile(binFilePath);
if (!outFile.open(QIODevice::WriteOnly)) {
qDebug() << "无法写入.bin文件:" << binFilePath;
return false;
}
outFile.write(binData);
outFile.close();
return true;
}