#include <stdio.h>
#include <string.h>
#include <stdlib.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 0x10//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, //目标文件路径可能输入有误
RES_HEX_ADDRRESS_ERROR //目标文件地址可能输入有误
} RESULT_STATUS;
RESULT_STATUS BinFile2HexFile(char*src, char *dest);
#endif
/********************************************************************************
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, char *addr)
{
FILE *src_file, *dest_file;
uint16_t tmp;
HexFormat gHexFor;
uint32_t low_addr = 0x8000, hign_addr = 0;
uint8_t buffer_bin[NUMBER_OF_ONE_LINE*10], buffer_hex[MAX_BUFFER_OF_ONE_LINE*10];
uint32_t src_file_length;
uint16_t src_file_quotient, cur_file_page = 0;
uint8_t src_file_remainder;
//low_addr = addr[0] - 0x30;
//low_addr *= 256;
//low_addr += (addr[1] - 0x30);
//low_addr *= 256;
////low_addr += (addr[2] - 0x30);
////low_addr *= 256;
////low_addr += (addr[3] - 0x30);
//printf("%d help\r\n",low_addr);
//if (low_addr > 0x10000)
//{
// return RES_HEX_ADDRRESS_ERROR;
//}
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.type = 4;
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);
gHexFor.type = 0; //数据记录
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;
gHexFor.type = 0; //数据记录
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.type = 1; //结束符
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;
}
int main(int argc, char *argv[])
{
RESULT_STATUS res;
//argv[1] = "DCT100_Boot.bin" ;// = _T("\\NANDFLASH\\Uartinfo.dat");
//argv[2] = "DCT100_1.hex";// = _T("\\NANDFLASH\\Uartinfo.dat");
if (argc == 1)
{
printf("bin2hex help\r\n");
printf("bin2hex src.bin dest.hex addr\r\n");
printf("src.bin:source BIN file\r\n");
printf("dest.bin:dest HEX file\r\n");
printf("addr: start Addrress\n");
return-1;
}
if (argc != 4)
{
printf("input para doesn't match\r\n");
return-1;
}
res = BinFile2HexFile(argv[1], argv[2], argv[3]);
switch (res)
{
case RES_OK:
printf("hex file to bin file success!\r\n");
printf("%s\r\n", argv[2]);
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;
case RES_HEX_ADDRRESS_ERROR:
printf("hex file address is error, please check it!\r\n");
return-1;
}
return 0;
}