ainet 发表于 2006-5-22 16:45:20

Bootloader 用到的hex 转 bin程序

8位 hex 文件格式说明



这是一个跑马灯程序的hex文件内容(由winavr ,atmega8编译生成)

:1000000012C02BC02AC029C028C027C026C025C0C6

:1000100024C023C022C021C020C01FC01EC01DC0DC

:100020001CC01BC01AC011241FBECFE5D4E0DEBF28

:10003000CDBF10E0A0E6B0E0E0EAF0E002C005903D

:100040000D92A036B107D9F710E0A0E6B0E001C0EC

:100050001D92A036B107E1F701C0D2CFCFE5D4E0C1

:10006000DEBFCDBF8FEF81BB12BA8CE49DE1A0E073

:10007000B0E031E027E032BBFC013197F1F7FC0141

:100080003197F1F7FC013197F1F7FC013197F1F766

:10009000FC013197F1F7330F215027FFECCFE9CF67

:00000001FF



说明: 除" : "外,以2个字符表示一个0xff型16进制数据



数据头         数据                        校验数据

:1000000012C02BC02AC029C028C027C026C025C0   C6



字符":" - 是每一行的开头标志

字符串" 10000000 " - 分解为 " 10 0000 00 "

      即为: 10 数据的长度(16进制) 该行数据有16个字节

            0000 在储存器中的偏移地址: (16进制)

            00数据类型 (类似关键字). 00 表示记录是数据,最后一行的01 表示记录结束



字符串" 12C02BC02AC029C028C027C026C025C0 " 表示数据为(22组合表示一个16进制数)

12 C0 2B C0 2A C0 29 C0 28 C0 27 C0 26 C0 25 C0

0x12 0xC0 0x2B 0xC0 0x2A 0xC0 0x29 0xC0 0x28 0xC0 0x27 0xC0 0x26 0xC0 0x25 0xC0



字符串" C6 " 是校验数据, 除了" : " 和 校验数据本身 的所有数据(转换后的)的累加和

    也就是:

0x10

+ 0x0000

+ 0x00

+ ( 全加0x12 0xC0 0x2B 0xC0 0x2A 0xC0 0x29 0xC0 0x28 0xC0 0x27 0xC0 0x26 0xC0 0x25 0xC0 )



这个数必须始终为8位,中间相加过程的超出0xff的部分是忽略的



然后这个数再加上 校验数据 ,则 = 0x00 ,说明数据正确,否则数据校验错误.





hex to bin

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/types.h>



#define TRUE1

#define FALSE 0

#define BYTE unsigned char



//8位Hex格式,由 WinAVR编译生成,MCU类型 ATmega8

typedef struct _HEX_FORMAT

{

BYTE DataLen;//记录长度00

intMemOffset; //偏移地址0000

BYTE DataType; //数据类型00

BYTE Data; //数据长度最大16位

BYTE DataVerify;//数据校验00

}HEX_FORMAT;



char HexArr = "0123456789ABCDEF";



//16进制字符转10进制数,默认为0??

BYTE ChHex2Dct(char chr)

{

BYTE i;

for(i=0;i<16;i++)

{

if(HexArr == chr)

{

   return i;

}

}

return 0;

}

BYTE Hex2Dct(char chH,char chL)

{

BYTE RetVal;



RetVal = ChHex2Dct(chH) * 16 + ChHex2Dct(chL);

return RetVal;

}

int Hex4Dct(char ch1,char ch2,char ch3,char ch4)

{

int RetVal;



RetVal = ChHex2Dct(ch1) << 12;

RetVal += ChHex2Dct(ch2) << 8;

RetVal += ChHex2Dct(ch3) << 4;

RetVal += ChHex2Dct(ch4);



return RetVal;

}







int Hex2Bin(char* szHexPath,char* szBinPath)

{

int fpHex;

int fpBin;



int HexFileLen;

int BinFileLen;



BYTE *pHexBuf;

int i,j;



BYTE *pBinBuf;

int iBinBufLen;



HEX_FORMAT *pHexRec;

int iRecCou;



struct stat HexInfo;

int TmpCou;

BYTE TmpVal;







fpHex = open(szHexPath,O_RDONLY);

if(fpHex<0) return FALSE;



fstat(fpHex,&HexInfo);



HexFileLen =(int)HexInfo.st_size;



printf("%s Hex File Length:%d
",szHexPath,HexFileLen);



pHexBuf = (BYTE*)malloc(HexFileLen+1);

if(!pHexBuf)

{

printf("Malloc Memory Fail!
");

return FALSE;

}

read(fpHex,pHexBuf,HexFileLen);



close(fpHex);





//以上读取hex文件的内容并保存到pHexBuf内存中



iRecCou=0;

//计算记录的个数

for(i=0;i<HexFileLen-1;i++)

{

if(pHexBuf == 13 && pHexBuf == 10)

{

   iRecCou++;

}

}



//为记录结构分配内存

pHexRec = malloc(iRecCou * sizeof(HEX_FORMAT) + 1);

if(!pHexRec)

{

printf("Hex Record Malloc Memory Fail!
");

return FALSE;

}



//将数据转换到记录结构中

TmpCou=0;

for(i=0;i<iRecCou;i++)

{

if(pHexBuf != ':')

{

   printf("Data Format Error!
");

   free(pHexBuf);

   free(pHexRec);

   return FALSE;

}

//记录长度00

pHexRec.DataLen = Hex2Dct(pHexBuf,pHexBuf);

TmpCou+=2;

//偏移地址0000

pHexRec.MemOffset = Hex4Dct(pHexBuf,pHexBuf,pHexBuf,pHexBuf);

TmpCou+=4;

//数据类型00

pHexRec.DataType = Hex2Dct(pHexBuf,pHexBuf);

TmpCou+=2;



for(j=0;j<pHexRec.DataLen;j++)

{

   pHexRec.Data = Hex2Dct(pHexBuf,pHexBuf);

   TmpCou+=2;

}

//数据校验00

pHexRec.DataVerify = Hex2Dct(pHexBuf,pHexBuf);

TmpCou+=2;

//该行结束符 13,10

if(pHexBuf != 13 || pHexBuf != 10)

{

   printf("Data Format Error,End Not 13,10!
");

   free(pHexBuf);

   free(pHexRec);

   return FALSE;

}

TmpCou+=2;

}



free(pHexBuf);





/*

for(i=0;i<iRecCou;i++)

{

printf("
Record %d:
",i+1);

printf("Data Length   :%d
",pHexRec.DataLen);

printf("Memory Offset:%4x
",pHexRec.MemOffset);

printf("Data Type      :%x
",pHexRec.DataType);

printf("Data:");

for(j=0;j<pHexRec.DataLen;j++)

   printf("%x ",pHexRec.Data);

printf("
Data Verify :%x
",pHexRec.DataVerify);

   

}

*/



//对每条记录进行校验 ,(除了 ; 和 校验 之外的所有数据的累加和+ 校验数据 )&0xff = 0x00



iBinBufLen = 0;

for(i=0;i<iRecCou;i++)

{

TmpVal = 0;

TmpVal += pHexRec.DataLen;

TmpVal += (pHexRec.MemOffset & 0xff00) >> 8;

TmpVal += (pHexRec.MemOffset & 0xff);

TmpVal += pHexRec.DataType;



for(j=0;j<pHexRec.DataLen;j++)

{

   TmpVal += (pHexRec.Data)&0xff;

}

if( ((TmpVal + (pHexRec.DataVerify & 0xff)) & 0xff) != 0x00)

{

   printf("Record[%d]:Data Verify Error!
",i);

   printf("Data:%x ,Data Verify:%x = %x
",TmpVal,pHexRec.DataVerify,TmpVal+pHexRec.DataVerify);

   free(pHexRec);

   return FALSE;

}

iBinBufLen += pHexRec.DataLen;

}



pBinBuf = malloc(iBinBufLen+1);

if(!pBinBuf)

{

printf("Bin Buffer Malloc Memory Error!
");

free(pHexRec);

return FALSE;

}



//将数据直接提取出来,直接存成bin格式

TmpCou = 0;

for(i=0;i<iRecCou;i++)

{

for(j=0;j<pHexRec.DataLen;j++)

{

   pBinBuf=pHexRec.Data;

   TmpCou++;

}

}

free(pHexRec);



fpBin = open(szBinPath,O_RDWR|O_CREAT);

if(fpBin<0)

fpBin = open(szBinPath,O_RDWR|O_CREAT);



write(fpBin,pBinBuf,iBinBufLen);



close(fpBin);



free(pBinBuf);



return TRUE;

}





int main(int argc,char *argv[])

{

char szHexPath;

char szBinPath;



puts("Hex to Bin Program...");



if(argc < 3)

{

if(argc < 2)

{

   printf("Please Input Hex Filename:");

   scanf("%s",szHexPath);

}      

else

{

   strcpy(szHexPath,argv);

}

   

if(argc < 3)

{

   printf("Please Input Bin Filename:");

   scanf("%s",szBinPath);

}

}

else

{

//赋值

strcpy(szHexPath,argv);

strcpy(szBinPath,argv);

}



printf("Source File(Hex):%s
Target File(Bin):%s
",szHexPath,szBinPath);







if(Hex2Bin(szHexPath,szBinPath)==FALSE)

{

printf("
Error Transform Hex file:%s To Bin file:%s!
",szHexPath,szBinPath);

exit(-1);

}

printf("
Success Transform Hex file:%s To Bin file:%s!
",szHexPath,szBinPath);



exit(0);

}



取出里面的hex 转bin 的过程,放到bootloader 得pc端程序中,即可将winavr 生成的 8 位hex 文件

数据 转成 atmega8 可以直接存储的格式, 注意,这个是8位 hex格式 !

pengshipower 发表于 2009-8-19 22:52:28

好帖子啊,难得难得。居然一直没有人顶,可惜啊

tong7127 发表于 2009-9-7 08:32:23

没怎么看明白。没明白这其中的原理

ShangGuan 发表于 2009-9-7 08:51:51

先mark,以后再看。

pinocchio 发表于 2009-9-7 08:57:40

为什么要费劲用程序转呢,如果用gcc的话,直接修改makefile,直接输出bin格式就可以了

wodetianmyday 发表于 2009-10-29 13:27:51

MARK

WillFeng 发表于 2010-12-12 14:25:32

好文,非常详细

NJ8888 发表于 2010-12-12 14:44:50

一个办法是用编程器软件,比如西尔特,不用硬件,启动后读入HEX文件,在另存BIN就行了

www1519 发表于 2010-12-12 15:45:48

mark

haolei432370 发表于 2013-6-20 16:39:04

mark{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}

leahcim89 发表于 2013-7-20 23:49:28

顶下。。。。

leahcim89 发表于 2013-7-21 08:47:30

参考着用下。

liren 发表于 2013-7-24 21:32:45

写的好!
页: [1]
查看完整版本: Bootloader 用到的hex 转 bin程序