我是靠谱客的博主 勤恳小白菜,最近开发中收集的这篇文章主要介绍linux开发 stc_仿STC-ISP写的Linux版编程烧录软件,附源代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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: %xn", len);

for(i=0; 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

printf("   ");

putchar(' ');

for(j=len&~0x0f; 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]tt");

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: %02xt", step);

print_data(buf, buf_len);

}

}

int checksum(char *buf, int buf_len)

{

int i, sum=0;

for(i=0; 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

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: %sn", 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: %sn", 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

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 datan");

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("nnMCU Type: n");

printf("MCU Firmware Version: %1d.%1d%cn", buf[i]>>4&0x0f, buf[i]&0x0f, buf[i+1]);

i=ntohl(*((int *)((char *)pt-4)));

printf("MCU Internal Clock: %2d.%6dMhzn", 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 coden");

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 Lisencen");

printf("Warning: this is not an official release, use it on your own risk.nn");

printf("Surpport MCU type: STC11F04Enn");

printf("Usage:n  %s [options] [.bin filename]nn", cmd_name);

printf("Options:n  -httprint this textn"

"  -d devtuse given device, default: " DEFAULT_PORT "n"

"  -Dttenable debug outputn");

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

file_name=argv[optind];

break;

}

if(file_name!=NULL) {

if(strcasestr(file_name, ".bin")==NULL) {

fprintf(stderr, "Invalid file namen");

exit(1);

}

rom_file=fopen(file_name, "rb");

if(rom_file==NULL) {

fprintf(stderr, "Cannot open filen");

exit(1);

}

i=fileno(rom_file);

if(fstat(i, (struct stat *)recv_buf)==-1) {

perror("Cannot get length of the filen");

close_port();

exit(1);

}

file_length=((struct stat *)recv_buf)->st_size;

}

printf("Use port %sn", 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, "x7fx7fx7fx7f", 4);

if(len<1) {

printf("bbSend data failedn");

close_port();

exit(1);

}

if(i%5==0) {

printf("bb%2d", i/5);

fflush(stdout);

}

len=recv_mcu(port_fd, recv_buf, BUFFSIZE);

if(len>=PKG_MINIMAL_LEN)

break;

}

if(len

printf("bbFailedn");

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);

********余下代码下载附件*********

最后

以上就是勤恳小白菜为你收集整理的linux开发 stc_仿STC-ISP写的Linux版编程烧录软件,附源代码的全部内容,希望文章能够帮你解决linux开发 stc_仿STC-ISP写的Linux版编程烧录软件,附源代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部