背景

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

转换逻辑

Hex文件格式:(以下对着hex文件一看便知)
【1】Hex是文本文件,所有数据都是以字符串方式读取
【2】文件有若干行字符串数据,每行都采用如下的固定格式
MARK | LEN | OFFSET | TYPE | DATA | CHKSUM
【2.1】MARK 即起始符,以“:”开始,以”rn”结尾
【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结束。
我们就按照这种逻辑实现binhex

实现方法

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
Hex文件开头
如下是实现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") + "rn";
    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") + "rn";
    return ret;
}

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

Over

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

原文地址:https://blog.csdn.net/weixin_38743772/article/details/134684346

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_10801.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注