| 特性 | Bin (Binary) | Hex (Intel HEX) |
|---|---|---|
| 內容 | 純二進位機器碼 | ASCII 文字記錄 |
| 位址資訊 | 無 (需外部指定偏移) | 每記錄含載入位址 |
| 檢驗和 | 無 | 每行有 Checksum |
| 適用場景 | 大量生產燒錄、固件升級 | 開發除錯、通用燒錄器 |
:LLAAAATTDD...DDCC │ │ │ └─ Data (0~255 bytes) │ │ └──── Record Type (00=Data, 01=EOF, 02=Ext Segment, 04=Ext Linear) │ └────── Address (16-bit, big-endian) └──────── Length (byte count)
Checksum = 兩位元組補數:0x100 - (LL + AA_H + AA_L + TT + ΣDD) & 0xFF
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef struct {
uint8_t len;
uint8_t addr_hi, addr_lo;
uint8_t type;
const uint8_t *data;
} HexRecord;
// 將一筆記錄編碼為 HEX 字串,回傳寫入長度
int encode_hex_record(char *out, const HexRecord *rec) {
int pos = 0;
uint8_t sum = rec->len + rec->addr_hi + rec->addr_lo + rec->type;
pos += sprintf(out, ":%02X%02X%02X%02X", rec->len, rec->addr_hi, rec->addr_lo, rec->type);
for (uint8_t i = 0; i < rec->len; ++i) {
pos += sprintf(out + pos, "%02X", rec->data[i]);
sum += rec->data[i];
}
uint8_t checksum = (uint8_t)(-sum); // 兩位元組補數
pos += sprintf(out + pos, "%02X", checksum);
out[pos++] = '\n';
return pos;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define LINE_MAX_BYTES 16 // 每行 16 位元組 (可調 16/32/64)
int bin2hex(const char *bin_path, const char *hex_path) {
FILE *fbin = fopen(bin_path, "rb");
if (!fbin) { perror("open bin"); return -1; }
FILE *fhex = fopen(hex_path, "w");
if (!fhex) { perror("open hex"); fclose(fbin); return -1; }
fseek(fbin, 0, SEEK_END);
long fsize = ftell(fbin);
fseek(fbin, 0, SEEK_SET);
uint8_t buf[LINE_MAX_BYTES];
uint32_t addr = 0; // 線性位址
uint32_t last_high16 = 0xFFFFFFFF;
while (addr < fsize) {
uint32_t high16 = (addr >> 16) & 0xFFFF;
if (high16 != last_high16) { // 需發出 Extended Linear Address Record (Type 04)
HexRecord er = {2, 0, 0, 0x04, (uint8_t[]){high16 >> 8, high16 & 0xFF}};
char line[64];
encode_hex_record(line, &er);
fputs(line, fhex);
last_high16 = high16;
}
size_t chunk = (fsize - addr >= LINE_MAX_BYTES) ? LINE_MAX_BYTES : (fsize - addr);
fread(buf, 1, chunk, fbin);
HexRecord dr = {
(uint8_t)chunk,
(uint8_t)((addr >> 8) & 0xFF), // 高 8 位
(uint8_t)(addr & 0xFF), // 低 8 位
0x00, // Data Record
buf
};
char line[80];
encode_hex_record(line, &dr);
fputs(line, fhex);
addr += chunk;
}
// EOF Record
fputs(":00000001FF\n", fhex);
fclose(fbin);
fclose(fhex);
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
return bin2hex(argv[1], argv[2]);
}
$ gcc bin2hex.c -o bin2hex $ ./bin2hex firmware.bin firmware.hex $ head -5 firmware.hex :1000000000112233445566778899AABBCCDDEEFF00 :10001000112233445566778899AABBCCDDEEFF0010 :0400000400010000FB :10000000FFEEDDCCBBAA99887766554433221100EF :00000001FF
:00000001FF