bin⽂件转换为hex⽂件C语⾔实现
对于嵌⼊式⽽⾔,hex⽂件可能⼤家再熟悉不过了,对,我们⼤学时学习的51单⽚机编写的代码在keil上编译后就⽣成了hex⽂件。那bin⽂件⼜是什么意思呢,它⼜和hex⽂件的区别在哪?这也不是本⽂的重点,下⾯简单的描述下:
最通俗的来讲,hex是带地址的,⽤下载器下载时,不需要设置偏移地址,它是⽂件流格式的,都是标准的ASCII码。⽽bin⽂件是不带地址的,全部是⼆进制数据流,打住⼀下,其实就是我们所谓的机器代码。有兴趣的同学,可以尝试着⽤反汇编,得到的就是汇编代码了。我所⽤的开发板S3C2440在ADS1.2上编译形成的代码就是bin格式流,⽤j-flash打开⽂件的时候就需要填⼊偏移地址,三星平台flash偏移地址为0,⽽stm32平台flash偏移地址就是0x08000000.
本来是应该要描述下hex⽂件的数据格式,这个就留着下⼀篇⽂章来描述,其实百度上也有很多。下⼀张是hex⽂件转换为bin⽂件,刚好和本⽂相反。说了这么多,下⾯就直接贴出代码了,有不详细的可以给我留⾔,同时也欢迎⼤家喷我。
代码是在VC6.0上⾯实现的:
⾸先新建bin2hex.h⽂件
#ifndef BIN2HEX_H
#define BIN2HEX_H
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
/***********************************
*********************************************
就是每次读写bin⽂件N个字节,然后再转化为hex格式流,hex格式流长度计算⽅式
: + 长度 + 地址 + 类型 + N个数据(N >= 0) + 校验
1 +
2  + 4 + 2    + N * 2    + 2
********************************************************************************/
#define NUMBER_OF_ONE_LINE  0x20
#define MAX_BUFFER_OF_ONE_LINE (NUMBER_OF_ONE_LINE * 2 + 11)
typedef struct {
uint8_t len;
uint8_t addr[2];
uint8_t type;
uint8_t *data;
} HexFormat;
typedef enum {
RES_OK = 0,      //操作完成
RES_BIN_FILE_NOT_EXIST,  //相当于bin⽂件不存在,包括输⼊的路径可能存在不正确
RES_HEX_FILE_PATH_ERROR  //⽬标⽂件路径可能输⼊有误
} RESULT_STATUS;
RESULT_STATUS BinFile2HexFile(char *src, char *dest);
#endif
fprintf格式
新建bin2hex.c ⽂件
#include "bin2hex.h"
#include <stdio.h>
/********************************************************************************
input:
dest: 为转换后的结果
p->addr[0]: ⾼地址
p->addr[1]: 低地址
p->type: 记录类型
p->data: 为bin格式流有效数据指针
p->len: 为bin格式流有效数据长度
output:
返回有效数据的长度
********************************************************************************/
uint16_t BinFormatEncode(uint8_t *dest, HexFormat *p)
{
uint16_t offset = 0;
uint8_t check = 0, num = 0;  //:(1) + 长度(2) + 地址(4) + 类型(2)
sprintf(&dest[offset], ":%02X%02X%02X%02X", p->len, p->addr[0], p->addr[1], p->type);
offset += 9;    //hex格式流数据指针偏移2
check = p->len + p->addr[0] + p->addr[1] + p->type; //计算校验和
while (num < p->len)  //当数据长度不为0,继续在之前的hex格式流添加数据
{
sprintf(&dest[offset], "%02X", p->data[num]);
check += p->data[num];  //计算校验和
offset += 2;    //hex格式数据流数据指针偏移2
num++;      //下⼀个字符
}
check = ~check + 1;    //反码+1
sprintf(&dest[offset], "%02X", check);
offset += 2;
return offset;    //返回hex格式数据流的长度
}
RESULT_STATUS BinFile2HexFile(char *src, char *dest)
{
FILE *src_file, *dest_file;
uint16_t tmp;
HexFormat gHexFor;
uint32_t low_addr = 0, hign_addr = 0;
uint8_t buffer_bin[NUMBER_OF_ONE_LINE], buffer_hex[MAX_BUFFER_OF_ONE_LINE];
uint32_t src_file_length;
uint16_t src_file_quotient, cur_file_page = 0;
uint8_t src_file_remainder;
src_file = fopen(src, "rb");  //源⽂件为bin⽂件,以⼆进制的形式打开
if (!src_file)      //这⾥也是相当于⽤来检查⽤户的输⼊是否准备
{
return RES_BIN_FILE_NOT_EXIST;
}
dest_file = fopen(dest, "w");  //⽬的⽂件为hex⽂件,以⽂本的形式打开
if (!dest_file)
{
return RES_HEX_FILE_PATH_ERROR;
}
fseek(src_file, 0, SEEK_END);  //定位到⽂件末
src_file_length = ftell(src_file);
fseek(src_file, 0, SEEK_SET);  //重新定位到开头,准备开始读取数据
src_file_quotient = (uint16_t)(src_file_length / NUMBER_OF_ONE_LINE); //商,需要读取多少次
src_file_remainder = (uint8_t)(src_file_length % NUMBER_OF_ONE_LINE); //余数,最后⼀次需要多少个字符
gHexFor.data = buffer_bin;  //指向需要转换的bin数据流
while (cur_file_page < src_file_quotient)
{
fread(buffer_bin, 1, NUMBER_OF_ONE_LINE, src_file);
gHexFor.len = NUMBER_OF_ONE_LINE;
if ((low_addr & 0xffff0000) != hign_addr && hign_addr != 0)  //只有⼤于64K以后才写⼊扩展线性地址,第⼀次⼀般是没有  {
hign_addr = low_addr & 0xffff0000;
gHexFor.addr[0] = (uint8_t)((hign_addr & 0xff000000) >> 24);
gHexFor.addr[1] = (uint8_t)((hign_addr & 0xff0000) >> 16);
gHexFor.len = 0;          //记录扩展地址
tmp = BinFormatEncode(buffer_hex, &gHexFor);
fwrite(buffer_hex, 1, tmp, dest_file);
fprintf(dest_file, "\n"); ;
}
gHexFor.addr[0] = (uint8_t)((low_addr & 0xff00) >> 8);
gHexFor.addr[1] = (uint8_t)(low_addr & 0xff);
tmp = BinFormatEncode(buffer_hex, &gHexFor);
fwrite(buffer_hex, 1, tmp, dest_file);
fprintf(dest_file, "\n"); ;
cur_file_page++;
low_addr += NUMBER_OF_ONE_LINE;
}
if (src_file_remainder != 0)  //最后⼀次读取的个数不为0,这继续读取
{
fread(buffer_bin, 1, src_file_remainder, src_file);
gHexFor.addr[0] = (uint8_t)((low_addr & 0xff00) >> 8);
gHexFor.addr[1] = (uint8_t)(low_addr & 0x00ff);
gHexFor.len = src_file_remainder;
tmp = BinFormatEncode(buffer_hex, &gHexFor);
fwrite(buffer_hex, 1, tmp, dest_file);
fprintf(dest_file, "\n"); ;
}
gHexFor.addr[0] = 0;
gHexFor.addr[1] = 0;
gHexFor.len = 0;
tmp = BinFormatEncode(buffer_hex, &gHexFor);
fwrite(buffer_hex, 1, tmp, dest_file);
fprintf(dest_file, "\n"); ;
fclose(src_file);
fclose(dest_file);
return RES_OK;
}
新建main.c⽂件,这⾥是带参数的,主要是⽅便批处理,是另有⽤途。
#include <stdio.h>
#include "bin2hex.h"
int main(int argc, char *argv[])
{
RESULT_STATUS res;
if (argc != 3)
{
printf("input para doesn't match\r\n");
return -1;
}
res = BinFile2HexFile(argv[1], argv[2]);
switch (res)
{
case RES_OK:
printf("hex file to bin file success!\r\n");
return -1;
case RES_BIN_FILE_NOT_EXIST:
printf("bin file doesn't exist!\r\n");
return -1;
case RES_HEX_FILE_PATH_ERROR:
printf("hex file path is error, please check it!\r\n");
return -1;
}
return 0;
}
就三个源⽂件,编译⽣成bin2hex.c⽂件。
下⾯描述下⽤法:
把bin2hex.c⽂件拷贝到c盘根⽬录下,再拷贝⼀个需要转换的bin⽂件,这⾥我就拷贝了⼀个hwb.bin⽂件。然后点击菜单开始->运⾏->输⼊cmd->进⼊dos窗⼝->调整当前⽬录为c:,这个如果不知道的可以百度⼀下,⽆法就是就是命令cd.
最后输⼊命令:bin2hex hwb.bin hwb.hex,输⼊后,可以看到提⽰说转换成功,⼤家再检查下是否有⼀个hex⽂件,本⽂的代码⽀持⼤于64K,⼤家把转换后的hex下载到单⽚机上运⾏试试看。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。