📄 hextobin.cpp
字号:
/************************************************************************************
* Copyright(c)2008-2018 GENVICT Co,.ltd.
* All rights reserved
*
*文件名称:HexToBin.c
*制作日期:2008-05-26 16:56:00
*作 者:郭云峰
*文件类型:Hex转bin文件的具体实现函数
*功能描述:实现Hex格式的文件转为bin格式的文件。
**************************************************************************************/
#define HEXTOBIN_GLOBAL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale>
#include "HexToBin.h"
/************************************************************************************
*函数名称:VerifyData()
*入口参数:数据指针、数据个数、上次校验完后的数据
*出口参数:操作结果
*功能描述:将传入的指定数量的数据进行异或运算并返回最终结果.
*抛出异常:无
*特殊情况:CRC校验方式采用CCITT(欧洲标准:X^16+X^12+X^5+1)
*************************************************************************************/
INT16U VerifyData(INT32U num,INT8U *p_data,INT8U type,INT16U last)
{
INT8U l_index;
UNWORD l_sum;
l_sum.word =last;
if( CRC == type )
{
while(num--)
{
for(l_index=0x80;l_index>0;l_index>>=1)
{
if(l_sum.word & 0x8000)
{
l_sum.word <<=1;
l_sum.word ^=0x1021;
}
else
{
l_sum.word <<=1;
}
if((*p_data) & l_index)
{
l_sum.word ^=0x1021;
}
}
p_data++;
}
}
else if( BCC == type )
{
while( num > 0 )
{
l_sum.byte.lb^=p_data[--num];
}
l_sum.byte.hb=~l_sum.byte.lb;
}
return l_sum.word;
}
/*************************************************************************************
*函数名称:AsciiToHex()
*入口参数:ASCII码1、ASCII码2、Hex数据指针
*出口参数:操作结果
*功能描述:将传入的2位ASCII码合并为一个Hex格式的数据
*抛出异常:无
*
**************************************************************************************/
INT8U AsciiToHex(INT8S ascii1,INT8S ascii2,INT8U *p_data)
{
INT8U status =OP_OK;
INT8S ascii;
BYTEUNION temp;
temp.byte =0;
//将传入的ASCII码全部转换为大写
ascii =(INT8S)toupper(ascii1);
//判断传入的ascii码是否符合要求
if( ascii >= '0' && ascii <= '9')
{
temp.bf.h4 =ascii-0x30;
}
else if( ascii >='A' && ascii <='F')
{
temp.bf.h4 =ascii-0x37;
}
else //其它字符认为是无效字符
{
status =OP_FAIL;
}
//进行低4位转换
if( OP_OK == status )
{
ascii =(INT8S)toupper(ascii2);
//判断传入的ascii码是否符合要求
if( ascii >= '0' && ascii <= '9')
{
temp.bf.l4 =ascii-0x30;
}
else if( ascii >='A' && ascii <='F')
{
temp.bf.l4 =ascii-0x37;
}
else //其它字符认为是无效字符
{
status =OP_FAIL;
}
}
//获取转换后的Hex数据
*p_data =temp.byte;
//返回执行结果
return status;
}
/****************************************************************************************
*函数名称:DispHelp()
*入口参数:无
*出口参数:无
*功能描述:显示帮助信息。
*抛出异常:无
*
*****************************************************************************************/
void DispHelp(void)
{
printf("功能描述:1.本软件可实现将Hex格式的文件转换为bin文件并自动根据需要加入校验和.\n");
printf(" 2.支持的校验方式:BCC(异或)/CRC.\n");
printf(" 3.选择了增加校验和时必须指定校验和存放的地址.\n");
printf(" 4.对未用到的程序空间必须指定填充数据(以十六进制方式).\n");
printf("入口参数:HexToBin ---- (输入)要执行任务的PC软件名称(必须是可执行文件).\n");
printf(" file.hex ---- (输入)要转换的hex格式文件名.\n");
printf(" file.bin ---- (输出)转换结束后的bin文件名.\n");
printf(" /bcc+xxxxxxxx ---- (输入)增加BCC校验和其存放地址为xxxxxxxx.\n");
printf(" xx ---- (输入)要填充的数据长度(hex格式).\n");
printf(" xx~xx ---- (输入)要填充的数据(hex格式).\n");
printf("举例说明:HexToBin App.hex iSpeedyC6BV100.bin /bcc+0000FFFC 02 94 0C\n");
printf("注意事项:加入校验和后默认的填充空间数据为0x00(如果没有指定填充数据)\n");
printf("编译日期:%s %s\n",__DATE__,__TIME__);
}
/***************************************************************************************
*函数名称:AddVerifyToBin()
*入口参数:Bin文件名称、校验类型
*出口参数:无
*功能描述:向bin文件的指定地址加入指定类型的校验字节
*抛出异常:
*****************************************************************************************/
void AddVerifyToBin(const INT8S *p_bin,INT8U verify_type)
{
FILE *f_bin; //bin文件指针
INT8U bin_data; //读出的bin数据
INT8U l_buf[4]; //写文件的缓冲区
UNWORD verify_byte; //校验字节
//////////////////////////////////////////////////////
//打开bin文件
if( NULL == (f_bin =fopen(p_bin,"r+b")))
{
printf("无法打开文件:%s.\n",p_bin);
exit(1);
}
//复位文件指针
rewind(f_bin);
/////////////////////////////////////////////////////
//计算校验和
verify_byte.word =0;
while( ftell(f_bin) < (long)verify_addr )
{
bin_data =(INT8U)fgetc(f_bin);
verify_byte.word=VerifyData(1,&bin_data,verify_type,verify_byte.word);
}
/////////////////////////////////////////////////////
//写校验和到bin文件中
l_buf[0] =verify_byte.byte.hb;
l_buf[1] =verify_byte.byte.lb;
l_buf[2] =~verify_byte.byte.hb;
l_buf[3] =~verify_byte.byte.lb;
//重定位文件指针
fseek(f_bin,verify_addr,SEEK_SET);
//写入到文件中
if( 4 == fwrite(l_buf,sizeof(INT8U),4,f_bin) )
{
printf("校验和写入成功:0x%04x,存放地址为:0x%08x.\n",verify_byte.word,verify_addr);
}
else
{
printf("校验和写入失败,操作终止!.\n");
}
fclose(f_bin);
}
/****************************************************************************************
*函数名称:HexToBin()
*入口参数:hex格式文件名称、bin文件名称、填充字节个数、填充数据指
*出口参数:无
*功能描述:实现将hex格式的文件类型转换为bin格式。
*抛出异常:1.无法打开指定的hex文件。
*****************************************************************************************/
void HexToBin(const INT8S *p_hex,const INT8S *p_bin,INT8U fill_length,const INT8U *p_fill)
{
FILE *f_hex=NULL; //hex文件类型指针
FILE *f_bin=NULL; //bin文件类型指针
INT8S l_buf[100]; //一行hex记录存放数据
INT8U l_num; //一行中实际读取到的字节数
INT8U i,j; //索引
INT16U l_sum; //一行的数据加总和
INT32U l_addr; //文件位置指针
//////////////////////////////////////////////////////////////////////////
//打开hex格式的文件---只读
if( NULL == (f_hex = fopen(p_hex,"r")))
{
printf("无法打开文件:%s.\n",p_hex);
exit(1);
}
//创建bin格式的文件--可读可写
if( NULL == (f_bin =fopen(p_bin,"w+b")))
{
printf("无法创建文件:%s.\n",p_bin);
exit(2);
}
rewind(f_bin);
////////////////////////////////////////////////////////////////////////////
//用指定的无效字符填充bin文件
if( fill_length )
{
for(l_addr=0;l_addr<fill_length;l_addr++)
{
l_buf[l_addr] =(INT8S)p_fill[l_addr];
}
l_addr =0;
while(l_addr < verify_addr )
{
l_num =fwrite(l_buf,sizeof(INT8U),fill_length,f_bin);
if( l_num == fill_length )
{
l_addr+=fill_length;
}
else
{
printf("bin文件填充无效字符失败\n");
exit(3);
}
}
}
//////////////////////////////////////////////////////////////////////////
//初始化hex记录数据结构体
g_hex.start ='~';
g_hex.length =0x00;
g_hex.address =0x0000;
g_hex.type =0xFF;
g_hex.check =0xAA;
g_hex.offset =0x0000;
g_hex.format =0x00;
//////////////////////////////////////////////////////////////////////////
//文件指针重定向
rewind(f_hex);
rewind(f_bin);
//读取Hex文件内容
while(1)
{
/////////////////////////////////////////////////////////////////////
//首先找到起始字符
l_num =0;
while( fgetc(f_hex) != ':')
{
if( ++l_num >= 0xFE) //在254字符内没有找到起始字符认为hex文件格式错误
{
printf("无法在%s文件中找到起始字符,异常退出\n",p_hex);
exit(3);
}
}
/////////////////////////////////////////////////////////////////////
//接收的字符个数清零
l_num =0;
//找到起始字符开始接收数据
l_buf[l_num++] =':';
//获取本行的数据长度
l_buf[l_num++] =(INT8S)fgetc(f_hex);
l_buf[l_num++] =(INT8S)fgetc(f_hex);
if( OP_FAIL == AsciiToHex(l_buf[1],l_buf[2],&g_hex.length) )
{
printf("传入的hex长度错误,转换终止!\n");
exit(3);
}
//一共要接收的数据个数为11+2*g_hex.length
while(l_num < (11 + 2*g_hex.length) )
{
l_buf[l_num++] =(INT8S)fgetc(f_hex);
}
//一行中至少应包含: ":"+"ll"+"aaaa"+"tt"+"cc"=11个字符
if( l_num >= 11 )
{
///////////////////////////////////////////////////////////////////
//保存起始字符
g_hex.start =l_buf[0];
///////////////////////////////////////////////////////////////////
//获取本行的有效数据长度
if( OP_FAIL == AsciiToHex(l_buf[1],l_buf[2],&g_hex.length) )
{
printf("传入的hex文件格式错误2,转换终止!\n");
exit(3);
}
///////////////////////////////////////////////////////////////////
//获取本行的数据存放地址
if( OP_FAIL == AsciiToHex(l_buf[3],l_buf[4],&l_num) )
{
printf("传入的hex文件格式错误3,转换终止!\n");
exit(3);
}
//获取地址的高8位
g_hex.offset =(INT16U)l_num;
g_hex.offset <<=8;
if( OP_FAIL == AsciiToHex(l_buf[5],l_buf[6],&l_num) )
{
printf("传入的hex文件格式错误4,转换终止!\n");
exit(3);
}
//获取地址的低8位
g_hex.offset |=(INT16U)l_num;
///////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -