搜索
bottom↓
回复: 16

(开源-C#)分享一个自己写的HEX2BIN源代码

[复制链接]

出590入992汤圆

发表于 2019-10-15 12:42:44 | 显示全部楼层 |阅读模式
本帖最后由 SUPER_CRJ 于 2019-10-15 12:44 编辑

RT
C#写的,把HEX转换为bin文件。没有用的部分用的是0填充。
大神轻拍。
解决昨天提到的,部分HEX文件没有按照地址顺序排列。
https://www.amobbs.com/thread-5720131-1-1.html
另外:我从网上下载几个HEX2BIN文件都不能解析地址乱的问题,我写的这个可以解决。
(具体思路是:定义一个大数组,数组地址就相当于HEX文件地址,然后进行解析填充,最后再进行截断生成一个bin文件)
(另外有帖子提到,可以先进行HEX地址排序,但是如果存在线性附加地址的话,实现比较麻烦,排序出来可能就乱了。)
可以使用到STM8/STM32生成的HEX生成BIN文件。



  1. s_path = txb_SouceBinPath.Text;

  2.             FileInfo myFile = new FileInfo(s_path);
  3.             string fileExtension = Path.GetExtension(myFile.FullName).ToLower();// 用来获取扩展名,而且变为小写返回,因为扩展名会存在大小写的情况

  4.             if (fileExtension == ".hex")  // 日后会增加各种文件的支持,hex文件的解析需要用点时间
  5.             {
  6.                 FileStream fs;
  7.                 try
  8.                 {
  9.                     fs = new FileStream(s_path, FileMode.Open);  //open file
  10.                 }
  11.                 catch
  12.                 {
  13.                     MessageBox.Show("文件访问错误,请检查是否设置读保护以及文件是否被占用!", "错误");
  14.                     return;
  15.                 }
  16.                 StreamReader HexReader = new StreamReader(fs);    //读取数据流
  17.                 string szLine = "";  // 因为Hex文件是以每行为单位的,所以也就是说读取可以用读取行的方式来操作
  18.                                      //string szHex = "";   // 这个用的是string类别
  19.                 StringBuilder szHex0 = new StringBuilder();  // 比直接读取string要快许多。
  20.                 startAddress = 0xFFFFFFFF;  // 最大的地址,需要一直减小
  21.                 endAddress = 0;  // 最大的地址,需要一直减小
  22.                 UInt32 currentAddress = 0;  // 当前地址,用于严谨的判断:防止地址不连续的时候出现,因为会有人使用Boot+App,然后拼接的形式生成HEX文件,用于下载。
  23.                 UInt32 currentAddressEnd = 0;
  24.                 UInt32 addressPrefix = 0; // 当前地址前缀,因为HEX文件的特性,使得前缀会被另外的放置。
  25.                 while (true)
  26.                 {
  27.                     szLine = HexReader.ReadLine();
  28.                     if (szLine == null) { break; }          //读取完毕,退出
  29.                     if (szLine.Substring(0, 1) == ":")    //判断首字符是”:”,理论是这个是一定会的
  30.                     {
  31.                         switch (szLine.Substring(8, 1))
  32.                         {
  33.                             case "0":  // 数据纪录,表示是数据,注意其中含有2个字节地址。
  34.                                 { // 重点处理
  35.                                     currentAddress = addressPrefix + Convert.ToUInt32(szLine.Substring(3, 4), 16);  // 找到当前的地址。
  36.                                     currentAddressEnd = currentAddress + Convert.ToUInt32(szLine.Substring(1, 2), 16);   //
  37.                                     {
  38.                                         if( currentAddress <= startAddress )
  39.                                         {
  40.                                             startAddress = currentAddress;
  41.                                         }
  42.                                         if( currentAddressEnd >= endAddress )
  43.                                         {
  44.                                             endAddress = currentAddressEnd;
  45.                                         }
  46.                                     }
  47.                                     {  // 进行数据填充
  48.                                         for( int i = (int)currentAddress , j = 0 ; i<currentAddressEnd;i++ ,j++)
  49.                                         {
  50.                                             enoughDataFile[i] = Convert.ToByte(szLine.Substring(9+j*2, 2), 16);
  51.                                         }
  52.                                     }

  53.                                 }
  54.                                 break;
  55.                             case "1":  // 文件线束记录
  56.                                 break;
  57.                             case "4":  // 扩展线性地址记录,这个在STM32中遇到过。
  58.                                 addressPrefix = (UInt32)(Convert.ToUInt16(szLine.Substring(9, szLine.Length - 11), 16) << 16);
  59.                                 break;

  60.                                 // 下面几个都没有遇到过!但是到目前为止,只用上面3个也一直没有出过问题。
  61.                             case "2":  // 扩展段地址记录,这个没有遇到到。
  62.                                        // 这个是<<4位,相对于04的<<8位,这个只移动了一半。
  63.                                 addressPrefix = (UInt32)(Convert.ToUInt16(szLine.Substring(9, szLine.Length - 11), 16) << 4);
  64.                                 break;
  65.                             case "3":  // 开始段地址记录,这个没有遇到过。
  66.                                        // 好像用不到
  67.                                 break;
  68.                             case "5":  // 开始线性地址记录,这个没有遇到过。
  69.                                        // 好像用不到
  70.                                 break;
  71.                             default:  
  72.                                 break;
  73.                         }
  74.                     }
  75.                     else
  76.                     {
  77.                         break;
  78.                     }
  79.                 }
  80.                 { // 关闭文件访问
  81.                     HexReader.Close();
  82.                 }
  83.                
  84.                 {  // 处理截断数据
  85.                     binFileData.Clear();
  86.                     bindataLen = endAddress - startAddress;
  87.                     for (UInt32 i = startAddress; i < endAddress; i++)
  88.                         binFileData.Add(enoughDataFile[i]);

  89.                     byte[] buffer_Temp = new byte[binFileData.Count];
  90.                     for (int tmp0 = 0; tmp0 < binFileData.Count; tmp0++)
  91.                     {
  92.                         buffer_Temp[tmp0] = binFileData[tmp0];
  93.                     }
  94.                     tmpSumValue = GetSumOf16Bit(buffer_Temp, binFileData.Count);
  95.                
  96.                  // 进行显示操作:
  97.                     label4.Text = "0x"+ startAddress.ToString("X");
  98.                     label5.Text = "0x" + endAddress.ToString("X");
  99.                     label6.Text = "0x" + bindataLen.ToString("X");
  100.                     label7.Text = "0x" + tmpSumValue.ToString("X");
  101.                
  102.                 // 进行文件输出操作。
  103.                     FileStream fBin = new FileStream(txb_targetBinPath.Text, FileMode.Create);
  104.                     BinaryWriter BinWrite = new BinaryWriter(fBin);
  105.                     BinWrite.Write(buffer_Temp, 0, buffer_Temp.Length); //
  106.                     BinWrite.Flush();//释放缓存
  107.                     BinWrite.Close();//关闭文件
  108.                     MessageBox.Show("文件转换完成!        ", "提示");
  109.                 }
  110.             }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入362汤圆

发表于 2019-10-15 14:28:13 | 显示全部楼层
直接用各种gcc binutils里附带的objcopy不就完了...

出590入992汤圆

 楼主| 发表于 2019-10-15 14:44:51 | 显示全部楼层
tomzbj 发表于 2019-10-15 14:28
直接用各种gcc binutils里附带的objcopy不就完了...

是真的不会。。。一直写的嵌入式,C#用的都头疼。这个代码正好集成在配置软件里面

出0入362汤圆

发表于 2019-10-15 15:21:16 | 显示全部楼层
SUPER_CRJ 发表于 2019-10-15 14:44
是真的不会。。。一直写的嵌入式,C#用的都头疼。这个代码正好集成在配置软件里面 ...

objcopy是个可执行文件, 运行objcopy -I ihex -O binary xxx.hex xxx.bin, 就完事了.
mingw里有, winavr里有, stm32的各种yagarto/sourcery之类gcc包里也都有, 随便哪个都能用.

出0入12汤圆

发表于 2019-10-15 15:56:18 | 显示全部楼层
记下2楼的objcopy。

出100入113汤圆

发表于 2019-10-15 15:58:24 | 显示全部楼层
如果不需要BIN文件的加密,或者需要添加其他信息,一般编译器可以直接编译生成BIN文件。

出0入0汤圆

发表于 2019-10-25 11:37:19 | 显示全部楼层
多谢分享,回来再弄个加密,给后面IAP用~

出0入0汤圆

发表于 2019-10-25 11:44:14 | 显示全部楼层
楼主有才,我一般是用各种烧录下载软件代替。
例如STC-ISP,打开hex文件,然后另存为bin文件。
并不限于烧录软件本身支持的MCU型号。

出590入992汤圆

 楼主| 发表于 2019-10-25 12:00:23 | 显示全部楼层
health 发表于 2019-10-25 11:44
楼主有才,我一般是用各种烧录下载软件代替。
例如STC-ISP,打开hex文件,然后另存为bin文件。
并不限于烧 ...

因为这个要给别人用,你让他自己转换下,他会觉得麻烦,所以还是写吧。

出0入0汤圆

发表于 2019-10-25 12:43:44 来自手机 | 显示全部楼层
如果遇到空间地址不连续怎么办,新塘的0x0000~0xffff,0x100000~0x1003fff这样你的bin文件怎么处理呢

出590入992汤圆

 楼主| 发表于 2019-10-25 13:18:09 | 显示全部楼层
way2888 发表于 2019-10-25 12:43
如果遇到空间地址不连续怎么办,新塘的0x0000~0xffff,0x100000~0x1003fff这样你的bin文件怎么处理呢 ...

你看我的楼主位说明的方法,这边用的是填充法。没有的地址填充0

出0入0汤圆

发表于 2019-10-25 19:10:41 | 显示全部楼层
SUPER_CRJ 发表于 2019-10-25 13:18
你看我的楼主位说明的方法,这边用的是填充法。没有的地址填充0

要这样填充,那个bin文件就太大了,还是hex格式最灵活

出590入992汤圆

 楼主| 发表于 2019-10-25 20:59:34 | 显示全部楼层
way2888 发表于 2019-10-25 19:10
要这样填充,那个bin文件就太大了,还是hex格式最灵活

bin文件不带有地址信息,除非拆分成两个。

出0入0汤圆

发表于 2019-10-26 03:39:44 来自手机 | 显示全部楼层
SUPER_CRJ 发表于 2019-10-25 20:59
bin文件不带有地址信息,除非拆分成两个。

如果一个文件拆分成2个文件,而且无法自动识别它的地址的时候,只能通过用文件名称来标识分别,这样反而累赘了,这就是我一直用hex格式而不用bin格式的原因了

出0入4汤圆

发表于 2021-1-26 08:54:38 | 显示全部楼层
多谢分享,正在研究HexToBin.

出0入34汤圆

发表于 2021-1-26 10:02:27 | 显示全部楼层
SUPER_CRJ 发表于 2019-10-25 13:18
你看我的楼主位说明的方法,这边用的是填充法。没有的地址填充0

刚看了一下这被挖出来的古文,想建议楼主若可能的话,在于没有用的部分空间应给使用者一个可以输入自订值来进行填充,
或是采用一般预设值的那 0xFF 来填充,因为在于 Flash 或 EPROM 等储存器清为零时就都为 1,故为 Byte 表示时应为 0xFF。
上述仅供楼主参考,谢谢。

出0入0汤圆

发表于 2021-1-26 10:06:26 | 显示全部楼层

多谢分享,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 17:43

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表