HEX文件和BIN文件总结及hex文件流转bin文件流示例代码
来源:互联网 发布:旅游网络推广方案 编辑:程序博客网 时间:2024/06/06 13:09
这几天在写STM32的ISP烧录工具,因此有涉及到输入hex文件或bin文件进行烧录的问题,所以对hex文件和bin文件进行了些总结。
1 hex介绍
Hex 全称 (Intel HEX)文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX文件通常用于传输将被存于ROM或者EPROM中的程序和数据。大多数EPROM编程器或模拟器使用Intel HEX文件。
2 hex与bin的区别
1 HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身,在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为HEX文件内部的信息已经包括了地址。而烧写BIN文件的时候,用户是一定需要指定地址信息的。
2 BIN文件格式,对二进制文件而言,其实没有”格式”。文件只是包括了纯粹的二进制数据。
3 HEX文件格式
HEX文件都是由记录(RECORD)组成的。在HEX文件里面,每一行代表一个记录。记录的基本格式为:
+—————————————————————+
| RECORD | RECLEN | LOAD |RECTYPE | INFO or DATA | CHKSUM |
| MARK ‘:’| | OFFSET | | | |
+—————————————————————+
| 1-byte | 1-byte | 2-byte | 1-byte | n-byte | 1-byte |
+—————————————————————+
‘00’ DataRrecord:用来记录数据,HEX文件的大部分记录都是数据记录
‘01’ End of File Record:用来标识文件结束,放在文件的最后,标识HEX文件的结尾
‘02’ Extended SegmentAddress Record: 用来标识扩展段地址的记录
‘03’ Start Segment Address Record
‘04’ Extended Linear AddressRecord: 用来标识扩展线性地址的记录
‘05’ Start Linear Address Record
在上面的后2种记录,都是用来提供地址信息的。每次碰到这2个记录的时候,都可以根据记录计算出一个“基”地址。
对于后面的数据记录,计算地址的时候,都是以这些“基”地址为基础的。
数据记录的具体格式:
+—————————————————————+
| RECORD | RECLEN | LOAD |RECTYPE | INFO or DATA | CHKSUM |
| MARK ‘:’| | OFFSET| ‘00’ | | |
+—————————————————————+
| 1-byte | 1-byte | 2-byte | 1-byte | n-byte | 1-byte |
+—————————————————————+
看个例子:
:020000040000FA
:10000400FF00A0E314209FE5001092E5011092E5A3
:00000001FF
对上面的HEX文件进行分析:
第1条记录的长度为02,LOADOFFSET为0000,RECTYPE为04,说明该记录为扩展段地址记录。数据为0000,校验和为
FA。从这个记录的长度和数据,我们可以计算出一个基地址,这个地址为0X0000。后面的数据记录都以这个地址为基
地址。
第2条记录的长度为10(16),LOADOFFSET为0004,RECTYPE为00,说明该记录为数据记录。
数据为FF00A0E314209FE5001092E5011092E5,共16个BYTE。这个记录的校验和为A3。此时的基地址为0X0000,加上OFFSET,
这个记录里的16BYTE的数据的起始地址就是0x0000+ 0x0004 = 0x0004.
第3条记录的长度为00,LOADOFFSET为0000,TYPE = 01,校验和为FF。说明这个是一个END OF FILE RECORD,标识
文件的结尾。
在上面这个例子里,实际的数据只有16个BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址为0x4
4 HEX文件和BIN文件大小有区别
HEX文件是用ASCII来表示二进制的数值。例如一般8-BIT的二进制数值0x3F,用ASCII来表示就需要分别表示字符’3’
和字符’F’,每个字符需要一个BYTE,所以HEX文件需要 > 2倍的空间。
对一个BIN文件而言,你查看文件的大小就可以知道文件包括的数据的实际大小。而对HEX文件而言,你看到的文件
大小并不是实际的数据的大小。一是因为HEX文件是用ASCII来表示数据,二是因为HEX文件本身还包括别的附加信息。
要想详细了解HEX文件格式, 请参见INTEL HEX PDF文档
3 hex文件流转bin文件流
hex.h:
- #ifndef __HEX_H_
- #define __HEX_H_
- typedef struct{
- int len; //bin文件大小
- UINT startAddress; //刷写的起始地址
- BYTE *pContent; //转化后的内容
- }HexToBinData;
- typedef struct{
- BYTE data[16];//数据
- BYTE len; //数据长度
- UINT pos; //偏移地址
- BYTE type; //类型
- }HexLinData;
- int ConvertHexToBin(const char *str,HexToBinData *pData);
- #endif
#ifndef __HEX_H_
define _HEX_H
typedef struct{
int len; //bin文件大小
UINT startAddress; //刷写的起始地址
BYTE *pContent; //转化后的内容
}HexToBinData;
typedef struct{
BYTE data[16];//数据
BYTE len; //数据长度
UINT pos; //偏移地址
BYTE type; //类型
}HexLinData;
int ConvertHexToBin(const char *str,HexToBinData *pData);
endif
hex.cpp:
- //#include “StdAfx.h”
- #include “hex.h”
- static BYTE HexCharToByte(char c)
- {
- if(c>=‘0’ && c<=‘9’)
- return c -‘0’;
- else if(c>=‘a’ && c<=‘f’)
- return c-‘a’+0x0a;
- else if(c>=‘A’ && c <=‘F’)
- return c-‘A’+0x0a;
- return -1;
- }
- static BYTE GetFirstByte(const char str)
- {
- ASSERT(str !=NULL);
- BYTE tmp =0;
- tmp =HexCharToByte(str[0]);
- tmp <<=4;
- tmp +=HexCharToByte(str[1]);
- return tmp;
- }
- //从字符串中获取一行
- static int GetLine(const char *str,char *pBuf)
- {
- ASSERT(str !=NULL);
- ASSERT(pBuf !=NULL);
- char *start =strchr((char )str,‘:’);
- if(NULL ==start){
- return -1;
- }
- char end =strstr(start,“\r\n”);
- char *p =start;
- char *p2 =pBuf;
- int len=0;
- for (;p<end+2;p++,p2++)
- {
- if(*p ==‘\0’)
- break;
- *p2 =*p;
- len ++;
- }
- *p2 =’\0’;
- return len;
- }
- //获取一行的数据
- static int GetHexLineData(const char *line,HexLinData *pData)
- {
- ASSERT(line !=NULL);
- ASSERT(pData !=NULL);
- if(line[0] !=‘:’)
- return -1;
- int i=1;
- pData->len =GetFirstByte(&line[i]);
- i +=2;
- pData->pos =GetFirstByte(&line[i]);
- i +=2;
- pData->pos <<=8;
- pData->pos +=GetFirstByte(&line[i]);
- i +=2;
- pData->type =GetFirstByte(&line[i]);
- i +=2;
- for(int j=0;j<pData->len;i+=2,j++){
- pData->data[j] =GetFirstByte(&line[i]);
- }
- return 0;
- }
- //获取第一行指定类型的数据
- static int GetFirstDataLine(const char *str,BYTE type,HexLinData *pData)
- {
- ASSERT(str !=NULL);
- ASSERT(pData !=NULL);
- char *p =(char )str;
- char line[128];
- HexLinData data ={0};
- int len =strlen(str);
- int dataLen =0;
- for(;p<str+len;p+=dataLen){
- memset(line,0,128);
- dataLen =GetLine(p,line);
- if(dataLen <0)
- return -1;
- memset(&data,0x00,sizeof(HexLinData));
- if(0 !=GetHexLineData(line,&data))
- return -1;
- if(data.type ==type){
- memcpy(pData,&data,sizeof(HexLinData));
- return 0;
- }
- }
- return -1;
- }
- static int GetStartAddress(const char str,UINT *pStartAddress)
- {
- HexLinData data ={0};
- UINT basePos=0;
- UINT pos;
- if(0 !=GetFirstDataLine(str,4,&data))
- return -1;
- for(int i=0;i<data.len;i++){
- basePos <<=8;
- basePos +=data.data[i];
- }
- memset(&data,0x00,sizeof(HexLinData));
- if(0 !=GetFirstDataLine(str,0,&data))
- return -1;
- pos =data.pos;
- *pStartAddress =(basePos<<16) +pos;
- return 0;
- }
- int ConvertHexToBin(const char *str,HexToBinData *pData)
- {
- ASSERT(str !=NULL);
- ASSERT(pData !=NULL);
- UINT startAddress =0;
- char line[128] ={0};
- HexLinData data={0};
- if(0 !=GetStartAddress(str,&startAddress))
- return -1;
- pData->startAddress =startAddress;
- char *p =(char )str;
- int binLen =0;
- int len =0;
- int size =strlen(str);
- /FILE *file =fopen(“test.hex”,”wb+”);
- fseek(file,0,SEEK_SET);
- FILE *file1 =fopen(“test.bin”,”wb+”);
- fseek(file1,0,SEEK_SET);/
- for(binLen=0;p<str+size;p +=len){
- memset(line,0,128);
- len =GetLine(p,line);
- if(len <0)
- break;
- /fwrite(line,1,len,file);/
- memset(&data,0x00,sizeof(HexLinData));
- if(0 !=GetHexLineData(line,&data))
- return -1;
- if(data.type ==0){
- binLen +=data.len;
- /fwrite(data.data,1,data.len,file1);/
- }
- }
- /fclose(file);
- fclose(file1);/
- pData->len =binLen;
- pData->pContent =(BYTE )malloc(pData->len+1);
- if(pData->pContent ==NULL)
- return -1;
- p =(char )str;
- binLen =0;
- len =0;
- for(binLen=0;p<str+size;p +=len){
- memset(line,0,128);
- len =GetLine(p,line);
- if(len <0)
- break;
- memset(&data,0x00,sizeof(HexLinData));
- if(0 !=GetHexLineData(line,&data))
- return -1;
- if(data.type ==0){
- memcpy(pData->pContent+binLen,data.data,data.len);
- binLen +=data.len;
- }
- }
- return 0;
- }
//#include "StdAfx.h"
include "hex.h"
static BYTE HexCharToByte(char c)
{
if(c>='0' && c<='9')
return c -'0';
else if(c>='a' && c<='f')
return c-'a'+0x0a;
else if(c>='A' && c <='F')
return c-'A'+0x0a;
return -1;
}static BYTE GetFirstByte(const char *str){ ASSERT(str !=NULL);BYTE tmp =0;tmp =HexCharToByte(str[0]);tmp <<=4;tmp +=HexCharToByte(str[1]);return tmp;
}//从字符串中获取一行static int GetLine(const char *str,char *pBuf){ ASSERT(str !=NULL); ASSERT(pBuf !=NULL);char *start =strchr((char *)str,':');if(NULL ==start){ return -1;}char *end =strstr(start,"\r\n");char *p =start;char *p2 =pBuf;int len=0;for (;p<end+2;p++,p2++){ if(*p =='\0') break; *p2 =*p; len ++;}*p2 ='\0';return len;
}//获取一行的数据static int GetHexLineData(const char *line,HexLinData *pData){ ASSERT(line !=NULL); ASSERT(pData !=NULL);if(line[0] !=':') return -1;int i=1;pData->len =GetFirstByte(&line[i]);i +=2;pData->pos =GetFirstByte(&line[i]);i +=2;pData->pos <<=8;pData->pos +=GetFirstByte(&line[i]);i +=2;pData->type =GetFirstByte(&line[i]);i +=2;for(int j=0;j<pData->len;i+=2,j++){ pData->data[j] =GetFirstByte(&line[i]);}return 0;
}//获取第一行指定类型的数据static int GetFirstDataLine(const char *str,BYTE type,HexLinData *pData){ASSERT(str !=NULL);ASSERT(pData !=NULL);char *p =(char *)str;char line[128];HexLinData data ={0};int len =strlen(str);int dataLen =0;for(;p<str+len;p+=dataLen){ memset(line,0,128); dataLen =GetLine(p,line); if(dataLen <0) return -1; memset(&data,0x00,sizeof(HexLinData)); if(0 !=GetHexLineData(line,&data)) return -1; if(data.type ==type){ memcpy(pData,&data,sizeof(HexLinData)); return 0; }}return -1;
}static int GetStartAddress(const char *str,UINT *pStartAddress){ HexLinData data ={0}; UINT basePos=0; UINT pos;if(0 !=GetFirstDataLine(str,4,&data)) return -1;for(int i=0;i<data.len;i++){ basePos <<=8; basePos +=data.data[i];}memset(&data,0x00,sizeof(HexLinData));if(0 !=GetFirstDataLine(str,0,&data)) return -1;pos =data.pos;*pStartAddress =(basePos<<16) +pos;return 0;
}int ConvertHexToBin(const char *str,HexToBinData *pData){ ASSERT(str !=NULL); ASSERT(pData !=NULL);UINT startAddress =0;char line[128] ={0};HexLinData data={0};if(0 !=GetStartAddress(str,&startAddress)) return -1;pData->startAddress =startAddress;char *p =(char *)str;int binLen =0;int len =0;int size =strlen(str);/*FILE *file =fopen("test.hex","wb+");fseek(file,0,SEEK_SET);FILE *file1 =fopen("test.bin","wb+");fseek(file1,0,SEEK_SET);*/for(binLen=0;p<str+size;p +=len){ memset(line,0,128); len =GetLine(p,line); if(len <0) break; /*fwrite(line,1,len,file);*/ memset(&data,0x00,sizeof(HexLinData)); if(0 !=GetHexLineData(line,&data)) return -1; if(data.type ==0){ binLen +=data.len; /*fwrite(data.data,1,data.len,file1);*/ }}/*fclose(file);fclose(file1);*/pData->len =binLen;pData->pContent =(BYTE *)malloc(pData->len+1);if(pData->pContent ==NULL) return -1;p =(char *)str;binLen =0;len =0;for(binLen=0;p<str+size;p +=len){ memset(line,0,128); len =GetLine(p,line); if(len <0) break; memset(&data,0x00,sizeof(HexLinData)); if(0 !=GetHexLineData(line,&data)) return -1; if(data.type ==0){ memcpy(pData->pContent+binLen,data.data,data.len); binLen +=data.len; }}return 0;
}只有一个接口函数:
- int ConvertHexToBin(const char *str,HexToBinData *pData);
int ConvertHexToBin(const char *str,HexToBinData *pData);
它的作用是将hex文件流str直接转化为bin文件流,并存储到HexToBinData结构体中,若成功则返回0,失败则返回非0.
- HEX文件和BIN文件总结及hex文件流转bin文件流示例代码
- HEX文件和BIN文件总结及hex文件流转bin文件流示例代码
- HEX文件和BIN文件总结及hex文件流转bin文件流示例代码
- HEX文件和BIN文件
- HEX转BIN文件总结
- Hex文件转Bin文件
- Hex文件转Bin文件
- Hex文件转Bin文件
- HEX 文件和bin文件区别
- bin文件和hex文件互转
- HEX文件和BIN文件区别
- hex文件和bin文件区别
- hex文件和bin文件区别
- HEX BIN文件 分析介绍
- HEX文件和BIN文件格式的区别
- HEX文件和BIN文件格式的区别
- HEX文件和BIN文件格式的区别
- HEX文件和BIN文件格式的区别
- 学习新技术时你应当掌握的『最少必要知识』
- 一个上传头像的小Demo
- 数据库存txt和图片
- Spring5学习(一)-官网首页阅读
- JVM参数及调优
- HEX文件和BIN文件总结及hex文件流转bin文件流示例代码
- 【Scikit-Learn 中文文档】概率校准
- Android Wear中国版模拟器
- 利用 AutoML 进行大规模图像分类和对象检测
- 多学一招(面试)
- 时间序列笔记(七)
- IT忍者神龟之Redis+Tomcat+Nginx集群实现Session共享
- myeclipse中的快捷键列表
- 2017-11-28 7周2次课 linux系统日常管理(二)