C# 将bin文件转成hex文件

背景

由于项目应用(服务器-APP-下位机)中,
1)服务器限制只能上传hex文件
2)APP中通过应用读取的数据为bin文件
所以需要APP中将bin文件转成hex文件,,正好做个bin转hex的功能
注:应用读取的bin文件实际是MCU的存放在Flash中的数据

转换逻辑

Hex文件格式:(以下对着hex文件一看便知)
【1】Hex是文本文件,所有数据都是以字符串方式读取
【2】文件有若干行字符串数据,每行都采用如下的固定格式:
MARK | LEN | OFFSET | TYPE | DATA | CHKSUM
【2.1】MARK 即起始符,以“:”开始,以"\r\n"结尾
【2.2】LEN,即本行有效数据的长度
【2.3】OFFSET,即地址偏移量
【2.4】TYPE,即类型,
Hex文件起源于英特尔定义的Inter Hex文件,每行数据被称为一条数据记录,TYPE也就是本行数据记录的类型
04,表示扩展地址记录
00,表示数据记录,真正的有效数据
01,文件结束标志
【2.5】DATA,有效数据
【2.6】CHKSUM,单字节的校验和

我们可以任意打开一个keil工程生成的hex文件进行查看:
基本只用了3种数据记录类型:
开始是04写地址,然后是00写数据,00写满65536字节时 - 地址递增重新写地址然后继续写数据,最后是01结束。
我们就按照这种逻辑实现bin转hex。

实现方法

1、获取bin文件路径,新建一个相同文件名的Hex文件

string fileName = System.IO.Path.GetFileName(path);
string write_path = path.Replace(".bin", ".hex");

2、用FileStream读取bin文件数据,用StreamWriter写字符串到Hex文件

byte[] read_buf = new byte[16];
int read_num, offset = 0;

FileStream f_read = File.OpenRead(path);//打开文件 准备读取
StreamWriter s_write = File.CreateText(write_path);//新建文件 进行写入

//写入首地址
//例如芯片为XMC4500 存放数据的地址为0x0C08 0000,则写入地址为0C08,也即地址的地址单位是0x10000 = 65536个字节
s_write.Write(WriteExternAddr(address));

//读取数据,每次读取16个字节,读不够16字节表明文件读完了
read_num = f_read.Read(read_buf, 0, 16);

while (read_num == 16)
{
	//将读取到的数据和索引组成数据记录写入文件
    s_write.Write(WriteDataRecord((UInt16)offset, read_buf, read_num));
    offset += 16;

    if (offset >= 65536)
    {
        offset = 0;
        address += 1;
        //读取超过65536字节,地址递增,索引置0,写入地址记录
        s_write.Write(WriteExternAddr(address));
    }

	//继续读取
    read_num = f_read.Read(read_buf, 0, 16);
}

//写入剩余字节
if (read_num  > 0)
{
    s_write.Write(WriteDataRecord((UInt16)offset, read_buf, read_num));
}

//写入结束记录
s_write.Write(WriteEndRecord());
s_write.Flush();

//关闭文件
s_write.Close();
f_read.Close();

3、数据记录的写入接口实现

1)写入地址记录
如下图,“ :020000040801F1 ” 即地址记录
:开头
02 表示有效长度为2 对应数据 0801
0000 地址记录中索引固定为 0000
04 即类型,表示本条为地址记录
0801 有效数据 表示地址为0x0801 0000
F1 为校验值,计算方法如下:(hex文件每行的校验值的计算方法都是如此)
Sum = 02 + 04 + 08 + 01 = 0x0F
Sum = 0xFF - Sum + 1 = 0xF1
C# 将bin文件转成hex文件_第1张图片
如下是实现2章节代码里的方法
简单总结:
1、写地址记录
可变参数只有地址,传参为无符号16位类型
2、写数据记录
传参有 有效数据长度 、偏移量 和有效数据
3、写结束记录
完全固定

private static string WriteExternAddr(UInt16 address)//写扩展地址记录
{
    byte sum = (byte)(2 + 4 + address / 256 + address % 256);
    sum = (byte)(0xff - sum);
    sum = (byte)(sum + 1);
    string ret = ":02000004" + address.ToString("X4") + sum.ToString("X2") + "\r\n";
    return ret;
}

private static string WriteDataRecord(UInt16 offset, byte[] bytes, int length)//写数据记录
{
    string ret = ":" + length.ToString("X2") + offset.ToString("X4") + "00";
    //byte sum = (byte)(length + offset / 256 + offset % 256);
    byte sum = (byte)(length);
    sum += (byte)(offset >> 8);
    sum += (byte)(offset & 0xFF);
    for (int i = 0; i < length; i++)
    {
        sum += bytes[i];
        ret += bytes[i].ToString("X2");
    }
    sum = (byte)(0xff - sum);
    sum = (byte)(sum + 1);
    ret += sum.ToString("X2") + "\r\n";
    return ret;
}

private static string WriteEndRecord() //写终止序列
{
    string ret = ":00000001FF\r\n";
    return ret;
}

Over

在STM32/GD32/XMC4500这种单片机中,读取Flash原始数据,保存为bin文件。
再实现按钮和文件选择框,将该bin文件转成hex文件,和keil生产的完全一致。
但是,该例子只用于地址连续的数据,比如还有地址分段的数据或者多个bin文件或地址,组成一个hex文件,需要自己再去封装逻辑了。

你可能感兴趣的:(C#,c#,开发语言)