C# 生成命令行程序 将hex格式烧录程序转换成bin烧录格式

1.程序

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Hex2Bin
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2 || args.Length > 3)
            {
                ShowHelp();
                return;
            }

            string inputFile = args[0];
            string outputFile = args[1];
            long startOffset = 0;
            long endOffset = long.MaxValue;

            // 处理可选的偏移参数
            if (args.Length == 3)
            {
                if (!long.TryParse(args[2], System.Globalization.NumberStyles.HexNumber, null, out startOffset))
                {
                    Console.WriteLine("错误:无效的偏移地址格式");
                    return;
                }
                endOffset = long.MaxValue;
            }

            try
            {
                ConvertHexToBin(inputFile, outputFile, startOffset, endOffset);
                Console.WriteLine($"转换成功!输出文件:{outputFile}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"错误:{ex.Message}");
            }
        }

        static void ShowHelp()
        {
            Console.WriteLine("Hex2Bin - Intel HEX 转 BIN 格式转换工具");
            Console.WriteLine("用法:Hex2Bin <输入文件.hex> <输出文件.bin> [起始偏移地址]");
            Console.WriteLine("示例:");
            Console.WriteLine("  Hex2Bin firmware.hex firmware.bin");
            Console.WriteLine("  Hex2Bin firmware.hex firmware.bin 1000    // 从0x1000开始提取");
        }

        static void ConvertHexToBin(string hexFile, string binFile, long startOffset, long endOffset)
        {
            var dataSegments = new Dictionary<long, byte>();
            long minAddr = long.MaxValue;
            long maxAddr = long.MinValue;
            long currentSegmentAddr = 0;
            long extendedLinearAddr = 0;
            long extendedSegmentAddr = 0;

            string[] lines = File.ReadAllLines(hexFile);
            
            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line) || line[0] != ':')
                    continue;

                // 解析HEX行
                byte byteCount = Convert.ToByte(line.Substring(1, 2), 16);
                ushort address = Convert.ToUInt16(line.Substring(3, 4), 16);
                byte recordType = Convert.ToByte(line.Substring(7, 2), 16);
                string dataString = line.Substring(9, byteCount * 2);
                byte checksum = Convert.ToByte(line.Substring(9 + byteCount * 2, 2), 16);

                // 验证校验和
                byte calcChecksum = 0;
                calcChecksum += byteCount;
                calcChecksum += (byte)(address >> 8);
                calcChecksum += (byte)(address & 0xFF);
                calcChecksum += recordType;
                for (int i = 0; i < byteCount; i++)
                {
                    calcChecksum += Convert.ToByte(dataString.Substring(i * 2, 2), 16);
                }
                calcChecksum = (byte)((~calcChecksum + 1) & 0xFF);
                
                if (calcChecksum != checksum)
                {
                    throw new Exception($"校验和错误:行 {line}");
                }

                // 计算实际地址
                long actualAddress;
                switch (recordType)
                {
                    case 0x00: // 数据记录
                        actualAddress = extendedLinearAddr + address;
                        if (extendedSegmentAddr != 0)
                            actualAddress = (extendedSegmentAddr << 4) + address;
                        
                        // 存储数据
                        for (int i = 0; i < byteCount; i++)
                        {
                            byte data = Convert.ToByte(dataString.Substring(i * 2, 2), 16);
                            long addr = actualAddress + i;
                            
                            if (addr >= startOffset && addr <= endOffset)
                            {
                                if (!dataSegments.ContainsKey(addr))
                                    dataSegments[addr] = data;
                                
                                if (addr < minAddr) minAddr = addr;
                                if (addr > maxAddr) maxAddr = addr;
                            }
                        }
                        break;
                        
                    case 0x01: // EOF
                        break;
                        
                    case 0x02: // 扩展段地址
                        extendedSegmentAddr = Convert.ToUInt16(dataString, 16);
                        break;
                        
                    case 0x03: // 起始段地址
                        // 忽略
                        break;
                        
                    case 0x04: // 扩展线性地址
                        extendedLinearAddr = Convert.ToUInt32(dataString, 16) << 16;
                        extendedSegmentAddr = 0;
                        break;
                        
                    case 0x05: // 起始线性地址
                        // 忽略
                        break;
                }
            }

            if (dataSegments.Count == 0)
            {
                throw new Exception("没有找到有效的数据记录");
            }

            // 创建连续的数据缓冲区
            long totalSize = maxAddr - minAddr + 1;
            byte[] binData = new byte[totalSize];
            
            // 填充数据
            foreach (var kvp in dataSegments)
            {
                binData[kvp.Key - minAddr] = kvp.Value;
            }

            // 写入BIN文件
            File.WriteAllBytes(binFile, binData);
            
            Console.WriteLine($"转换统计:");
            Console.WriteLine($"  起始地址:0x{minAddr:X8}");
            Console.WriteLine($"  结束地址:0x{maxAddr:X8}");
            Console.WriteLine($"  数据大小:{totalSize} 字节");
        }
    }
}

2. 使用方法

cs 复制代码
# 基本用法
Hex2Bin.exe input.hex output.bin

# 指定起始地址(十六进制)
Hex2Bin.exe input.hex output.bin 1000

# 显示帮助
Hex2Bin.exe

3.程序特点

  1. 支持标准Intel HEX格式

    • 数据记录(00)

    • 文件结束记录(01)

    • 扩展段地址(02)

    • 扩展线性地址(04)

    • 起始地址记录(03, 05)

  2. 校验和验证:每行HEX数据都会验证校验和

  3. 地址范围过滤:可选的起始地址参数

  4. 内存高效:使用字典存储非连续数据段

4.使用示例

假设有HEX文件内容:

bash 复制代码
:100000000102030405060708090A0B0C0D0E0F101A
:100010001112131415161718191A1B1C1D1E1F2029
:00000001FF

转换后的BIN文件将包含地址0x0000-0x001F的32字节数据。

这个工具适用于嵌入式开发中常见的固件格式转换需求。

相关推荐
Mortalbreeze1 小时前
C++11类的新特性:移动语义、default、delete、override详解
开发语言·c++
xiaoshuaishuai81 小时前
C# 封装与继承
开发语言·c#
FL16238631291 小时前
基于C#winform使用纯opencv部署ppocrv5和ppocrv6的onnx模型进行OCR文件检测识别
opencv·c#·ocr
不脱发的程序猿2 小时前
DLL文件缺失怎么办?
单片机·嵌入式硬件·嵌入式
星辰_mya2 小时前
限流、漏斗桶和令牌桶的区别
java·开发语言·面试·架构·高并发
Shadow(⊙o⊙)2 小时前
信号1.0,信号概念、signal()处理、前后台进程、闹钟设置、初识信号三张表。
linux·运维·服务器·开发语言·c++
(Charon)2 小时前
【C++ 面试高频:STL 容器 vector、map、unordered_map 总结】
开发语言·c++·面试
我是一颗柠檬2 小时前
【Java项目技术亮点】滑动窗口限流算法
java·开发语言·算法
于指尖飞舞2 小时前
java后端面试题(jvm极简)
java·开发语言·jvm