原文网址:iOS hex文件转bin文件_Snow_Bing的博客-CSDN博客

hex文件转换bin文件有两种方式:
1.通过软件的方式,软件的方式我是通过软件J-Flash来转换的。具体操作流程如下:

(1)打开J-Flash选择Create a new project。

(2)把hex文件拖入J-Flash 。

(3)找到hex文件对应的结束的最后一位的位置。

(4)选择Save data file as 保存类型选bin类型,然后点击保存之后弹出Enter address range框 start address 保持不变,End address 输入你想要转换文件的结束地址,然后点击OK hex转bin文件转换成功。

2.通过到代码的方式。转换的代码如下:

//
//  LBHexToBin.h
//  BleDemo
//
//  Created by Zhang Jonathan on 2022/11/7.
//  Copyright © 2022 Jonathan. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LBHexToBin : NSObject

+ (NSData*)convert:(NSData*)hex;

@end

NS_ASSUME_NONNULL_END

  

//
//  LBHexToBin.m
//  BleDemo
//
//  Created by Zhang Jonathan on 2022/11/7.
//  Copyright © 2022 Jonathan. All rights reserved.
//

#import "LBHexToBin.h"

@implementation LBHexToBin

+ (const Byte)ascii2char:(const Byte*)ascii
{

    if(*ascii >='A')
     return*ascii -0x37;

    if(*ascii >='0')
     return*ascii -'0';

    return -1;
}

+ (const Byte)readByte:(const Byte*)pointer
{
    Byte first = [LBHexToBin ascii2char:pointer];
    Byte second = [LBHexToBin ascii2char:pointer +1];
    return(first <<4) | second;
}

+ (const UInt16)readAddress:(const Byte*)pointer
{
    Byte msb = [LBHexToBin readByte:pointer];
    Byte lsb = [LBHexToBin readByte:pointer +2];
    return(msb <<8) | lsb;
}

+ (NSUInteger)calculateBinLength:(NSData*)hex
{
    if(hex ==nil|| hex.length==0){
        return 0;
    }

    NSUInteger binLength =0;
    const NSUInteger hexLength = hex.length;
    const Byte* pointer = (const Byte*)hex.bytes;
    UInt32 lastBaseAddress =0;

    do
    {
        const Byte semicollon = *pointer++;
        // Validate - each line of the file must have a semicollon as a firs char
        if(semicollon !=':'){
            return 0;
        }

         const UInt8 reclen = [LBHexToBin readByte:pointer]; pointer +=2;
         const UInt16 offset = [LBHexToBin readAddress:pointer]; pointer +=4;
         const UInt8 rectype = [LBHexToBin readByte:pointer]; pointer +=2;
         switch(rectype) {
             case 0x04: {
                // Only consistent hex files are supported. If there is a jump to non-following ULBA address skip the rest of the file

                 const UInt32 newULBA = [LBHexToBin readAddress:pointer];
                 
                 if(binLength >0&& newULBA != (lastBaseAddress >>16) +1)
                     return binLength;

                 lastBaseAddress = newULBA <<16;
                 break;
             }

             case 0x02: {
                // The same with Extended Segment Address. The calculated ULBA must not be greater than the last one + 1

                 const UInt32 newSBA = [LBHexToBin readAddress:pointer] <<4;

                 if(binLength >0&& (newSBA >>16) != (lastBaseAddress >>16) +1)
                     return binLength;
                 lastBaseAddress = newSBA;

                 break;
            }

             case 0x00:
                // If record type is Data Record (rectype = 0), add it's length (only it the address is >= 0x1000, MBR is skipped)

                 if(lastBaseAddress + offset >=0x1000)
                     binLength += reclen;

             default:
                 break;
        }

        pointer += (reclen <<1);  // Skip the data when calculating length
        pointer +=2;  // Skip the checksum

        // Skip new line
        if(*pointer =='\r') pointer++;
        if(*pointer =='\n') pointer++;

    }while(pointer != hex.bytes+ hexLength);

    return binLength;

}

+ (NSData*)convert:(NSData*)hex{

    const NSUInteger binLength = [LBHexToBin calculateBinLength:hex];
    const NSUInteger hexLength = hex.length;
    const Byte* pointer = (const Byte*)hex.bytes;
    NSUInteger bytesCopied =0;
    UInt32 lastBaseAddress =0;

    Byte* bytes =malloc(sizeof(Byte) * binLength);
    Byte* output = bytes;

    do
    {
        const Byte semicollon = *pointer++;

        // Validate - each line of the file must have a semicollon as a firs char
        if(semicollon !=':')
        {
            free(bytes);
            return nil;
        }

        const UInt8 reclen = [LBHexToBin readByte:pointer]; pointer +=2;
        const UInt16 offset = [LBHexToBin readAddress:pointer]; pointer +=4;
        const UInt8 rectype = [LBHexToBin readByte:pointer]; pointer +=2;
        
        switch(rectype) {

            case 0x04: {
                const UInt32 newULBA = [LBHexToBin readAddress:pointer]; pointer +=4;
                
                if(bytesCopied >0&& newULBA != (lastBaseAddress >>16) +1)
                    return[NSData dataWithBytesNoCopy:bytes length:bytesCopied];

                lastBaseAddress = newULBA <<16;

                break;
            }
            case 0x02: {
                const UInt32 newSBA = [LBHexToBin readAddress:pointer] <<4; pointer +=4;
                
                if(bytesCopied >0&& (newSBA >>16) != (lastBaseAddress >>16) +1)
                    return [NSData dataWithBytesNoCopy:bytes length:bytesCopied];

                lastBaseAddress = newSBA;
                break;
            }
            case 0x00:
                // If record type is Data Record (rectype = 0), copy data to output buffer
                // Skip data below 0x1000 address (MBR)

                if(lastBaseAddress + offset >=0x1000)
                {
                    for(int i =0; i < reclen; i++)
                    {
                        *output++ = [LBHexToBin readByte:pointer]; pointer +=2;
                        bytesCopied++;
                    }
                }else{
                    pointer += (reclen <<1);  // Skip the data
                }
                break;
            default:
                pointer += (reclen <<1);  // Skip the irrelevant data
                break;

        }
        pointer +=2;  // Skip the checksum
        
        // Skip new line
        if(*pointer =='\r') pointer++;
        if(*pointer =='\n') pointer++;

    }while(pointer != hex.bytes+ hexLength);

    return[NSData dataWithBytesNoCopy:bytes length:bytesCopied];

}

@end