上一章讲解的是bin文件转化为hex文件,本文主要是贴出hex文件转bin文件的代码:
新建hex2bin.h
#ifndef HEX2BIN_H
#define HEX2BIN_H
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
#define HEX_MAX_LENGTH 521
#define HEX_MIN_LEN 11
typedef enum {
RES_OK = 0, //正确
RES_DATA_TOO_LONG, //数据太长
RES_DATA_TOO_SHORT, //数据太短
RES_NO_COLON, //无标号
RES_TYPE_ERROR, //类型出错,或许不存在
RES_LENGTH_ERROR, //数据长度字段和内容的总长度不对应
RES_CHECK_ERROR, //校验错误
RES_HEX_FILE_NOT_EXIST, //HEX文件不存在
RES_BIN_FILE_PATH_ERROR,//BIN文件路径可能不正确
RES_WRITE_ERROR, //写数据出错
RES_HEX_FILE_NO_END //hex文件没有结束符
} RESULT_STATUS;
typedef struct {
uint8_t len;
uint8_t type;
uint16_t addr;
uint8_t *data;
} BinFarmat;
RESULT_STATUS HexFile2BinFile(char *src, char *dest);
#endif
新建hex2bin.c
#include "hex2bin.h"
#include
#include
/********************************************************************************
input:
c:单个字符('0'~'9' 'a'~'f', 'A'~'F')
output:
单个字符转化为单个字符
********************************************************************************/
static uint8_t HexCharToBinBinChar(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'a' && c <= 'z')
return c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return 0xff;
}
/********************************************************************************
input:
p: 两个文本字符
output:
转化为1个字节
********************************************************************************/
static uint8_t Hex2Bin(const char *p)
{
uint8_t tmp = 0;
tmp = HexCharToBinBinChar(p[0]);
tmp <<= 4;
tmp |= HexCharToBinBinChar(p[1]);
return tmp;
}
/********************************************************************************
input:
src: hex单行字符串
p->type: 如果函数返回结果正确,这里就存着转化后的类型
p->len: 如果函数运行正确,这里就存着转化后的bin数据长度
p->data: 如果函数运行正确,长度并且不为0,该指针就只想转化后的数据
p->addr[0]: 如果函数返回结果正确,这里就存着地址的低字节
p->addr[1]: 如果函数返回结果正确,这里就存着地址的低字节
output:
返回hex格式流分析的结果
********************************************************************************/
static RESULT_STATUS HexFormatUncode(const char *src, BinFarmat *p)
{
uint8_t check = 0, tmp[4], binLen;
uint16_t hexLen = strlen(src);
uint16_t num = 0, offset = 0;
if (hexLen > HEX_MAX_LENGTH) //数据内容过长
return RES_DATA_TOO_LONG;
if (hexLen < HEX_MIN_LEN)
return RES_DATA_TOO_SHORT; //数据内容过短
if (src[0] != ':')
return RES_NO_COLON; //没有冒号
if ((hexLen - 1) % 2 != 0)
return RES_LENGTH_ERROR; //hexLen的长度应该为奇数
binLen = (hexLen - 1) / 2; //bin总数据的长度,包括长度,地址,类型校验等内容
while (num < 4)
{
offset = (num << 1) + 1;
tmp[num] = Hex2Bin(src + offset);
check += tmp[num];
num++;
}
p->len = tmp[0]; //把解析的这些数据保存到结构体中
p->addr = tmp[1];
p->addr <<= 8;
p->addr += tmp[2];
p->type = tmp[3];
while (num < binLen)
{
offset = (num << 1) + 1; //保存真正的bin格式数据流
p->data[num - 4] = Hex2Bin(src + offset);
check += p->data[num - 4];
num++;
}
if (p->len != binLen - 5) //检查hex格式流的长度和数据的长度是否一致
return RES_LENGTH_ERROR;
if (check != 0) //检查校验是否通过
return RES_CHECK_ERROR;
return RES_OK;
}
RESULT_STATUS HexFile2BinFile(char *src, char *dest)
{
FILE *src_file, *dest_file;
uint16_t addr_low = 0;
uint32_t addr_hign = 0;
char buffer_hex[600];
uint8_t buffer_bin[255];
BinFarmat gBinFor;
RESULT_STATUS res;
gBinFor.data = buffer_bin;
src_file = fopen(src, "r"); //以文本的形式打开一个hex文件
if (!src_file)
return RES_HEX_FILE_NOT_EXIST;
dest_file = fopen(dest, "wb"); //以二进制写的方式打开文件,文件不存在也没影响
if (!dest_file)
return RES_BIN_FILE_PATH_ERROR;
fseek(src_file, 0, SEEK_SET); //定位到开头,准备开始读取数据
while (!feof(src_file))
{
fscanf(src_file, "%s
", buffer_hex);
res = HexFormatUncode(buffer_hex, &gBinFor);
if (res != RES_OK)
{
fclose(src_file);
fclose(dest_file);
return res;
}
switch (gBinFor.type)
{
case 0: //数据记录
addr_low = gBinFor.addr;
//数据指针偏移
fseek(dest_file, addr_low + addr_hign, SEEK_SET);
if (fwrite((const uint8_t*)gBinFor.data, gBinFor.len, 1, dest_file) != 1)
{
fclose(src_file);
fclose(dest_file);
return RES_WRITE_ERROR;
}
break;
case 1: //数据结束
fclose(src_file);
fclose(dest_file);
return RES_OK;
case 2:
addr_hign = ((uint32_t)gBinFor.addr) << 2;
break;
case 4: //线性段地址
addr_hign = ((uint32_t)gBinFor.addr) << 16;
break;
default:
fclose(src_file);
fclose(dest_file);
return RES_TYPE_ERROR;
}
}
fclose(src_file);
fclose(dest_file);
return RES_HEX_FILE_NO_END;
}
新建main.c
#include
#include "hex2bin.h"
const char *TipString[] =
{
"bin file to hex file success!",
"line data of hex file is too large",
"line data of hex file is too short",
"line data of hex file is no colon",
"line data of hex file type is error",
"line data of hex file length is error",
"line data of hex file check error",
"hex file is not exist",
"bin file path is error",
"hex file is no end"
};
int main(int argc, char *argv[])
{
RESULT_STATUS res;
if (argc != 3)
{
printf("para doesn't match!
");
}
res = HexFile2BinFile(argv[1], argv[2]);
printf("%s
", TipString[res]);
if (res != RES_OK)
{
return -1;
}
return 0;
}
用法 hex2bin hwb.hex hwb.bin