using System;
using System.IO;
using System.Windows.Forms;
using System.Globalization;
//hex文件格式详细说明
//1
//推荐QUESTION
//What is the Intel HEX file format?
//ANSWER
//The Intel HEX file is an ASCII text file with lines of text that follow the
//Intel HEX file format. Each line in an Intel HEX file contains one HEX record.
//These records are made up of hexadecimal numbers that represent machine
//language code and/or constant data. Intel HEX files are often used to transfer
//the program and data that would be stored in a ROM or EPROM. Most EPROM
//programmers or emulators can use Intel HEX files.
//Record Format
//An Intel HEX file is composed of any number of HEX records. Each record is made
//up of five fields that are arranged in the following format:
//:llaaaatt[dd...]cc
//Each group of letters corresponds to a different field, and each letter
//represents a single hexadecimal digit. Each field is composed of at least two
//hexadecimal digits-which make up a byte-as described below:
//: is the colon that starts every Intel HEX record.
//ll is the record-length field that represents the number of data bytes (dd) in
//the record.
//aaaa is the address field that represents the starting address for subsequent
//data in the record.
//tt is the field that represents the HEX record type, which may be one of the
//following:
//00 - data record
//01 - end-of-file record
//02 - extended segment address record
//04 - extended linear address record
//dd is a data field that represents one byte of data. A record may have multiple
//data bytes. The number of data bytes in the record must match the number
//specified by the ll field.
//cc is the checksum field that represents the checksum of the record. The
//checksum is calculated by summing the values of all hexadecimal digit pairs in
//the record modulo 256 and taking the two's complement.
//Data Records
//The Intel HEX file is made up of any number of data records that are terminated
//with a carriage return and a linefeed. Data records appear as follows:
//:10246200464C5549442050524F46494C4500464C33
//where:
//10 is the number of data bytes in the record.
//2462 is the address where the data are to be located in memory.
//00 is the record type 00 (a data record).
//464C...464C is the data.
//33 is the checksum of the record.
//Extended Linear Address Records (HEX386)
//Extended linear address records are also known as 32-bit address records and
//HEX386 records. These records contain the upper 16 bits (bits 16-31) of the
//data address. The extended linear address record always has two data bytes and
//appears as follows:
//:02000004FFFFFC
//where:
//02 is the number of data bytes in the record.
//0000 is the address field. For the extended linear address record, this field
//is always 0000.
//04 is the record type 04 (an extended linear address record).
//FFFF is the upper 16 bits of the address.
//FC is the checksum of the record and is calculated as
//01h + NOT(02h + 00h + 00h + 04h + FFh + FFh).
//When an extended linear address record is read, the extended linear address
//stored in the data field is saved and is applied to subsequent records read
//from the Intel HEX file. The linear address remains effective until changed by
//another extended address record.
//The absolute-memory address of a data record is obtained by adding the address
//field in the record to the shifted address data from the extended linear
//address record. The following example illustrates this process..
//Address from the data record's address field 2462
//Extended linear address record data field FFFF
// --------
//Absolute-memory address FFFF2462
//Extended Segment Address Records (HEX86)
//Extended segment address records-also known as HEX86 records-contain bits 4-19
//of the data address segment. The extended segment address record always has two
//data bytes and appears as follows:
//:020000021200EA
//where:
//02 is the number of data bytes in the record.
//0000 is the address field. For the extended segment address record, this field
//is always 0000.
//02 is the record type 02 (an extended segment address record).
//1200 is the segment of the address.
//EA is the checksum of the record and is calculated as
//01h + NOT(02h + 00h + 00h + 02h + 12h + 00h).
//When an extended segment address record is read, the extended segment address
//stored in the data field is saved and is applied to subsequent records read
//from the Intel HEX file. The segment address remains effective until changed by
//another extended address record.
//The absolute-memory address of a data record is obtained by adding the address
//field in the record to the shifted-address data from the extended segment
//address record. The following example illustrates this process.
//Address from the data record's address field 2462
//Extended segment address record data field 1200
// --------
//Absolute memory address 00014462
//End-of-File (EOF) Records
//An Intel HEX file must end with an end-of-file (EOF) record. This record must
//have the value 01 in the record type field. An EOF record always appears as
//follows:
//:00000001FF
//where:
//00 is the number of data bytes in the record.
//0000 is the address where the data are to be located in memory. The address in
//end-of-file records is meaningless and is ignored. An address of 0000h is
//typical.
//01 is the record type 01 (an end-of-file record).
//FF is the checksum of the record and is calculated as
//01h + NOT(00h + 00h + 00h + 01h).
//Example Intel HEX File
//Following is an example of a complete Intel HEX
//:10001300AC12AD13AE10AF1112002F8E0E8F0F2244
//:10000300E50B250DF509E50A350CF5081200132259
//:03000000020023D8
//:0C002300787FE4F6D8FD7581130200031D
//:10002F00EFF88DF0A4FFEDC5F0CEA42EFEEC88F016
//:04003F00A42EFE22CB
//:00000001FF
//Hex文件的INTEL格式:这是Intel公司提出的按地址排列的数据信息,数据宽度为字节,所有数
//据使用16进制数字表示.
//这是一个例子:
//:10008000AF5F67F0602703E0322CFA92007780C361
//:1000900089001C6B7EA7CA9200FE10D2AA00477D81
//:0B00A00080FA92006F3600C3A00076CB
//:00000001FF
//第一行,":"符号表明记录的开始. 后面的两个字符表明记录的长度,这里是10h. 后面的四个字
//符给出调入的地址,这里是0080h. 后面的两个字符表明记录的类型;
//0 数据记录 1 记录文件结束 2 扩展段地址记录 3 开始段地址记录 4 扩展线性地址记录 5
//开始线性地址记录
//后面则是真正的数据记录, 最后两位是校验和检查,它加上前面所有的数据和为0.
//最后一行特殊,总是写成这个样子.
//扩展Intel Hex的格式(最大1M): 由于普通的Intel的Hex记录文件只能记录64K的地址范围,
//所以大于64K的地址数据要靠扩展Intel Hex格式的文件来记录.对于扩展形式Hex文件,在每
//一个64K段的开始加上扩展的段地址规定,下面的数据地址均在这个段内,除非出现新的段地址
//定义.
//一个段地址 定义的格式如下:
//起始符 长度 起始地址 扩展段标示 扩展段序号 无用 累加和
//: 02 0000 02 3000 EC
//段地址的标识符是第四组数据02,表示扩展地址段的定义,再后面的以为HEX数表示段的数目,
//上面的定义为3,表示段地址是3,所以下面的数据地址是3 + XX(XX是64K段内的地址)
namespace demo
{
class BMU_Hex2Bin
{
public byte[] hex2BinByte(String szHexPath, String szBinPath)
{
Int32 i = 0;
Int32 j = 0;
Int32 maxAddr = 0; //HEX文件的最大地址
Int32 segAddr = 0; //段地址
byte[] szBin = null;
try
{
String szLine = "";
String szHex = "";
StreamReader HexReader = new StreamReader(szHexPath);
//先找出HEX文件的最大地址
while (true)
{
szLine = HexReader.ReadLine(); //读取一行数据
i++;
if (szLine == null) //读完所有行
{
break;
}
if (szLine.Substring(0, 1) == ":") //判断第1字符是否是:
{
if (szLine.Substring(1, 8) == "00000001")//数据结束,所有的Hex文件均是统一的格式
{
break;
}
// if (szLine.Substring(7, 2) == "02")//查看是否有扩展线性地址出现,在BMU的HEX文件中是不会出现此扩展地址的。
// {
// segAddr = Int32.Parse(szLine.Substring(9, 4), NumberStyles.HexNumber);
// segAddr *= 16;
// }
if (szLine.Substring(7, 2) == "04")//查看是否有扩展线性地址出现,在BMU的HEX文件中是不会出现此扩展地址的。
{
segAddr = Int32.Parse(szLine.Substring(9, 4), NumberStyles.HexNumber);
if (segAddr == 0x01)
segAddr = 0x10000;
else
{
segAddr = 0;
}
}
else if (szLine.Substring(7, 2) == "00")//大部分均是此
{
Int32 tmp;
Int32 tmpAddr = Int32.Parse(szLine.Substring(3, 4), NumberStyles.HexNumber);
tmpAddr += UInt16.Parse(szLine.Substring(1, 2), NumberStyles.HexNumber);
tmp = tmpAddr;
tmpAddr = tmp + segAddr;
if (tmpAddr > maxAddr)
maxAddr = tmpAddr;
}
}
}
//新建一个二进制文件,填充为0XFF
szBin = new byte[maxAddr];
for (i = 0; i < maxAddr; i++)
szBin[i] = 0XFF;
//返回文件开头
HexReader.BaseStream.Seek(0, SeekOrigin.Begin);
HexReader.DiscardBufferedData();//不加这句不能正确返回开头
segAddr = 0;
//根据hex文件地址,填充bin文件
while (true)
{
szLine = HexReader.ReadLine(); //读取一行数据
if (szLine == null) //读完所有行
{
break;
}
if (szLine.Substring(0, 1) == ":") //判断第1字符是否是:
{
if (szLine.Substring(1, 8) == "00000001")//数据结束
{
break;
}
if (szLine.Substring(7, 2) == "04")//查看是否有扩展线性地址出现,在BMU的HEX文件中是不会出现此扩展地址的。
{
segAddr = Int32.Parse(szLine.Substring(9, 4), NumberStyles.HexNumber);
if (segAddr == 0x01)
segAddr = 0x10000;
else
{
segAddr = 0;
}
}
if (szLine.Substring(7, 2) == "00")
{
int tmpAddr = Int32.Parse(szLine.Substring(3, 4), NumberStyles.HexNumber);
int num = Int16.Parse(szLine.Substring(1, 2), NumberStyles.HexNumber);
tmpAddr += segAddr;
j = 0;
for (i = 0; i < num; i++)
{
szBin[tmpAddr++] = (byte)Int16.Parse(szLine.Substring(j + 9, 2), NumberStyles.HexNumber);
j += 2;
}
}
}
}
HexReader.Close(); //关闭目标文件
/*
if (szBinPath == "")
{
szBinPath = Path.ChangeExtension(szHexPath, "bin");
//tbBinPath.Text = szBinPath;
}
FileStream fBin = new FileStream(szBinPath, FileMode.Create); //创建文件BIN文件
BinaryWriter BinWrite = new BinaryWriter(fBin); //二进制方式打开文件
BinWrite.Write(szBin, 0, maxAddr); //写入数据
BinWrite.Flush();//释放缓存
BinWrite.Close();//关闭文件
string tmp = "文件转换完成! 文件大小: ";
tmp += maxAddr.ToString();
tmp += "字节";
MessageBox.Show(tmp, "提示");
*/
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
MessageBox.Show("Hex File Format damaged!","ERROR");
}
return szBin;
}
}
}
07-27
05-11