HEX文件解析C语言源代码

最近在编写MCU程序,BootLoader要支持UART和CAN升级,做一些记录.下面是Hex升级文件的解析方法,上位机调试用,能够将Hex的各个Block进行分组,每个块的起始地址和大小,总字节数等信息提取.

void ReadHexFileToStruct(char *FileName, HEX_FEIL_T *HexFile)
{
	FILE *fp;
	ssize_t size;
	int status = 0;
	char RowData[48];													//逐行读取,每行数据缓存
	uint32_t  i = 0;
	uint32_t  RowDataByte = 0;											//单行数据块字节数
	uint32_t  OffsetAddress = 0;										//扩展线性地址 	
	uint32_t  ReAddr = 0;												//上一数据行起始地址 
	uint32_t  Len = 0;													//HEX每行有效数据字节数
	uint32_t  ReLen = 0;												//HEX前一次数据长度
	uint32_t  Addr=0;													//HEX每行起始地址
	uint8_t   Type = 0;													//HEX单行数据的类型	
	ReadHexFileInit(HexFile);											//初始化缓存区
	status = GetFileInfo (FileName, &size);								//获取文件信息
	if(status > 0)														//0:不存在,1:文件存在,-1:已打开
	{    
		if((fp = fopen(FileName, "r")) == NULL) 						//打开文件
		{	
			Msg("Hex文件不存在!");
			return ;													//空指针
		}
		while(fgets (RowData, 48, fp) != NULL)							//读行函数fgets
		{
			if(RowData[0] == ':')						  				//首字判断:偏移1,“:”0x3A
			{
				Len  = CharToHexUchar(RowData + 1); 					//数据长度:偏移2- 1,2
				Addr = CharToHexInt(RowData + 3) ;						//起始地址:偏移4- 3,4,5,6
				Addr|= (OffsetAddress << 16);
				Type = CharToHexUchar(RowData + 7);						//类型:偏移2 -7,8
				switch(Type)
				{
					case 0x00:											//数据
						if(Addr  > (ReLen + ReAddr))					//判断为新数据块
						{
							if(RowDataByte == 0)						//是否为首行数据字节数
							{ 
								HexFile->BlockStartAddr[HexFile->HexBlockTotalNumber] = Addr;//记录新数据块的起始地址
							}
							else										//不是首行
							{
								HexFile->BlockDataLength[HexFile->HexBlockTotalNumber]= RowDataByte;//数据长度  
								RowDataByte = 0;						//重新开始计数
								HexFile->BlockStartAddr[++HexFile->HexBlockTotalNumber] = Addr;		//记录新数据块的起始地址
							}
						}
						for(i = 0;i < Len; i++)							
						{   
							HexFile->HexBlockData[HexFile->HexBlockTotalNumber][RowDataByte++] = CharToHexUchar(RowData + 9 + i*2);	//数据: 9,10起始
						}
						ReAddr = Addr;									//保存当前地址,下一次使用  
						ReLen  = Len;									//保存当前长度,下一次使用
						break;
					case 0x04:										   	//扩展线性地址记录
						OffsetAddress =  CharToHexInt(RowData + 9);		//偏移地址	 
						break;
					case 0x01:										   	//地址,结束
						HexFile->BlockDataLength[HexFile->HexBlockTotalNumber]= RowDataByte;				//数据长度 
						HexFile->HexBlockTotalNumber++;
						break;
				}
			}
		}
		fclose(fp);
		StringUpperCase(FileName);
		Msg(FileName); 
		Msg("\r\nHex文件读取成功, 大小%d字节, 数据分块:%d \r\n",size,HexFile->HexBlockTotalNumber);
		for(i = 0; i < HexFile->HexBlockTotalNumber; i++)
		{
			HexFile->HexTotalByteNumber += HexFile->BlockDataLength[i];
			Msg("数据块:%d,  起始地址:0x%.4X, 结束地址:0x%.4X, 数据长度:%6d字节\r\n", i+1, HexFile->BlockStartAddr[i], HexFile->BlockStartAddr[i] + HexFile->BlockDataLength[i] - 1, HexFile->BlockDataLength[i]);
		}
	}
	else
	{
		Msg("Hex文件不存在,%s\r\n",FileName);
	}
}
  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值