标题:
仿STC-ISP写的Linux版编程烧录软件,附源代码
[打印本页]
作者:
mp3
时间:
2019-3-24 10:45
标题:
仿STC-ISP写的Linux版编程烧录软件,附源代码
本帖最后由 mp3 于 2019-3-25 08:48 编辑
只在STC11F04E单片机上试用过,其它型号可能要修改通信协议,可通过串口监控工具分析。
单片机脱机烧录源程序如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <ctype.h>
#pragma pack(1)
// config MCU clock
#define MCU_CONFIG
//#define MCU_6TO6
//#define MCU_6TO12
//#define MCU_12TO12
//#define MCU_12TO6
#ifdef MCU_6TO6
#define MCU_CLOCK
#endif
#ifdef MCU_6TO12
#define MCU_CLOCK
#endif
#ifdef MCU_12TO12
#define MCU_CLOCK
#define MCU_CLOCK_12MHZ
#undef MCU_CONFIG
#endif
#ifdef MCU_12TO6
#define MCU_CLOCK
#define MCU_CLOCK_12MHZ
#endif
#ifndef MCU_CLOCK
#error "You must define MCU clock!"
#endif
#define VERSION "0.1"
#define DEFAULT_PORT "/dev/ttyS1"
#define LOW_BAUD B2400
#ifdef MCU_CLOCK_12MHZ
#define HIGH_BAUD B57600
#define MSG_HIGH_BAUD "57600bps"
#else
#define HIGH_BAUD B38400
#define MSG_HIGH_BAUD "38400bps"
#endif
#define BUFFSIZE 1024
#define TIMEOUT 2
#define BLOCK_SIZE 128
#define PKG_MINIMAL_LEN 9
#define PKG_SIGN1 '\x46'
#define PKG_SIGN2 '\xb9'
#define PKG_SIGN3 '\x16'
#define PKG_SIGN 0x46b9
enum pkg_type {
PKG_TYPE1=0x68,
PKG_TYPE2=0x6a,
};
enum pkg_code {
CODE_INFO=0x50,
CODE_MODI=0x8f,
CODE_NEWB=0x8e,
CODE_ERASE=0x84,
CODE_DATA=0x00,
CODE_END =0x69,
CODE_CONF=0x8d,
CODE_BYE =0x82,
};
int port_fd=-1;
FILE *rom_file;
int file_length;
int debug=0;
enum pkg_code step;
int block_no;
struct timeval start_tv;
typedef unsigned int uint32;
typedef unsigned short int uint16;
typedef unsigned char uint8;
// Package format: head + data + tail
typedef struct _pkg_head {
uint16 sign; // 0x46b9
uint8 type; // 68: MCU to PC; 6a: PC to MCU
uint16 lenth; // from 'type' to 'pkg_tail.sign'
uint8 code;
} pkg_head, *ppkg_head;
typedef struct _pkg_tail {
uint16 cksum; // from 'pkg_head.type' to 'data'
uint8 sign; // 0x16
} pkg_tail, *ppkg_tail;
typedef struct _pkg_data_head {
uint16 dummy; // always 0x0000
uint16 addr; // start addr
uint16 lenth; // 0x0080
} pkg_data_head, *ppkg_data_head;
void print_data(char *data, int len)
{
unsigned char ch;
int i, j;
printf("Length: %x\n", len);
for(i=0; i<len; i++) {
ch=data[i];
if((i&0x0f)==0)
printf("%04x: ", i);
if((i&0x07)!=0x07)
printf("%02x ", ch);
else
if((i&0x0f)!=0x0f)
printf("%02x-", ch);
else {
printf("%02x ", ch);
for(j=0x0f; j>=0; j--) {
ch=data[i-j];
if(!isascii(ch) || iscntrl(ch))
ch='.';
putchar(ch);
}
putchar('\n');
}
}
if(len&0x0f) {
for(; i<(len&~0x0f)+0x10; i++)
printf(" ");
putchar(' ');
for(j=len&~0x0f; j<len; j++) {
ch=data[j];
if(!isascii(ch) || iscntrl(ch))
ch='.';
putchar(ch);
}
putchar('\n');
}
}
enum dbg_type {RECV, SEND};
void print_dbg(int type, char *buf, int buf_len)
{
struct timeval tv;
unsigned int sec, usec;
if(debug) {
if(type==SEND)
printf("\n[Send]\t\t");
else
printf("\n[Received]\t");
gettimeofday(&tv, NULL);
if(start_tv.tv_usec>tv.tv_usec) {
usec=tv.tv_usec-start_tv.tv_usec+1000000;
sec=tv.tv_sec-start_tv.tv_sec-1;
} else {
usec=tv.tv_usec-start_tv.tv_usec;
sec=tv.tv_sec-start_tv.tv_sec;
}
printf("[%d.%06d]\n", sec, usec);
printf("Step: %02x\t", step);
print_data(buf, buf_len);
}
}
int checksum(char *buf, int buf_len)
{
int i, sum=0;
for(i=0; i<buf_len; i++)
sum+=(unsigned char)buf[i];
return sum;
}
// return: -1: bad pkg; >=0: pkg start position
int check_pkg(int code, char *buf, int buf_len)
{
int i, len;
ppkg_head ph=NULL;
ppkg_tail pt=NULL;
for(i=0; i<buf_len; i++) {
if(buf[i]==PKG_SIGN1 && buf[i+1]==PKG_SIGN2 && i+PKG_MINIMAL_LEN<=buf_len) {
ph=(ppkg_head)buf+i;
if(ph->type==PKG_TYPE1 && ph->code==code) {
len=ntohs(ph->lenth);
pt=(ppkg_tail)((char *)ph+len-1);
if(pt->sign==PKG_SIGN3 && ntohs(pt->cksum)==checksum((char *)ph+2, len-3)) break;
pt=NULL;
break;
}
}
}
if(ph==NULL || pt==NULL)
i=-1;
return i;
}
typedef struct port_info {
int port_fd;
int baud_rate;
char parity;
char stop_bit;
char flow_ctrl;
char data_bits;
} *pport_info;
int set_port(pport_info p_info)
{
struct termios old_opt,new_opt;
memset(&old_opt,0,sizeof(old_opt));
memset(&new_opt,0,sizeof(new_opt));
cfmakeraw(&new_opt);
tcgetattr(p_info->port_fd,&old_opt);
//修改new_opt结构中的串口输入/输出波特率参数
cfsetispeed(&new_opt,p_info->baud_rate);
cfsetospeed(&new_opt,p_info->baud_rate);
//修改控制模式,保证程序不会占用串口
new_opt.c_cflag |=CLOCAL;
//修改控制模式,使得能够从串口中读取输入数据
new_opt.c_cflag |=CREAD;
/*===========设置数据流控制==========*/
switch(p_info->flow_ctrl){
case '0':
//不使用流控制
new_opt.c_cflag &=~CRTSCTS;
break;
case '1':
//使用硬件进行流控制
new_opt.c_cflag |=CRTSCTS;
break;
case '2':
new_opt.c_cflag |= IXON | IXOFF | IXANY;
break;
}
/*===========设置数据位============*/
new_opt.c_cflag &=~CSIZE;
switch(p_info->data_bits){
case '5':
new_opt.c_cflag |=CS5;
break;
case '6':
new_opt.c_cflag |=CS6;
break;
case '7':
new_opt.c_cflag |=CS7;
break;
case '8':
new_opt.c_cflag |=CS8;
break;
default:
new_opt.c_cflag |=CS8;
}
/*===========设置奇偶效验位==========*/
switch(p_info->parity){
case '0': //不使用奇偶效验
new_opt.c_cflag &=~PARENB;
break;
case '1': //使用偶效验
new_opt.c_cflag |=PARENB;
new_opt.c_cflag &=~PARODD;
break;
case '2': //使用奇效验
new_opt.c_cflag |=PARENB;
new_opt.c_cflag |=PARODD;
break;
}
/*============设置停止位===========*/
if(p_info->stop_bit=='2')
new_opt.c_cflag |=CSTOPB;
else
new_opt.c_cflag &=~CSTOPB;
//修改输出模式,原始数据输出
new_opt.c_oflag &=~OPOST;
//修改控制字符,读取字符的最少个数为1
new_opt.c_cc[VMIN]=1;
//修改控制字符,读取第一个字符等待1*(1/10)s
new_opt.c_cc[VTIME]=1;
//如果发生数据溢出,接收数据,但是不再读取
tcflush(p_info->port_fd,TCIFLUSH);
int result=tcsetattr(p_info->port_fd,TCSANOW,&new_opt);
if(result==-1){
perror("Cannot set the serial port parameters");
return -1;
}
tcgetattr(p_info->port_fd,&old_opt);
return result;
}
int open_port(char *port_name, int baud_rate)
{
int port_fd;
if((port_fd=open(port_name, O_RDWR | O_NOCTTY | O_NONBLOCK))==-1){
fprintf(stderr, "Failed to open serial port: %s\n", port_name);
return -1;
}
//设置串口通信参数
struct port_info info;
info.port_fd=port_fd;
info.baud_rate=baud_rate;
info.data_bits='8';
info.flow_ctrl='0';
info.stop_bit='1';
info.parity='1';
if(set_port(&info)==-1) {
fprintf(stderr, "Failed to setup serial port: %s\n", port_name);
close(port_fd);
return -1;
}
return port_fd;
}
void close_port()
{
if(rom_file!=NULL) {
fclose(rom_file);
rom_file=NULL;
}
if(port_fd!=-1) {
close(port_fd);
port_fd=-1;
}
}
void reopen_port(char *port_name, int baud_rate)
{
if(port_fd!=-1)
close(port_fd);
if((port_fd=open_port(port_name, baud_rate))==-1)
{
close_port();
exit(1);
}
}
int send_data(int fd, char *data, int data_len)
{
int len=write(fd, data, data_len);
//如果出现溢出的情况
if(len!=data_len)
tcflush(fd, TCOFLUSH);
return len;
}
int send_mcu(int fd, char *data, int data_len)
{
int i, len=0, total=0;
for(i=0; i<data_len; i++) {
usleep(150);
len=send_data(fd,data+i,1);
if(len>0)
total+=len;
}
print_dbg(SEND, data, total);
return total;
}
int recv_data(int fd, char *data, int data_len)
{
static int timeout=0;
int len=0, fs_sel;
fd_set fs_read;
struct timeval time;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
if(step==CODE_MODI)
timeout=TIMEOUT;
time.tv_sec=timeout;
time.tv_usec=10000;
//使用select实现串口的多路通信
fs_sel=select(fd+1, &fs_read, NULL, NULL, &time);
if(fs_sel)
len=read(fd, data, data_len);
return len;
}
int recv_mcu(int fd, char *buf, int buf_len)
{
int i, len=0;
do {
if(step==CODE_INFO)
usleep(100000);
i=recv_data(fd, buf+len, buf_len-len);
if(i>0) len+=i;
if(check_pkg(step, buf, len)>=0)
break;
} while(i>0);
return len;
}
int check_recv(int expect_code, char *buf, int buf_len) {
int i;
print_dbg(RECV, buf, buf_len);
i=check_pkg(expect_code, buf, buf_len);
if(i<0) {
printf("\nError received data\n");
close_port();
exit(1);
}
return i;
}
void mcu_info(char *buf, int buf_len) {
int i, len;
ppkg_head ph;
ppkg_tail pt;
ph=(ppkg_head)buf;
len=ntohs(ph->lenth);
pt=(ppkg_tail)((char *)ph+len-1);
/*
MCU Type is: STC11F04E
MCU Firmware Version: 6.5K
Next Power-Up-Reset, use External Crystal/Clock
RESET/P3.6 is used as RESET
Power-Up Reset,add extra Reset-Delay-Time
Oscillator Gain: High gain
P1.0/P1.1 are not related to STC ISP Programming
Next ISP Programming Code,don't erase EEPROM data
Wait n clocks after MCU is waked up: 32768
Low Voltage Reset, when MCU-VCC < 4.1V
WDT_CONTR be write-protected except CLR_WDT:NO
WDT is enabled automatically during power-up:NO
Stop WatchDog Timer counting in Idle mode: YES
Pre-scale time of WDT(did not start): 256
MCU Clock:12.019038MHz.
*/
i=sizeof(pkg_head)+16;
printf("\n\nMCU Type: \n");
printf("MCU Firmware Version: %1d.%1d%c\n", buf[i]>>4&0x0f, buf[i]&0x0f, buf[i+1]);
i=ntohl(*((int *)((char *)pt-4)));
printf("MCU Internal Clock: %2d.%6dMhz\n", i/1000000, i%1000000);
}
//return: pkg length
int make_pkg(int code, char *inbuf, int ibuf_len, char *outbuf, int obuf_len)
{
int i, len;
ppkg_head ph;
ppkg_tail pt;
ppkg_data_head pd;
static char request_mcu[]={
0x46,0xB9,0x6A,0x00,0x0D,0x50,0x09,0x00,0x36,0x01,0xE2,0x24,0x02,0x0D,0x16};
static char erase[]={
0x46,0xB9,0x6A,0x00,0x8C,0x84,0xFF,0x00,0x02,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static char end[]={
0x46,0xB9,0x6A,0x00,0x0D,0x69,0x09,0x00,0x36,0x01,0xE2,0x24,0x02,0x26,0x16};
static char bye[]={
0xFE,0xFE,0xFE,0xFE,0x46,0xB9,0x6A,0x00,0x07,0x82,0x00,0xF3,0x16};
/* 38400bps @ 6.2MHz, internal clock */
#ifdef MCU_6TO6
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF6,0x3F,0x14,0x2D,0x84,0x03,0xC0,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF6,0x3F,0x14,0x2D,0x03,0x3A,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7D,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x5E,0x90,0x04,0x11,0x2A,0x16};
#endif
/* 38400bps @ 6.2MHz, change 6.2MHz to 12MHz */
#ifdef MCU_6TO12
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF6,0x3F,0x14,0x2D,0x84,0x03,0xC0,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF6,0x3F,0x14,0x2D,0x03,0x3A,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7F,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x5E,0x27,0x41,0x11,0x00,0x16};
#endif
/* 57600bps @ 12MHz, change back to 6.2MHz if run conf_mcu() */
#ifdef MCU_CLOCK_12MHZ
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF3,0x3F,0x1A,0x2D,0x83,0x03,0xC2,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF3,0x3F,0x1A,0x2D,0x03,0x3D,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7D,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xB7,0x65,0x5E,0x11,0xB2,0x16};
#endif
switch(code) {
case CODE_INFO:
len=sizeof(request_mcu);
memcpy(outbuf, request_mcu, len);
break;
case CODE_MODI:
len=sizeof(inform_change);
memcpy(outbuf, inform_change, len);
break;
case CODE_NEWB:
len=sizeof(confirm_newrate);
memcpy(outbuf, confirm_newrate, len);
break;
case CODE_ERASE:
len=sizeof(erase);
memcpy(outbuf, erase, len);
*(short int *)(outbuf+7)=htons((file_length+255)>>8);
for(i=0x80; i>=0x0e; i--)
outbuf[len++]=i;
i=htons(checksum(outbuf+2, len-2));
*(int *)(outbuf+len)=i;
len+=2;
outbuf[len++]=PKG_SIGN3;
break;
case CODE_DATA:
ph=(ppkg_head)outbuf;
ph->sign=htons(PKG_SIGN);
ph->type=PKG_TYPE2;
i=sizeof(pkg_head)+sizeof(pkg_data_head);
len=i+ibuf_len+sizeof(pkg_tail);
ph->lenth=htons(len-2);
ph->code=CODE_DATA;
pd=(ppkg_data_head)(outbuf+sizeof(pkg_head));
pd->dummy=htons(0x0000);
pd->addr=htons(block_no*BLOCK_SIZE);
pd->lenth=htons(ibuf_len);
memcpy(outbuf+i, inbuf, ibuf_len);
pt=(ppkg_tail)(outbuf+i+ibuf_len);
pt->cksum=htons(checksum(outbuf+2, i+ibuf_len-2));
pt->sign=PKG_SIGN3;
break;
case CODE_END:
len=sizeof(end);
memcpy(outbuf, end, len);
break;
case CODE_CONF:
len=sizeof(config);
memcpy(outbuf, config, len);
break;
case CODE_BYE:
len=sizeof(bye);
memcpy(outbuf, bye, len);
break;
default:
fprintf(stderr, "make_pkg(): invalid package code\n");
len=0;
}
return len;
}
// return: 0: fail; 1: success
int conf_mcu(char *port_name, int baud_rate)
{
int i, len=0;
char recv_buf[BUFFSIZE], send_buf[BUFFSIZE];
reopen_port(port_name, baud_rate);
step=CODE_CONF;
len=make_pkg(step, recv_buf, len, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
step=CODE_INFO;
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
step=CODE_BYE;
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_data(port_fd, send_buf, len);
close_port();
if(i>=0)
i=1;
else
i=0;
return i;
}
void help(char *cmd_name)
{
printf("STC MCU flash ROM programmer, Version " VERSION " (2011), GPLv2 Lisence\n");
printf("Warning: this is not an official release, use it on your own risk.\n\n");
printf("Surpport MCU type: STC11F04E\n\n");
printf("Usage:\n %s [options] [.bin filename]\n\n", cmd_name);
printf("Options:\n -h\t\tprint this text\n"
" -d dev\tuse given device, default: " DEFAULT_PORT "\n"
" -D\t\tenable debug output\n");
exit(0);
}
int main(int argc, char *argv[])
{
static char default_dev[]=DEFAULT_PORT;
char *port_name=default_dev;
char *file_name=NULL;
int i, len;
char recv_buf[BUFFSIZE], send_buf[BUFFSIZE];
while((i=getopt(argc, argv, "hd:D"))!=-1) {
switch(i) {
case 'h':
help(argv[0]);
break;
case 'd':
port_name=optarg;
break;
case 'D':
debug=1;
break;
case '?':
exit(1);
}
}
for(; optind<argc; optind++) {
file_name=argv[optind];
break;
}
if(file_name!=NULL) {
if(strcasestr(file_name, ".bin")==NULL) {
fprintf(stderr, "Invalid file name\n");
exit(1);
}
rom_file=fopen(file_name, "rb");
if(rom_file==NULL) {
fprintf(stderr, "Cannot open file\n");
exit(1);
}
i=fileno(rom_file);
if(fstat(i, (struct stat *)recv_buf)==-1) {
perror("Cannot get length of the file\n");
close_port();
exit(1);
}
file_length=((struct stat *)recv_buf)->st_size;
}
printf("Use port %s\n", port_name);
printf("Connecting to target MCU at 2400bps ... ");
if((port_fd=open_port(port_name, LOW_BAUD))==-1)
exit(1);
// Power off and power on MCU via DTR & RTS signal
ioctl(port_fd, TIOCMGET, &i);
i&=~(TIOCM_RTS | TIOCM_DTR);
ioctl(port_fd, TIOCMSET, &i);
usleep(100000);
i|=TIOCM_RTS | TIOCM_DTR;
ioctl(port_fd, TIOCMSET, &i);
step=CODE_INFO;
for(i=150; i>0; i--) {
len=send_data(port_fd, "\x7f\x7f\x7f\x7f", 4);
if(len<1) {
printf("\b\bSend data failed\n");
close_port();
exit(1);
}
if(i%5==0) {
printf("\b\b%2d", i/5);
fflush(stdout);
}
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
if(len>=PKG_MINIMAL_LEN)
break;
}
if(len<PKG_MINIMAL_LEN) {
printf("\b\bFailed\n");
close_port();
exit(1);
}
gettimeofday(&start_tv, NULL);
i=check_recv(step, recv_buf, len);
mcu_info(recv_buf+i, len-i);
if(rom_file==NULL) {
close_port();
exit(0);
}
// confirm MCU, procedure: make_pkg -> send -> recv -> check_recv
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
step=CODE_MODI;
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
// Inform to modify baud rate
if(debug) printf("\nInform MCU to modify baud rate ...\n");
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
reopen_port(port_name, HIGH_BAUD);
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
// Send at 2400bps to confirm the new baud rate
if(debug) printf("\nConfirm MCU with new baud rate ... \n");
step=CODE_NEWB;
reopen_port(port_name, LOW_BAUD);
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
// Change to new baud rate
printf("\nReconnecting to target MCU at " MSG_HIGH_BAUD " ... ");
step=CODE_ERASE;
reopen_port(port_name, HIGH_BAUD);
********余下代码下载附件*********
复制代码
所有资料51hei提供下载:
stc-isp.rar
(5.88 KB, 下载次数: 68)
2019-3-24 10:38 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
51hei团团
时间:
2019-3-25 03:29
高手,能不能请教下如何编译,这些头文件怎么办?
作者:
mp3
时间:
2019-3-25 08:46
51hei团团 发表于 2019-3-25 03:29
高手,能不能请教下如何编译,这些头文件怎么办?
忘了说明,这个是在Linux下用。
作者:
51hei团团
时间:
2019-3-25 16:53
牛逼的作品.好资料,51黑有你更精彩!!!
作者:
hzjgyr
时间:
2019-8-21 02:26
如果你们看见,能写中文注释吗?看不懂呀
作者:
闲来无事
时间:
2019-12-11 20:46
好东西,不知道楼主能否联系一下,想要定做一款isp
作者:
jk8363298
时间:
2020-2-11 23:40
大神,正想找这样的资料,膜拜下先
作者:
860451472
时间:
2020-3-13 10:28
正有需要,感谢大佬分享。
作者:
Lprong
时间:
2020-3-13 17:45
哇,好棒的程序!
作者:
a461624201
时间:
2020-7-21 19:40
sudo gcc stc-isp.c -o stc-isp 会出现错误
解决:www点cnblogs点com/liwei0526vip/p/4873109.html
作者:
a461624201
时间:
2020-7-21 22:12
转载:www点cnblogs点com/sky1991/archive/2012/08/08/2627575.html
用 objcopy 也可以把 hex文件转化为bin'文件,姑且我就先这么用了。
生成hex文件后,用如下命令将hex转化为bin
objcopy -I ihex -O binary liushui.hex liushui.bin # I 和O 都是大写
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1