|
8位 hex 文件格式说明
这是一个跑马灯程序的hex文件内容(由winavr ,atmega8编译生成)
:1000000012C02BC02AC029C028C027C026C025C0C6
:1000100024C023C022C021C020C01FC01EC01DC0DC
:100020001CC01BC01AC011241FBECFE5D4E0DEBF28
:10003000CDBF10E0A0E6B0E0E0EAF0E002C005903D
:100040000D92A036B107D9F710E0A0E6B0E001C0EC
:100050001D92A036B107E1F701C0D2CFCFE5D4E0C1
:10006000DEBFCDBF8FEF81BB12BA8CE49DE1A0E073
:10007000B0E031E027E032BBFC013197F1F7FC0141
:100080003197F1F7FC013197F1F7FC013197F1F766
:10009000FC013197F1F7330F215027FFECCFE9CF67
:00000001FF
说明: 除" : "外,以2个字符表示一个0xff型16进制数据
数据头 数据 校验数据
:10000000 12C02BC02AC029C028C027C026C025C0 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 TRUE 1
#define FALSE 0
#define BYTE unsigned char
//8位Hex格式,由 WinAVR编译生成,MCU类型 ATmega8
typedef struct _HEX_FORMAT
{
BYTE DataLen; //记录长度 00
int MemOffset; //偏移地址 0000
BYTE DataType; //数据类型 00
BYTE Data[20]; //数据长度 最大16位
BYTE DataVerify;//数据校验 00
}HEX_FORMAT;
char HexArr[16] = "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[i+1] == 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[TmpCou++] != ':')
{
printf("Data Format Error!
");
free(pHexBuf);
free(pHexRec);
return FALSE;
}
//记录长度 00
pHexRec.DataLen = Hex2Dct(pHexBuf[TmpCou],pHexBuf[TmpCou+1]);
TmpCou+=2;
//偏移地址 0000
pHexRec.MemOffset = Hex4Dct(pHexBuf[TmpCou],pHexBuf[TmpCou+1],pHexBuf[TmpCou+2],pHexBuf[TmpCou+3]);
TmpCou+=4;
//数据类型 00
pHexRec.DataType = Hex2Dct(pHexBuf[TmpCou],pHexBuf[TmpCou+1]);
TmpCou+=2;
for(j=0;j<pHexRec.DataLen;j++)
{
pHexRec.Data[j] = Hex2Dct(pHexBuf[TmpCou],pHexBuf[TmpCou+1]);
TmpCou+=2;
}
//数据校验 00
pHexRec.DataVerify = Hex2Dct(pHexBuf[TmpCou],pHexBuf[TmpCou+1]);
TmpCou+=2;
//该行结束符 13,10
if(pHexBuf[TmpCou] != 13 || pHexBuf[TmpCou+1] != 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[j]);
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[j])&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[TmpCou]=pHexRec.Data[j];
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[255];
char szBinPath[255];
puts("Hex to Bin Program...");
if(argc < 3)
{
if(argc < 2)
{
printf("Please Input Hex Filename:");
scanf("%s",szHexPath);
}
else
{
strcpy(szHexPath,argv[1]);
}
if(argc < 3)
{
printf("Please Input Bin Filename:");
scanf("%s",szBinPath);
}
}
else
{
//赋值
strcpy(szHexPath,argv[1]);
strcpy(szBinPath,argv[2]);
}
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格式 ! |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|