BIN,S19,M0T,SREC,HEX文件解析;FileParse(二)之源码解析

一、摘要

1.描述

  • 本文主要描述的是如何通过使用C#解析常用MCU的刷写格式文件,如Bin,S19,Hex,Mot,Serc。
  • 本软编写的语言是基于C#语言,并未使用其他关联的DLL文件,所以不同的电脑之间兼容性很好,不会出现调用异常的问题。
  • 郑重申明,关于实现方法,我也是从网上很多地方学习而来,大家若觉得版权问题可以联系我随时删除。

2.关键字

文件解析,C#,Bin,S19,Hex,Mot,Serc。

二、为何选择C#解析

  • C#解析文件有很多好用的字符串处理函数,不过其实方式方法都一样,只要知道了解析方法,使用任何语言都是一样轻松的。

三、BIN文件解析

		/*-----define---------------------------------*/
        private const int BLOCK_BUFF_LEN = 83886080;
        private const byte MOT_LINE_LEN = 16;
        private const byte HEX_LINE_LEN = 16;
        /*-----enum and struct------------------------*/
        private class DataInfo_Type
        {
            internal int len;
            internal uint startAddr;
            internal uint endAddr;
            internal byte[] buff;
        }
        /*-----variable statement---------------------*/
        private readonly List<DataInfo_Type> g_DataInfos = new List<DataInfo_Type>();
		/***********************************************
          * Name    :PushDataInfo
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private void PushDataInfo(uint? startAddr, uint? endAddr, uint? minStartAddr, uint? maxEndAddr, byte[] p_buff, int len)
        {
            int m = 0; int n = 0;
            if (minStartAddr == null) { minStartAddr = 0; }
            if (maxEndAddr == null) { maxEndAddr = 0xFFFFFFFF; }
            if ((startAddr > maxEndAddr) || (endAddr < minStartAddr)) { return; }
            if (startAddr < minStartAddr) { m = (int)(minStartAddr - startAddr); }
            if (endAddr > maxEndAddr) { n = (int)(endAddr - maxEndAddr); }
            len = len - m - n;
            DataInfo_Type dataInfo = new DataInfo_Type
            {
                len = len,
                startAddr = (uint)(startAddr + m),
                endAddr = (uint)(endAddr - n),
                buff = new byte[len]
            };
            CommonLib.Copy(dataInfo.buff, p_buff, m, len);
            g_DataInfos.Add(dataInfo);
        }
        
		/***********************************************
          * Name    :AnalysisBinFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool AnalysisBinFile(string path, uint? minStartAddr, uint? maxEndAddr)
        {
            try
            {
                FileStream file = new FileStream(path, FileMode.Open);
                int lenth = (int)file.Length;
                if (lenth == 0) { return false; }
                byte[] data = new byte[BLOCK_BUFF_LEN];
                uint? startAddr = minStartAddr;
                if (startAddr == null) { startAddr = 0; }
                uint? endAddr = (uint?)(startAddr + lenth - 1);
                _ = file.Read(data, 0, lenth);
                PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth);
                file.Close();
                return true;
            }
            catch { return false; }
        }

四、BIN文件生成

		/***********************************************
          * Name    :StorageBinFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool StorageBinFile(string path, uint startAddr, byte[] p_buff, int len)
        {
            try
            {
                Stream file = new FileStream(path, FileMode.Create);
                BinaryWriter binWriter = new BinaryWriter(file, Encoding.Unicode);
                binWriter.Write(p_buff, (int)startAddr, len);
                binWriter.Close();
                file.Close();
                return true;
            }
            catch { return false; }
        }

五、S19,M0T,SREC文件解析

		/***********************************************
          * Name    :MotCheckSum
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private byte MotCheckSum(byte[] buff, int len)
        {
            byte ret = 0x00;
            for (int i = 0; i < len; i++) { ret += buff[i]; }
            return (byte)(0xFF - ret);
        }
        
		/***********************************************
          * Name    :AnalysisMotFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool AnalysisMotFile(string path, uint? minStartAddr, uint? maxEndAddr, List<string> ignoreLines)
        {
            int lenth = 0;
            uint? startAddr = null;
            uint? endAddr = null;
            byte[] data = new byte[BLOCK_BUFF_LEN];
            StreamReader reader = new StreamReader(path);
            while (true)
            {
                string line = reader.ReadLine();
                if (line == null) { break; }
                if (line == string.Empty) { continue; }
                if (ignoreLines != null) { foreach (string str in ignoreLines) { if (str == line.Replace(" ", "")) { continue; } } }
                string type = line.Substring(0, 2);
                int len = (line.Length / 2) - 1;
                if (len != (Convert.ToInt32(line.Substring(2, 2), 16) + 1))
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                byte[] buff = new byte[256];
                for (int i = 0; i < len; i++) { buff[i] = Convert.ToByte(line.Substring((i + 1) * 2, 2), 16); }
                if (buff[len - 1] != MotCheckSum(buff, len - 1))
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                uint address;
                switch (type)
                {
                    case "S1":
                        address = 0;
                        address |= ((uint)buff[1]) << 8;
                        address |= ((uint)buff[2]) << 0;
                        if (startAddr == null) { startAddr = address; }
                        if ((endAddr != null) && (address != (endAddr + 1)))
                        {
                            PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth);
                            lenth = 0;
                            startAddr = address;
                        }
                        endAddr = address + (uint)(len - 4) - 1;
                        CommonLib.Copy(data, lenth, buff, 3, len - 4);
                        lenth += len - 4;
                        break;
                    case "S2":
                        address = 0;
                        address |= ((uint)buff[1]) << 16;
                        address |= ((uint)buff[2]) << 8;
                        address |= ((uint)buff[3]) << 0;
                        if (startAddr == null) { startAddr = address; }
                        if ((endAddr != null) && (address != (endAddr + 1)))
                        {
                            PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth);
                            lenth = 0;
                            startAddr = address;
                        }
                        endAddr = address + (uint)(len - 5) - 1;
                        CommonLib.Copy(data, lenth, buff, 4, len - 5);
                        lenth += len - 5;
                        break;
                    case "S3":
                        address = 0;
                        address |= ((uint)buff[1]) << 24;
                        address |= ((uint)buff[2]) << 16;
                        address |= ((uint)buff[3]) << 8;
                        address |= ((uint)buff[4]) << 0;
                        if (startAddr == null) { startAddr = address; }
                        if ((endAddr != null) && (address != (endAddr + 1)))
                        {
                            PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth);
                            lenth = 0;
                            startAddr = address;
                        }
                        endAddr = address + (uint)(len - 6) - 1;
                        CommonLib.Copy(data, lenth, buff, 5, len - 6);
                        lenth += len - 6;
                        break;
                    case "S7":
                    case "S8":
                    case "S9":
                        break;
                    default:
                        break;
                }
            }
            if (lenth != 0) { PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth); }
            reader.Close();
            reader.Dispose();
            return true;
        }

六、S19,M0T,SREC文件生成

		/***********************************************
          * Name    :StorageMotFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool StorageMotFile(string path, uint? startAddr, byte[] p_buff, int len)
        {
            try
            {
                int lenth;
                int block = len / MOT_LINE_LEN;
                byte[] buff = new byte[256];
                if (startAddr == null) { startAddr = 0x00; }
                StreamWriter writeFile = new StreamWriter(path);
                string str = "S011000000486578766965772056312E3038D1";
                writeFile.WriteLine(str);
                if ((len % MOT_LINE_LEN) != 0) { block += 1; }
                byte addrLen = startAddr > 0xFFFFFF ? (byte)4 : (byte)3;
                for (int i = 0; i < block; i++)
                {
                    for (int j = 0; j < addrLen; j++) { buff[j + 1] = (byte)((startAddr + (i * MOT_LINE_LEN)) >> ((addrLen - j - 1) * 8)); }
                    lenth = ((i + 1) * MOT_LINE_LEN) > len ? len - (i * MOT_LINE_LEN) : MOT_LINE_LEN;
                    buff[0] = (byte)(lenth + addrLen + 1);
                    CommonLib.Copy(buff, addrLen + 1, p_buff, MOT_LINE_LEN * i, lenth);
                    buff[lenth + addrLen + 1] = MotCheckSum(buff, lenth + addrLen + 1);
                    str = "S" + Convert.ToString(addrLen - 1, 16);
                    str += CommonLib.ToStr(buff, lenth + addrLen + 2).Replace(" ", "");
                    writeFile.WriteLine(str);
                }
                buff[0] = (byte)(addrLen + 1);
                CommonLib.Fill(buff, 1, 0xFF, 4);
                buff[addrLen + 1] = MotCheckSum(buff, addrLen + 1);
                str = "S" + Convert.ToString(11 - addrLen, 16);
                str += CommonLib.ToStr(buff, addrLen + 2).Replace(" ", "");
                writeFile.WriteLine(str);
                writeFile.Flush();
                writeFile.Close();
                return true;
            }
            catch { return false; }
        }

七、HEX文件解析

		/***********************************************
          * Name    :HexCheckSum
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private byte HexCheckSum(byte[] buff, int len)
        {
            byte ret = 0x00;
            for (int i = 0; i < len; i++) { ret += buff[i]; }
            return (byte)(0x100 - ret);
        }
        
		/***********************************************
          * Name    :AnalysisBinFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool AnalysisHexFile(string path, uint? minStartAddr, uint? maxEndAddr, List<string> ignoreLines)
        {
            int lenth = 0;
            uint? deviationAddr = null;
            uint? startAddr = null;
            uint? endAddr = null;
            byte[] data = new byte[BLOCK_BUFF_LEN];
            StreamReader reader = new StreamReader(path);
            while (true)
            {
                string line = reader.ReadLine();
                if (line == null) { break; }
                if (line == string.Empty) { continue; }
                if (ignoreLines != null) { foreach (string str in ignoreLines) { if (str == line.Replace(" ", "")) { continue; } } }
                if (line.Substring(0, 1) != ":")
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                byte type = Convert.ToByte(line.Substring(7, 2), 16);
                int len = line.Length / 2;
                if (len != (Convert.ToInt32(line.Substring(1, 2), 16) + 5))
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                byte[] buff = new byte[80];
                for (int i = 0; i < len; i++) { buff[i] = Convert.ToByte(line.Substring((i * 2) + 1, 2), 16); }
                if (buff[len - 1] != HexCheckSum(buff, len - 1))
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                switch (type)
                {
                    case 0x00:
                        if (deviationAddr == null) { deviationAddr = 0x00; }
                        uint? address = deviationAddr;
                        address += ((uint)buff[1]) << 8;
                        address += ((uint)buff[2]) << 0;
                        if (startAddr == null) { startAddr = address; }
                        if ((endAddr != null) && (address != (endAddr + 1)))
                        {
                            PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth);
                            lenth = 0;
                            startAddr = address;
                        }
                        endAddr = address + (uint)(len - 5) - 1;
                        CommonLib.Copy(data, lenth, buff, 4, len - 5);
                        lenth += len - 5;
                        break;
                    case 0x01:
                        break;
                    case 0x02:
                        deviationAddr = 0x00;
                        for (int i = 0; i < len - 5; i++)
                        {
                            deviationAddr <<= 8;
                            deviationAddr += buff[i + 4];
                        }
                        deviationAddr <<= 4;
                        break;
                    case 0x03:
                        break;
                    case 0x04:
                        deviationAddr = 0x00;
                        for (int i = 0; i < len - 5; i++)
                        {
                            deviationAddr <<= 8;
                            deviationAddr += buff[i + 4];
                        }
                        deviationAddr <<= 16;
                        break;
                    case 0x05:
                        break;
                    default:
                        break;
                }
            }
            if (lenth != 0) { PushDataInfo(startAddr, endAddr, minStartAddr, maxEndAddr, data, lenth); }
            reader.Close();
            reader.Dispose();
            return true;
        }

八、HEX文件生成

		/***********************************************
          * Name    :StorageHexFile
          * Author  :WangHu
          * Function:***
          * Version :V1.0.0
          * Data    :2022.5.20
        ***********************************************/
        private bool StorageHexFile(string path, uint? startAddr, byte[] p_buff, int len)
        {
            try
            {
                ushort? address = null;
                uint? deviationAddr = null;
                int block = len / HEX_LINE_LEN;
                byte[] buff = new byte[256];
                if (startAddr == null) { startAddr = 0x00; }
                StreamWriter writeFile = new StreamWriter(path);
                if ((len % HEX_LINE_LEN) != 0) { block += 1; }
                string str;
                for (int i = 0; i < block; i++)
                {
                    if ((address == null) || (address == 0x00))
                    {
                        buff[0] = 0x02;
                        buff[1] = 0x00;
                        buff[2] = 0x00;
                        buff[3] = startAddr > 0xFFFFF ? (byte)4 : (byte)2;
                        if (buff[3] == 2)
                        {
                            buff[4] = (byte)(startAddr >> 12);
                            buff[5] = (byte)(startAddr >> 4);
                            deviationAddr = startAddr & 0xFFFFFFF0;
                        }
                        if (buff[3] == 4)
                        {
                            buff[4] = (byte)(startAddr >> 24);
                            buff[5] = (byte)(startAddr >> 16);
                            deviationAddr = startAddr & 0xFFFF0000;
                        }
                        buff[6] = HexCheckSum(buff, 6);
                        str = ":" + CommonLib.ToStr(buff, 7).Replace(" ", "");
                        writeFile.WriteLine(str);
                        address = (ushort)(startAddr - deviationAddr);
                    }
                    buff[1] = (byte)(address >> 8);
                    buff[2] = (byte)(address >> 0);
                    buff[3] = 0x00;

                    int lenth = ((i + 1) * HEX_LINE_LEN) > len ? len - (i * HEX_LINE_LEN) : HEX_LINE_LEN;
                    buff[0] = (byte)lenth;
                    address += (ushort)lenth;
                    startAddr += (uint)lenth;
                    CommonLib.Copy(buff, 4, p_buff, HEX_LINE_LEN * i, lenth);
                    buff[lenth + 4] = HexCheckSum(buff, lenth + 4);
                    str = ":" + CommonLib.ToStr(buff, lenth + 5).Replace(" ", "");
                    writeFile.WriteLine(str);
                }
                str = ":00000001FF";
                writeFile.WriteLine(str);
                writeFile.WriteLine("");
                writeFile.Flush();
                writeFile.Close();
                return true;
            }
            catch { return false; }
        }

九、源码下载

十、其他

本文主要是讲解BIN,S19,M0T,SREC,HEX文件解析,后续章节会对源码的内容进行讲解,方便新手查询,有些地方可能会有描述性的错误,希望看到的朋友及时指出,我会及时更正错误,其他地方有些借鉴的描述,写此文章的目的是为了交流,非商业用途,欢迎私信讨论,感谢大家阅读。

十一、参考

【1】:S19文件格式详解
【2】:HEX文件格式详解

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值