http://www.cppblog.com/Lee7/archive/2007/12/21/39231.html
Intel HEX文件是记录文本行的 ASCII 文本文件,在 Intel HEX 文件中,每一行是一个 HEX 记录,由十六进制数组成的机器码或 者数据常量。 Intel HEX 文件经常被用于将程序或数据传输存储到 ROM 、 EPROM , 大多数编程器和模拟器使用 Intel HEX 文件。
很多编译器的支持生成 HEX 格 式的烧录文件,尤其是 Keil c 。但是编程器能够下载的往往是 BIN 格 式,因此 HEX 转 BIN 是每个编程器都必须 支持的功能。
HEX 格式文件以行为单位, 每行由“:”( 0x3a )开始,以回车键结束 (0x0d,0x0a) 。 行内的数据都是由两个字 符表示一个 16 进制字节,比如 ”01” 就表 示数 0x01 ; ”0a” ,就表示 0x0a 。 对于 16 位 的地址,则高位在前低位在后,比如地址 0x010a ,在 HEX 格 式文件中就表示为字符串 ”010a” 。 下面为 HEX 文件中的一行:
:10000000FF0462FF051EFF0A93FF0572FF0A93FFBC
“:”表示一行的开始。
“:” 后的第 1 , 2 个 字符“ 10 ” 表 示本行包含的数据的长度,这里就是 0x10 即 16 个。
第 3 , 4 , 5 , 6 个 字符“ 0000 ” 表 示数据存储的起始地址,这里表示从 0x0000 地址开始存储 16 个 数据,其中高位地址在前,低位地址在后。
第 7 , 8 个 字符“ 00 ” 表 示数据的类型。该类型总共有以下几种:
00 ---- 数据记录
01 ---- 文 件结束记录
02 ---- 扩展段地址记录
04 ---- 扩展线性地址记录
这里就是 0x00 即 为普通数据记录。
自后的 32 个字符就是本行包含的数据, 每两个字符表示一个字节数据,总共有 16 个 字节数据跟行首的记录的长度相一致。
最后两个字符表示校验码。
每个 HEX 格 式的最后一行都是固定为:
:00000001FF
以上的信息其实就足够进行 HEX 转 BIN 格 式的程序的编写。首先我们只处理数据类型为 0x00 及 0x01 的 情况。 0x02 表示对应的存储地址超过了 64K , 由于我的编程器只针对 64K 以下的单片机,因此在次不处理, 0x04 也 是如此。
我的编程思路是从文件中一个一个 读出字符,根据“:”判断一行的 开始,然后每两个字符转换成一个字节,并解释其对应的意义。然后将数据从该行中剥离出来保存到缓冲区中,并最终输出到文件中。
具体程序如下,该程序在 VC2005 下 采用控制台项目编译,需要在 release 下编译,在 debug 模 式中会提示一个 dll 文件无法找到,这可能是 VC 自 身的错误。
// hextobin.cpp : 定义控制台应用程序的入口点。
//
1
#include
"
stdafx.h
"
2
3
#include
<
malloc.h
>
4
5
#include
<
memory.h
>
6
7
typedef unsigned
char
BYTE;8
9
10
11
//
将两个字符转化为一个字节量
12
13
void
CharToByte(
char
*
pChar,BYTE
*
pByte)14
15
{16
17
char h,l;18
19
h = pChar[ 0 ]; // 高位 20
21
l = pChar[ 1 ]; // 低位 22
23
if (l >= ' 0 ' && l <= ' 9 ' )24
25
l = l - ' 0 ' ;26
27
else if (l >= ' a ' && l <= ' f ' )28
29
l = l - ' a ' + 0xa ;30
31
else if (l >= ' A ' && l <= ' F ' )32
33
l = l - ' A ' + 0xa ;34
35
if (h >= ' 0 ' && h <= ' 9 ' )36
37
h = h - ' 0 ' ;38
39
else if (h >= ' a ' && h <= ' f ' )40
41
h = h - ' a ' + 0xa ;42
43
else if (h >= ' A ' && h <= ' F ' )44
45
h = h - ' A ' + 0xa ;46
47
* pByte = (BYTE)h * 16 + l;48
49
}
50
51
52
53
int
_tmain(
int
argc, _TCHAR
*
argv[])54
55
{56
57
char fileName[ 100 ];58
59
char data[ 2 ];60
61
BYTE * outBuf;62
63
FILE * myFile;64
65
int len;66
67
int i;68
69
BYTE adressHigh;70
71
BYTE adressLow;72
73
BYTE dataLen;74
75
BYTE dataType; 76
77
BYTE byteData;78
79
int totalLen;80
81
totalLen = 0 ;82
83
len = 0 ;84
85
adressHigh = 0 ;86
87
adressLow = 0 ;88
89
dataLen = 0 ;90
91
dataType = 0 ;92
93
printf( " 请 输入HEX格式文件名: " );94
95
scanf_s( " %s " ,fileName);96
97
printf( " /n " );98
99
if (fopen_s( & myFile,fileName, " r " ) != 0 )100
101
{102
103
printf( " 打 开文件%s失败! " ,fileName);104
105
} 106
107
// 将文件长度计算出来用于申请存储数据的缓冲区 108
109
while ( ! feof(myFile))110
111
{112
113
++ len;114
115
fgetc(myFile);116
117
} 118
119
rewind(myFile);120
121
// 因为是每两个字符表示一个字节,所以最大的数据个数要少于文件字符个数的一半 122
123
outBuf = (BYTE * )malloc(len / 2 );124
125
memset(outBuf, 0xff ,len / 2 );126
127
while ( ! feof(myFile))128
129
{130
131
// :号表示一行的开始 132
133
if (fgetc(myFile) == ' : ' )134
135
{136
137
// 一行的头两个字符表示该行包含的数据长度 138
139
data[ 0 ] = fgetc(myFile);140
141
data[ 1 ] = fgetc(myFile);142
143
CharToByte(data, & dataLen);144
145
// 一行的第、个字符表示数据存储起始地址的高位 146
147
data[ 0 ] = fgetc(myFile);148
149
data[ 1 ] = fgetc(myFile);150
151
CharToByte(data, & adressHigh);152
153
// 一行的第、个字符表示数据存储起始地址的低位 154
155
data[ 0 ] = fgetc(myFile);156
157
data[ 1 ] = fgetc(myFile);158
159
CharToByte(data, & adressLow);160
161
// 一行的第、个字符表示数据类型 162
163
data[ 0 ] = fgetc(myFile);164
165
data[ 1 ] = fgetc(myFile);166
167
CharToByte(data, & dataType);168
169
// 当数据类型为时,表示本行包含的是普通数据记录 170
171
if (dataType == 0x00 )172
173
{174
175
for (i = 0 ;i < dataLen;i ++ )176
177
{178
179
data[ 0 ] = fgetc(myFile);180
181
data[ 1 ] = fgetc(myFile);182
183
CharToByte(data, & byteData);184
185
outBuf[adressHigh * 256 + adressLow + i] = byteData;186
187
} 188
189
totalLen += dataLen;190
191
} 192
193
// 当数据类型为时,表示到了最后一行 194
195
if (dataType == 0x01 )196
197
{198
199
printf( " 文 件结束记录! " );200
201
} 202
203
// 当数据类型为时,表示本行包含的是扩展段地址记录 204
205
if (dataType == 0x02 )206
207
{208
209
printf( " 不 支持扩展段地址记录! " );210
211
return 0 ;212
213
} 214
215
// 当数据类型为时,表示本行包含的是扩展线性地址记录 216
217
if (dataType == 0x04 )218
219
{220
221
printf( " 不 支持扩展线性地址记录! " );222
223
return 0 ;224
225
} 226
227
} 228
229
} 230
231
fclose(myFile);232
233
printf( " 请 输入保存的BIN格式文件名: " );234
235
scanf_s( " %s " ,fileName);236
237
if (fopen_s( & myFile,fileName, " w " ) != 0 )238
239
{240
241
printf( " 打 开文件%s失败! " ,fileName);242
243
} 244
245
for (i = 0 ;i < totalLen;i ++ )246
247
{248
249
fputc(outBuf[i],myFile);250
251
} 252
253
return 0 ;254
255
}
256
posted on 2007-12-21 17:15
4492

被折叠的 条评论
为什么被折叠?



