搜索
bottom↓
回复: 81

芯片脱机复制机(带电路图、源码及烧录文件)

[复制链接]

出0入228汤圆

发表于 2007-10-20 14:10:48 | 显示全部楼层 |阅读模式
前一阵帮人家做了一些小设备,板上预留了6芯ICSP座,偏偏客户居然不用PC机的,用MAC,而我又没有MAC机,没法试验怎么在MAC下升级.

没办法只得想其他办法让他能够自己升级.就做了这个东西:读出源芯片内容复制到目标设备上.
图中:

U3为主控芯片,
U1为源芯片(做板时做成IC座,换起来方便些)
ICSP0接目标芯片ICSP.(也可与U1一样做成IC座)

DS3:待机灯
DS2:运行指示
DS1:ERROR
在串口有调试信息输出,可接PC查看.(用19200速率)
使用时:
接好源芯片与目标芯片.按下S1按钮即可.

由于我没有其他芯片,只在MEGA8,16M上测试通过.

点击此处下载ourdev_177573.rar(文件大小:15K)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入228汤圆

 楼主| 发表于 2007-10-20 14:21:35 | 显示全部楼层

出0入0汤圆

发表于 2007-10-20 14:44:03 | 显示全部楼层
帮你顶
是不很明白,个人智商不高。
看起来很爽,市场价也要近二百一只呀,先收下再慢慢看

出0入8汤圆

发表于 2007-10-20 14:54:58 | 显示全部楼层
急需这东西,不知能否上复制已加密的源芯片,因为一般都要加密了才转交他人.想了解源码,不知是否方便,谢谢

出0入228汤圆

 楼主| 发表于 2007-10-20 14:57:57 | 显示全部楼层
呵,加密的应该不行吧,我没试呢.
头像被屏蔽

出0入0汤圆

发表于 2007-10-20 14:59:29 | 显示全部楼层
【4楼】 wxws 能否将源代码也传上来? 这样本贴就会达到COOL贴的份量,对其它人也更有参考价值了。谢谢。

出0入0汤圆

发表于 2007-10-20 15:01:24 | 显示全部楼层
呵呵,关注中,

出0入228汤圆

 楼主| 发表于 2007-10-20 15:19:28 | 显示全部楼层
呵,我用的是傻瓜式开发平台,贴上来怕大家不明白呀.

出0入8汤圆

发表于 2007-10-20 17:42:48 | 显示全部楼层
关注中,顶顶
头像被屏蔽

出0入0汤圆

发表于 2007-10-20 17:45:11 | 显示全部楼层
【7楼】 wxws ,

呵呵,如果你没有打算将它作为商业用途,上传上来方便其它人,也方便自己啊。说不一定以后某一天你要重新找回这代码,在自己的电脑上已经找不到,回到这里就能找到呢。

我就经常发现这样 :)

出0入8汤圆

发表于 2007-10-20 17:51:55 | 显示全部楼层
大伙要顶啊

出0入0汤圆

发表于 2007-10-20 20:06:09 | 显示全部楼层
不错的东东,谢谢lz
有空也搭个玩玩
头像被屏蔽

出0入0汤圆

发表于 2007-10-20 21:05:38 | 显示全部楼层
先置COOL,鼓励一下 :)

出0入8汤圆

发表于 2007-10-22 09:22:13 | 显示全部楼层
期待源码

出0入0汤圆

发表于 2007-10-22 09:44:53 | 显示全部楼层
正在找这个东西!

出0入228汤圆

 楼主| 发表于 2007-10-22 12:17:32 | 显示全部楼层
/*
芯片脱机复制机
by wxws
jyzhkj@163.com
qq:1103012
        07-10-10
*/




// 目标设备FLASH大小  8*1024=8192  MEGA8的大小
#define FLASH_MAX    8192

#define PAGE_WORDS   32
// 每页32*2=64 byte=32 WORDS
#define TOTAL_PAGE    128
//总页数
#define BOOT_PAGE    112
//共128页,启动区占16页(32*16=512 word = 1024 byte)
#define BOOT_MAX  1019

// PINS  源
#define SCK      6
#define MISO     7
#define MOSI     8
#define RESET  5

// PINS  目标
#define SCK1      10
#define MISO1     11
#define MOSI1     12
#define RESET1  9



#define START_BTN  13
// 按键

#define IDLE_LED   2
#define RUN_LED    3
#define ERR_LED    4


#define CKEDGE  LOW

// ISP Command Words (use the functions defined further below)
#define PE        0xAC53
#define ER        0xAC80
#define RD_PL        0x2000
#define RD_PH   0x2800
#define LD_PL   0x4000
#define LD_PH   0x4800
#define WR_P    0x4C00
#define RD_E    0xA000
#define WR_E    0xC000
#define RD_L    0x5800
#define WR_L    0xACE0
#define RD_S    0x3000
#define WR_F    0xACA0
#define WR_FH   0xACA8
#define RD_F    0x5000
#define RD_FH   0x5808
#define RD_C    0x3800

// Arduino lock bits (default 0xCF ~ prevented reading the boot sector with LPM)
#define LockBits    0xEF
// 11101111 = SPM is not allowed to write to the boot loader section (prevents bootloader corruption)
// Your mega8 running this program probably has bit 6 is programmed. That lock bit makes the bootloader unreadable... (doh!)
// When you use this program to burn new bootloaders, those chips WILL be able to use LPM in the boot flash section.
// You could reduce this program's size by 1K, if LPM can read the boot flash. (there'd be no need for the bootloader table above)

// Arduino fuse bits
#define FuseLow     0xDF //目标设备FUSE

#define FuseHigh    0xC9   //目标设备FUSE

// MACRO DECLARATION

#define PULSE_SCK(level)  { digitalWrite((SCK),(level)); digitalWrite((SCK),!(level)); }
// slow pulse, max 60KHz
#define PULSE_SCK1(level)  { digitalWrite((SCK1),(level)); digitalWrite((SCK1),!(level)); }
// slow pulse, max 60KHz


#define GetWordHigh(a)  ( ((a) & 0xFF00) >> 8 )
#define GetWordLow(a)   ( ((a) & 0x00FF) )
// these macros are used by the function declarations below

// FUNCTION DECLARATION

// sends 4 bytes out with SCK, MOSI (output) and gets the return value of the last byte from MISO (input)
unsigned char Send_ISP(unsigned char dd,unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3);

#define CMD_Program_Enable(dd)                (Send_ISP(dd,GetWordHigh(PE),GetWordLow(PE),0x22,0x22))
// Programming Enable: enable serial programming after reset goes low

#define CMD_Erase_Flash(dd)                   (Send_ISP(dd,GetWordHigh(ER),GetWordLow(ER),0x22,0x22))
// Chip Erase: chip erase eeprom and flash

#define CMD_Read_Flash_Low(dd,addr)     (Send_ISP(dd,GetWordHigh(RD_PL), (GetWordLow(RD_PL) | (((addr) & 0xF00) >> 8)), ((addr) & 0xFF), 0))
// Read Program Memory - Low Byte: reads and returns low data from 12 bit word address (divide byte address by 2 for word address)
//读flash内容, ADDR为地址,0-8192
#define CMD_Read_Flash_High(dd,addr)    (Send_ISP(dd,GetWordHigh(RD_PH), (GetWordLow(RD_PH) | (((addr) & 0xF00) >> 8)), ((addr) & 0xFF), 0))
// Read Program Memory - High Byte: reads and returns high data from 12 bit word address

#define CMD_Load_Page_Low(dd,addr,data)        (Send_ISP(dd,GetWordHigh(LD_PL),GetWordLow(LD_PL), (addr), (data)))
// Load Program Memory Page - Low Byte: loads a low byte to the selected memory page, at word address "page" (page is 4 bits)
// data low byte must be loaded before data high byte; the flash data is entered by pages, then that whole page is written
// pages are 32 words (64 bytes)

#define CMD_Load_Page_High(dd,addr,data)       (Send_ISP(dd,GetWordHigh(LD_PH),GetWordLow(LD_PH), (addr), (data)))
// Load Program Memory Page - High Byte: loads a high byte to program memory page at word address "page" (page is 4 bits)
// data low byte must be loaded before data high byte; the flash data is entered by pages, then that whole page is written
// pages are 32 words (64 bytes)

//#define CMD_Write_Page(addr)                (Send_ISP(GetWordHigh(WR_P),(GetWordLow(WR_P) | (((addr) & 0xF0) >> 4)), (((addr) & 0x0F) << 4), 0))
// this is how it's supposed to be done, according to the documentation, but it doesn't work as it's supposed to.
// the code below works correctly, by multiplying the address by 2?... very weird
#define CMD_Write_Page(dd,addr)                (Send_ISP(dd,GetWordHigh(WR_P),(((addr)*2) & 0xF0) >> 4, ((addr)*2) << 4, 0))
// Write Program Memory Page: write the current page into flash memory at the 8 bit page address "addr"
// your program must wait or poll after performing this command; otherwise the page writing will be halted
// each page is 32 words (64 bytes) - 8K bytes flash, or 4096 words, is 128 pages (0 thru 127)
// 1K flash (bootloader) is 1024 bytes, 512 words - which is 16 pages
// the bootloader begins at 7K (7168 /2=3584) which is page address 112

#define CMD_Read_EEPROM(dd,addrH,addrL)        (Send_ISP(dd,GetWordHigh(RD_E),(GetWordLow(RD_E) | ((addrH) & 0x01)), (addrL), 0))
// Read EEPROM Memory: reads and returns data from the 9 bit address to the EEPROM (addrH is 1 bit, addrL is 8 bit)

#define CMD_Write_EEPROM(dd,addrH,addrL,data)  (Send_ISP(dd,GetWordHigh(WR_E),(GetWordLow(WR_E) | ((addrH) & 0x01)), (addrL), (data)))
// Write EEPROM Memory: writes data from the 9 bit address to the EEPROM (addrH is 1 bit, addrL is 8 bit)

#define CMD_Read_Lock(dd)                 (Send_ISP(dd,GetWordHigh(RD_L),GetWordLow(RD_L), 0, 0))
// Read Lock Bits: read the 6 lock bits; "0" is programmed, 1 is unprogrammed

#define CMD_Write_Lock(dd,data)            (Send_ISP(dd,GetWordHigh(WR_L),GetWordLow(WR_L), 0, (0xC0 | ((data) & 0x3F)) ))
// Write Lock Bits: write the 6 lock bits; "0" is programmed, 1 is unprogrammed

#define CMD_Read_Signature(dd,addr)            (Send_ISP(dd,GetWordHigh(RD_S),GetWordLow(RD_S), ((addr) & 0x03) , 0))
// Read Signature Byte: reads and returns the signature byte from the 2 bit address

#define CMD_Write_Fuse_Low(dd,data)            (Send_ISP(dd,GetWordHigh(WR_F),GetWordLow(WR_F), 0, (data) ))
// Write Fuse Bits - Low: writes the low fuse bits (8 bits)

#define CMD_Write_Fuse_High(dd,data)           (Send_ISP(dd,GetWordHigh(WR_FH),GetWordLow(WR_FH), 0, (data) ))
// Write Fuse Bits - High: writes the high fuse bits (8 bits)

#define CMD_Read_Fuse_Low(dd)                 (Send_ISP(dd,GetWordHigh(RD_F),GetWordLow(RD_F), 0, 0 ))
// Read Fuse Bits - Low: reads and returns the low fuse bits (8 bits)

#define CMD_Read_Fuse_High(dd)                (Send_ISP(dd,GetWordHigh(RD_FH),GetWordLow(RD_FH), 0, 0 ))
// Read Fuse Bits - High: reads and returns the high fuse bits (8 bits)

#define CMD_Read_Calibration(dd)              (Send_ISP(dd,GetWordHigh(RD_C),GetWordLow(RD_C), 0, 0 ))
// Read Calibration Byte: reads and returns the calibration byte (8 bits)


void Reset_Target(unsigned char dd);    // resets the target avr
void Read_Signature(unsigned char dd);  // prints the 16 signature bytes (device codes)
void Read_Flash(unsigned char dd);      // prints the target flash memory
void Read_Fuse(unsigned char dd);       // prints the lock and fuse bits (no leading zeros)
void Show_Bootloader(unsigned char dd); // prints the contents of the bootloader table (for debugging)
void Write_Test(unsigned char dd);      // testing/debugging; writes the address number to each address

void setup(void) {
  pinMode(SCK,OUTPUT);
  pinMode(MISO,INPUT);
  pinMode(MOSI,OUTPUT);
  pinMode(RESET,OUTPUT);
  
  pinMode(SCK1,OUTPUT);
  pinMode(MISO1,INPUT);
  pinMode(MOSI1,OUTPUT);
  pinMode(RESET1,OUTPUT);
   
  // user interface
  pinMode(START_BTN,INPUT);
  pinMode(IDLE_LED,OUTPUT);
  pinMode(RUN_LED,OUTPUT);
  pinMode(ERR_LED,OUTPUT);
  
  Serial.begin(19200);
}

void loop(void) {
  unsigned int result = 0; // used for debugging & showing errors
  
  digitalWrite(ERR_LED,LOW);
  digitalWrite(RUN_LED,LOW);
  digitalWrite(IDLE_LED,HIGH); // indicate idle/waiting
  
  do {} while (digitalRead(START_BTN));
  
  digitalWrite(ERR_LED,LOW);
  digitalWrite(RUN_LED,HIGH);
  digitalWrite(IDLE_LED,LOW); // indicate running
  
  Serial.println("Starting...");
  
  //复位,检测芯片是否存在
  Reset_Target(0);                       
  if ( result=CMD_Program_Enable(0) != 0x22 ) {
    Serial.print("IC 0 Not Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
  }
  
  Reset_Target(1);                        //复位,检测芯片是否存在
  if ( result=CMD_Program_Enable(1) != 0x22 ) {
    Serial.print("IC 1 Not Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
  }

   //写熔丝位
  Serial.println("Setting Fuses");
  CMD_Write_Fuse_Low(1,FuseLow);
  delay(20);
  CMD_Write_Fuse_High(1,FuseHigh);
  delay(20);
  CMD_Write_Lock(1,LockBits);
  delay(20);
  
  Reset_Target(1);
  if ( result=CMD_Program_Enable(1) != 0x22 ) {
    Serial.print("Program Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
  }
  
  Serial.println("Erasing Flash");
  CMD_Erase_Flash(1);
  delay(20);
  
  Reset_Target(1);
  if ( result=CMD_Program_Enable(1) != 0x22 ) {
    Serial.print("Program Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
  }


  for ( unsigned char page = 0 ; page < BOOT_PAGE; page++ ) { //BOOT_PAGE
  //                                    112
    for ( unsigned char index = 0 ; index < PAGE_WORDS  ; index++ ) {
      //                                     32                     
      CMD_Load_Page_Low(1,index,CMD_Read_Flash_Low(0,(page*32)+index));
      CMD_Load_Page_High(1,index,CMD_Read_Flash_High(0,(page*32)+index));
      //Serial.println(((page-BOOT_PAGE)*PAGE_WORDS+index)*2,DEC);
      //Serial.print(CMD_Read_Flash_High(0,(page*32)+index),HEX);
      //Serial.println(CMD_Read_Flash_Low(0,(page*32)+index),HEX);

    }
    Serial.print("Writing page ");
    Serial.println(page,DEC);
    CMD_Write_Page(1,page);
    delay(20);
  }


  return;
  
  SHOW_ERROR:
  Serial.print("ERROR (result ");
  Serial.print(result,BIN);
  Serial.println(")");
  
  digitalWrite(ERR_LED,HIGH);
  digitalWrite(RUN_LED,LOW);
  digitalWrite(IDLE_LED,LOW); // indicate error
  
  do {} while (digitalRead(START_BTN));
  return;

}

// send 4 bytes to target microcontroller, returns the fourth MISO byte
unsigned char Send_ISP(unsigned char dd,unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3) {
  // MO output
  // MI input
  unsigned char result = 0;
  if (dd==0){  //源设备
    // first byte
    for ( int i = 0x80 ; i>0 ; i /= 2 ) {
      digitalWrite(MOSI,(v0 & i));
      PULSE_SCK(CKEDGE);
      //result = ((result << 1) | digitalRead(MISO)); // shift contents of result left one bit, set LSB with MISO value
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // second byte - MISO echos first byte
      digitalWrite(MOSI,(v1 & i));
      PULSE_SCK(CKEDGE);
      result = ((result << 1) | digitalRead(MISO));
    }
    if (result != v0 ) { // handle error
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // third byte - MISO echos second byte
      digitalWrite(MOSI,(v2 & i));
      PULSE_SCK(CKEDGE);
      result = ((result << 1) | digitalRead(MISO));
    }
    if (result != v1 ) { // handle error
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // fourth byte - MISO returns some value (depends on command)
      digitalWrite(MOSI,(v3 & i));
      PULSE_SCK(CKEDGE);
      result = ((result << 1) | digitalRead(MISO));
    }
  
    return result;
  } else {  //目标设备
    // first byte
    for ( int i = 0x80 ; i>0 ; i /= 2 ) {
      digitalWrite(MOSI1,(v0 & i));
      PULSE_SCK1(CKEDGE);
      //result = ((result << 1) | digitalRead(MISO)); // shift contents of result left one bit, set LSB with MISO value
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // second byte - MISO echos first byte
      digitalWrite(MOSI1,(v1 & i));
      PULSE_SCK1(CKEDGE);
      result = ((result << 1) | digitalRead(MISO1));
    }
    if (result != v0 ) { // handle error
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // third byte - MISO echos second byte
      digitalWrite(MOSI1,(v2 & i));
      PULSE_SCK1(CKEDGE);
      result = ((result << 1) | digitalRead(MISO1));
    }
    if (result != v1 ) { // handle error
    }
  
    for ( int i = 0x80 ; i>0 ; i /= 2 ) { // fourth byte - MISO returns some value (depends on command)
      digitalWrite(MOSI1,(v3 & i));
      PULSE_SCK1(CKEDGE);
      result = ((result << 1) | digitalRead(MISO1));
    }
  
    return result;   
   
   
   
  }  
}

void Reset_Target(unsigned char dd) {
  if (dd==0){
    digitalWrite(RESET,HIGH);
    digitalWrite(SCK,LOW); // has to be set LOW at startup, or PE fails
    delay(30);
    digitalWrite(RESET,LOW);
    delay(30); // minimum delay here is 20ms for the ATmega8
  } else{
    digitalWrite(RESET1,HIGH);
    digitalWrite(SCK1,LOW); // has to be set LOW at startup, or PE fails
    delay(30);
    digitalWrite(RESET1,LOW);
    delay(30); // minimum delay here is 20ms for the ATmega8
   
  }
}


// prints the flash memory
void Read_Flash(unsigned char dd) {
  unsigned int value = 0;
  Serial.println("READING FLASH");
  for ( unsigned int index = 0 ; index<(FLASH_MAX/2) ; index++ ) {
    if ( (index % PAGE_WORDS) == 0) {
      Serial.println("");
      Serial.print("Page ");
      Serial.print(index/PAGE_WORDS,DEC);
      Serial.print(" = ");
      if ( index/PAGE_WORDS < 100)
        Serial.print(" ");
    } else if ( (index % (PAGE_WORDS/2)) == 0) {
      Serial.println("");
      Serial.print("           ");
    }

    Serial.print(CMD_Read_Flash_Low(dd,index),HEX);

    Serial.print(" ");
    Serial.print(CMD_Read_Flash_High(dd,index),HEX);
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("END FLASH");
}

// prints the lock and fuse bits (no leading zeros)
void Read_Fuse(unsigned char dd) {
  Serial.print("Lock Bits: ");
  Serial.println(CMD_Read_Lock(dd),BIN);
  Serial.print("Fuse Low: ");
  Serial.println(CMD_Read_Fuse_Low(dd),BIN);
  Serial.print("Fuse High: ");
  Serial.println(CMD_Read_Fuse_High(dd),BIN);
}

出0入228汤圆

 楼主| 发表于 2007-10-22 12:22:18 | 显示全部楼层
源码来啦,
阿莫改一下标题吧.
我用的是ARDUINO开发平台,老外的,用起来特爽,上手超级快.傻瓜式的,呵.
不需要装那些软件,就是一个IDE环境,写小程序是飞一样的快.呵呵.其他平台可能更好,不过我用习惯了.不知有没同道者,有兴趣的话联系我一起研究研究.

不过这都是对我这个AVR生手而言.


改在其他平台也很简单的.

SETUP() ,在上电时运行一遍,定义一下管脚
LOOP(),是主程序.

出0入228汤圆

 楼主| 发表于 2007-10-22 12:23:32 | 显示全部楼层
这是ARDUINO开发平台与芯片对应的管脚式意图:


出0入0汤圆

发表于 2007-10-22 12:28:30 | 显示全部楼层
先谢谢了,但为何不上传成附件的形式?

出0入228汤圆

 楼主| 发表于 2007-10-22 12:34:31 | 显示全部楼层
请参考这个一起看
AVRISP通讯协议的翻译

http://www.ourdev.cn/bbs/bbs_content.jsp?mother_form=bbs_content.jsp&bbs_id=1000&bbs_page_no=3&bbs_sn=437335
头像被屏蔽

出0入0汤圆

发表于 2007-10-22 13:37:49 | 显示全部楼层
谢谢啊!!

出0入0汤圆

发表于 2007-10-22 21:10:07 | 显示全部楼层
我们太擅长把剽窃来的东西,当成自己原创了。
头像被屏蔽

出0入0汤圆

发表于 2007-10-22 21:27:22 | 显示全部楼层
“剽窃来的东西,当成自己原创”,并且愿意在网上公开,总比某些人一毛不拨,却又对肯公开资料的人指指点点要强多了。

出0入0汤圆

发表于 2007-10-22 22:09:58 | 显示全部楼层
呵呵,楼上对剽窃还是很大度嘛。不说明出处的剽窃,在你这里成了英雄。这好像不符合你一贯的“尊重”知识产权的“虎屁大旗”哇。

我去银行抢了100W,然后捐给慈善机构,按照你的伟大逻辑,是不是我就成英雄了?

出0入0汤圆

发表于 2007-10-22 22:13:39 | 显示全部楼层
伟大、光荣、正确的armok先生在所谓的“知识产权”问题上很有一套双重标准啊 。详细的制作过程,有兴趣的看这个吧:


The Arduino Boot-Cloner
What is it? Why?
The boot-cloner is a program compiled and burnt with the Arduino IDE, that copies part of it's flash memory onto another microcontroller. The bootloader can be written to a new microcontroller by the Arduino, instead of burning the bootloader onto new ATmega8's with a separate device.


If you're like me, then you need more than one microcontroller, so you can put the IC into a circuit and leave it there permanently. Unfortunately, burning multiple bootloaders can be a very involved, time consuming process. The cloner will help you get dozens of new ATmega8's ready to use, in seconds. The program gives you access to an implementation of the ISP protocol and declaring and using tables stored in program flash, which don't occupy ram.


Requirements
You need a functioning Arduino that you can already write programs to. If you don't have at least one ATmega8 with a bootloader on it, you'll need to burn it using a separate device, like the parallel port burner.
momentary push button and pull-up resistor 1K ~ 10K Ohms
three leds and current limiting resistors appropriate for the voltage of the device. If you're working from the Arduino, you've got 5V which means 220 Ohm resistors for 20mA. If you build a 2.4V battery powered device, use lower resistors to get 20mA. (Voltage divided by current tells you resistance, so 2.4/.02=12 Ohms, 10 approx)
two ceramic disc capacitors of 10pF (with no polarity) and a 2 to 16MHz crystal oscillator for the target microcontroller. Don't use less than 1MHz; the speed of this crystal determines the maximum rate you can issue commands and send data to the target IC, with ISP. 16MHz was convenient for me, but use whatever you've got on hand.

Pictures

More Pictures
Schematic


Notes:

Connect GND on the Arduino to pins 8 and 22 and +5V to pins 7 and 20 on the target microcontroller.
Make sure you have the notch on the target ATmega8 facing up. I can't tell you how many times I've accidentally tried wiring the microcontroller upside-down. The good news is doing that doesn't seem to hurt anything.

Download Project and Schematic




Inner Workings
In-System Programming (ISP) is a protocol developed by Atmel to be used as the primary means of programming their microcontrollers. The three wire serial protocol can be used to write the fuse bits, program memory and eeprom. It's a bit of a language by itself, and varys slightly from one microcontroller to another - mostly by chip architecture differences. (i.e. flash/eeprom size and fuse bit features) While holding the RESET pin of the microcontroller at a low level, the first command issued through ISP is called program enable. After those special 32 bits are sent, the microcontroller begins communicating. There's several commands that can be issued after program enable, which are sent serially at any rate: reading the flash memory, writing the flash memory page-by-page, erasing the flash memory, reading/writing the fuse bits or eeprom, reading device codes and more.


In the Boot-Cloner sketch is an implementation of the ISP protocol for an ATmega8, complete with functions that encapsulate the protocol's commands - making them easier to use. These functions are compatible with many of the other atmel microcontrollers as-is, but haven't been tested yet. The bootloader written to the new ATmega8 is stored in a large array - because default fuse bits of your Arduino prevent reading the boot section. This was a problem I ran into, but the table that had to be added also provides new possibilities.
To sum it all up, this means the Boot-Cloner could write any program to any atmel microcontroller. But, because the target's program must be stored in the source's memory (which limits the maximum size of the program) it's only possible to write small programs like bootloaders.


The ISP protocol is detailed in the Atmel ATmega8 datasheet, towards the end. Additional comments in the sketch's source code describe command parameters and the flash write process.


Step-By-Step Guide
The Arduino will provide power to the entire circuit. Unplug your Arduino before wiring +5V and GND from it, to the target microcontroller. This avoids potential shorts which could damage your hardware. Based on my own experience, it's very difficult to damage the computer or Arduino ~ there's added safety in the design of USB controllers and the ATmega8 is unbelievably tough. Having said that - never feed a different voltage into the 5V or 9V header connectors.

If you should happen to short +5V and GND wires together and your USB port stops providing power - fix the short and then restart your computer. The computer's USB resettable fuse should return to normal. If not, shutdown and power-up your computer. If it still doesn't work, use a different computer or install a new USB adapter card. Some motherboard USB controllers may be more sensitive than others, and provide more or less current than others.

This circuit should draw less than 20+20+20+30mA = 90mA. If either the IC on the Arduino or the target ATmega8 on the breadboard gets warm ~ something's wired incorrectly. Ensure you've got the correct value resistors to the LEDs, suitable pull-up from the button and the right pins are connected on the Arduino.

1) Download and expand the zip archive containing the source code and schematic


2) In the Arduino IDE, open the Boot-Cloner sketch


3) Verify the sketch compiles without error


4) The +5V and GND of your Arduino should be used to power the target ATmega8


I haven't yet had noise problems with this circuit, but avoid using excessively long wires for SCK, MISO, MOSI and avoid working near sources of significant electrical noise.

5) Upon wiring the circuit, according to the schematic, your Arduino should be connected by 10 wires to a breadboard
5V, GND, RESET, SCK, MISO, MOSI, LED1, LED2, LED3, START BTN


6) Ensure you have the chip oriented correctly, and oscillator and power connected to the pins as shown in the schematic


7) Burn the BootCloner sketch to the Arduino and wait for the program to start - you'll see an LED light up according to the program's state


8) At this point, you can push the start button.
The LEDs will change from Idle/Green to Run/Yellow for a moment (less than 4 seconds) and then switch back to Idle/Green.


If the Error/Red LED comes on, it's an indication that your target microcontroller is not responding to the program enable command. This indicates a problem with your wiring. Check to make sure SCK, MISO and MOSI are connected exactly as shown, that you're got the notch/pin1 facing the right direction and that a stable 5V is being provided to your target.

9) Remove the target ATmega8, insert the next.


10) Test the first one you burn, the first time you do this, by putting it in an Arduino and writing the Blinking LED program.


11) If step 10 worked you can repeat steps 8 and 9 until all your ICs are prepared.


Using A Different Bootloader
The bootloader table in the BootCloner sketch holds the raw data which is written to the boot section of the microcontroller. However, a hex file contains memory address and checksums in addition to the raw data. To save space the extra information was discarded and the string hexadecimal numbers were converted to decimal or hexadecimal constants recognizable by the Arduino IDE. (0-255 or 0x00-0xFF)


At the beginning of the BootCloner source code is a reference to a website described as "iHex flash file format information". If you want to understand the format better, that's a great place to start.


The program below, "Hex Data Extractor" can be built into an application that'll extract it for you.


There are also some things in the sketch that need to be changed. How many defined constants need to be modified depends on how different your target microcontroller is than an ATmega8. Ideally you should only have to change the constants, and not the program itself.


Alternate bootloader for an ATmega8:

BOOT_MAX is the size of the bootloader table. Since your bootloader will probably be a different size, you'll need to change this. Arrays in C are zero based, including the bootloader table, so size is the number of bytes minus 1. (0 to 1019 is 1020 bytes)

Alternate bootloader for an ATmega168:

FLASH_MAX should be 16384. (16Kb)
BOOT_PAGE should be 480, if your boot section is 1K. (16384-1024=15360/32=480)
BOOT_MAX is the size of the bootloader table. (byte count minus 1)

Alternate bootloaders for other atmel microcontrollers:

FLASH_MAX, BOOT_PAGE, and BOOT_MAX will most likely need to be changed.
Check the datasheet for your microcontroller to determine how many words (2 bytes) are in a page (PAGE_WORDS).
To my knowledge, there are two different flash write methods. The only one available in the Boot-Cloner is the page method. Your microcontroller might require the other.
Some of the command parameters may need to be altered, such as fuse bits and the largest address size sent to read/write flash and eeprom. This means the functions themselves should be adjusted, as well as the code in the loop() function.

Notes:

I assume that the boot section begins at 7K (BOOT_PAGE) regardless of the size of the bootloader, as long as the fuse bits are set to a 1K boot section.
Technically, you can set BOOT_MAX to 1024 and leave it there. Random junk from the source's flash memory will be written after the bootloader data on the target - but this theoretically doesn't cause problems.
If you want to reduce the bootloaders size below 1K and also free up memory, you'll need to change the corresponding fuse bits to adjust the boot section size and increase the BOOT_PAGE constant.

Hex Data Extractor
/* Data Extractor for Intel Hex Formatted Files
* ------------------
* Created 2007 by jims
* <mailto:jim@federated.com>
*
* Compile this with your preferred C environment, as a standard console app.
* From the console (Command Prompt), launch the app with the hex file pathname.
* The console output will be the extracted hex data.
*
*/

#include <stdio.h>
#include <string.h>

main()
{
    char buf[4096];
    int n = 0;

    while( fgets(buf, sizeof(buf)-1, stdin)) {
        int len = strlen(buf);
        char *b;

        if ( len < 9) continue;
        buf[len-4] = 0;

        for ( b = buf+9; *b != 0; b += 2) {
            printf("0x%c%c, ", b[0], b[1]);
            n++;
        }
        printf("\n");
    }
    printf("/* %d bytes */\n", n);
}


Boot-Cloner Source Code
/* ARDUINO BOOT-CLONER
* -------------------
*
* Comments
*
* The ATmega8 fuse bytes and bootloader are copied
* from the chip on the Arduino, to a new blank ATmega8.
*
* / See app note DOC0943.pdf "AVR910: In-System Programming"
* / See app note DOC2486.pdf "ATmega8 Documentation" - The chapter on Memory Programming, p.237/240
* / iHex flash file format information "http://www.scienceprog.com/shelling-the-intel-8-bit-hex-file-format/"
* / PROGMEM and pgmspace.h usage information:
*     "http://www.scienceprog.com/simple-routine-how-to-store-data-in-microcontroller-flash-and-read-from-it-using-winavr/"
*
* Notes:
* Sometimes the program wont detect errors, i.e. if the target ic isn't inserted.
* Contrary to what I originally thought, the bootloader resides at the end of flash memory.
*
* The program was too big, so some of the extra functions are commented out to save memory.
*
* This program hasn't been optimized for speed, but it's still pretty quick. Some of the delays are unnecessary.
*
* Your bootloader flash probably can't be read; the default lock bits prevent that. (0xCF ~ bit 6)
* This boot-cloner writes different lock bits to the new ATmega8; so the boot flash section *could* be read
* when run from the new chip. (0xEF)
* With the bootloader flash unlocked, you could remove the bootloader[] table and save a bunch of memory.
*
* 2007 by Amplificar
* <mailto:amplificar@gmail.com>
*
*/

// need this header for PROGMEM and the command pgm_read_byte()
// which reads bytes from flash program memory.
// you can view the header's contents, which are in arduino->tools->avr->avr->include->avr->pgmspace.h
#include <avr/pgmspace.h>

// CONSTANT DECLARATION

// target microcontroller constants
#define FLASH_MAX    8192
// the flash size
#define PAGE_WORDS   32
// the number of words per page
#define BOOT_PAGE    112
// the starting page number, where the bootloader lurks (8192/2/32=128, 1024/2/32=16, 128-16=112)

// the bootloader data; distributed with arduino ide 0005
// this is the extracted data from the ihex file
// PROGMEM forces this data to be kept in the flash - and not get loaded into ram (that'd be bad)
// this table has to be read back using  "byte=pgm_read_byte(&bootloader[index]);"
#define BOOT_MAX  1019
const unsigned char bootloader[] PROGMEM= {
  0x12,0xC0,0x2B,0xC0,0x2A,0xC0,0x29,0xC0,0x28,0xC0,0x27,0xC0,0x26,0xC0,0x25,0xC0,
0x24,0xC0,0x23,0xC0,0x22,0xC0,0x21,0xC0,0x20,0xC0,0x1F,0xC0,0x1E,0xC0,0x1D,0xC0,
0x1C,0xC0,0x1B,0xC0,0x1A,0xC0,0x11,0x24,0x1F,0xBE,0xCF,0xE5,0xD4,0xE0,0xDE,0xBF,
0xCD,0xBF,0x10,0xE0,0xA0,0xE6,0xB0,0xE0,0xE6,0xEF,0xFF,0xE1,0x02,0xC0,0x05,0x90,
0x0D,0x92,0xA2,0x36,0xB1,0x07,0xD9,0xF7,0x11,0xE0,0xA2,0xE6,0xB0,0xE0,0x01,0xC0,
0x1D,0x92,0xAA,0x36,0xB1,0x07,0xE1,0xF7,0x4B,0xC0,0xD2,0xCF,0xEF,0x92,0xFF,0x92,
0x0F,0x93,0x1F,0x93,0xEE,0x24,0xFF,0x24,0x87,0x01,0x5F,0x99,0x15,0xC0,0x08,0x94,
0xE1,0x1C,0xF1,0x1C,0x01,0x1D,0x11,0x1D,0x81,0xE0,0xE8,0x16,0x82,0xE1,0xF8,0x06,
0x8A,0xE7,0x08,0x07,0x80,0xE0,0x18,0x07,0x28,0xF0,0xE0,0x91,0x62,0x00,0xF0,0x91,
0x63,0x00,0x09,0x95,0x5F,0x9B,0xEB,0xCF,0x8C,0xB1,0x99,0x27,0x87,0xFD,0x90,0x95,
0x1F,0x91,0x0F,0x91,0xFF,0x90,0xEF,0x90,0x08,0x95,0x5D,0x9B,0xFE,0xCF,0x8C,0xB9,
0x08,0x95,0xD4,0xDF,0x80,0x32,0x21,0xF4,0x84,0xE1,0xF7,0xDF,0x80,0xE1,0xF5,0xDF,
0x08,0x95,0x08,0x95,0xCF,0x93,0xC8,0x2F,0xC9,0xDF,0x80,0x32,0x31,0xF4,0x84,0xE1,
0xEC,0xDF,0x8C,0x2F,0xEA,0xDF,0x80,0xE1,0xE8,0xDF,0xCF,0x91,0x08,0x95,0xCF,0x93,
0x88,0x23,0x21,0xF0,0xC8,0x2F,0xBA,0xDF,0xC1,0x50,0xE9,0xF7,0xCF,0x91,0x08,0x95,
0xCF,0xE5,0xD4,0xE0,0xDE,0xBF,0xCD,0xBF,0x00,0x00,0x10,0xBC,0x83,0xE3,0x89,0xB9,
0x88,0xE1,0x8A,0xB9,0x86,0xE8,0x80,0xBD,0xBD,0x9A,0x10,0x92,0x68,0x01,0x30,0xE2,
0x2F,0xE0,0x88,0xB3,0x83,0x27,0x88,0xBB,0x80,0xE0,0x90,0xE0,0x01,0x97,0xF1,0xF7,
0x21,0x50,0x27,0xFF,0xF6,0xCF,0x20,0xE1,0x20,0x93,0x68,0x01,0x97,0xDF,0x80,0x33,
0x09,0xF4,0x44,0xC0,0x81,0x33,0xA1,0xF4,0x91,0xDF,0xC8,0x2F,0x80,0x32,0xB1,0xF7,
0x84,0xE1,0xB3,0xDF,0x81,0xE4,0xB1,0xDF,0x86,0xE5,0xAF,0xDF,0x82,0xE5,0xAD,0xDF,
0x8C,0x2F,0xAB,0xDF,0x89,0xE4,0xA9,0xDF,0x83,0xE5,0xA7,0xDF,0x80,0xE5,0x2E,0xC1,
0x80,0x34,0x29,0xF4,0x7B,0xDF,0x86,0x38,0x48,0xF1,0x78,0xDF,0x27,0xC0,0x81,0x34,
0x71,0xF4,0x74,0xDF,0x80,0x38,0x11,0xF4,0x82,0xE0,0x28,0xC1,0x81,0x38,0x11,0xF4,
0x81,0xE0,0x24,0xC1,0x82,0x38,0x09,0xF0,0x20,0xC1,0x82,0xE1,0x1F,0xC1,0x82,0x34,
0x11,0xF4,0x84,0xE1,0x03,0xC0,0x85,0x34,0x19,0xF4,0x85,0xE0,0xA0,0xDF,0x0E,0xC0,
0x80,0x35,0x61,0xF0,0x81,0x35,0x51,0xF0,0x82,0x35,0x41,0xF0,0x85,0x35,0x41,0xF4,
0x55,0xDF,0x80,0x93,0x64,0x00,0x52,0xDF,0x80,0x93,0x65,0x00,0x7A,0xDF,0xB6,0xCF,
0x86,0x35,0x19,0xF4,0x84,0xE0,0x8B,0xDF,0x00,0xC1,0x84,0x36,0x09,0xF0,0x9D,0xC0,
0x45,0xDF,0x80,0x93,0x67,0x01,0x42,0xDF,0x80,0x93,0x66,0x01,0x80,0x91,0x69,0x01,
0x8E,0x7F,0x80,0x93,0x69,0x01,0x3A,0xDF,0x85,0x34,0x29,0xF4,0x80,0x91,0x69,0x01,
0x81,0x60,0x80,0x93,0x69,0x01,0xC0,0xE0,0xD0,0xE0,0x80,0x91,0x66,0x01,0x90,0x91,
0x67,0x01,0xC8,0x17,0xD9,0x07,0x70,0xF4,0x06,0xE6,0x10,0xE0,0x27,0xDF,0xF8,0x01,
0x81,0x93,0x8F,0x01,0x21,0x96,0x80,0x91,0x66,0x01,0x90,0x91,0x67,0x01,0xC8,0x17,
0xD9,0x07,0xA0,0xF3,0x1B,0xDF,0x80,0x32,0x09,0xF0,0x80,0xCF,0x80,0x91,0x69,0x01,
0x80,0xFF,0x26,0xC0,0xC0,0xE0,0xD0,0xE0,0x80,0x91,0x66,0x01,0x90,0x91,0x67,0x01,
0xC8,0x17,0xD9,0x07,0x08,0xF0,0x5F,0xC0,0x06,0xE6,0x10,0xE0,0xF8,0x01,0x61,0x91,
0x8F,0x01,0x80,0x91,0x64,0x00,0x90,0x91,0x65,0x00,0xC2,0xD0,0x80,0x91,0x64,0x00,
0x90,0x91,0x65,0x00,0x01,0x96,0x90,0x93,0x65,0x00,0x80,0x93,0x64,0x00,0x21,0x96,
0x80,0x91,0x66,0x01,0x90,0x91,0x67,0x01,0xC8,0x17,0xD9,0x07,0x38,0xF3,0x43,0xC0,
0xF8,0x94,0xE1,0x99,0xFE,0xCF,0x11,0x27,0xE0,0x91,0x64,0x00,0xF0,0x91,0x65,0x00,
0xEE,0x0F,0xFF,0x1F,0xC6,0xE6,0xD0,0xE0,0x80,0x91,0x66,0x01,0x90,0x91,0x67,0x01,
0x80,0xFF,0x01,0xC0,0x01,0x96,0x10,0x30,0x51,0xF4,0x22,0xD0,0x03,0xE0,0x00,0x93,
0x57,0x00,0xE8,0x95,0x1D,0xD0,0x01,0xE1,0x00,0x93,0x57,0x00,0xE8,0x95,0x09,0x90,
0x19,0x90,0x16,0xD0,0x01,0xE0,0x00,0x93,0x57,0x00,0xE8,0x95,0x13,0x95,0x10,0x32,
0x58,0xF0,0x11,0x27,0x0D,0xD0,0x05,0xE0,0x00,0x93,0x57,0x00,0xE8,0x95,0x08,0xD0,
0x01,0xE1,0x00,0x93,0x57,0x00,0xE8,0x95,0x32,0x96,0x02,0x97,0x39,0xF0,0xDB,0xCF,
0x00,0x91,0x57,0x00,0x01,0x70,0x01,0x30,0xD9,0xF3,0x08,0x95,0x10,0x30,0x11,0xF0,
0x02,0x96,0xE7,0xCF,0x11,0x24,0x84,0xE1,0x59,0xC0,0x84,0x37,0x09,0xF0,0x49,0xC0,
0xA5,0xDE,0x80,0x93,0x67,0x01,0xA2,0xDE,0x80,0x93,0x66,0x01,0x9F,0xDE,0x90,0x91,
0x69,0x01,0x85,0x34,0x21,0xF4,0x91,0x60,0x90,0x93,0x69,0x01,0x0D,0xC0,0x9E,0x7F,
0x90,0x93,0x69,0x01,0x80,0x91,0x64,0x00,0x90,0x91,0x65,0x00,0x88,0x0F,0x99,0x1F,
0x90,0x93,0x65,0x00,0x80,0x93,0x64,0x00,0x89,0xDE,0x80,0x32,0x09,0xF0,0xEE,0xCE,
0x84,0xE1,0xAB,0xDE,0xC0,0xE0,0xD0,0xE0,0x80,0x91,0x66,0x01,0x90,0x91,0x67,0x01,
0xC8,0x17,0xD9,0x07,0x60,0xF5,0x80,0x91,0x69,0x01,0x80,0xFF,0x06,0xC0,0x80,0x91,
0x64,0x00,0x90,0x91,0x65,0x00,0x2C,0xD0,0x08,0xC0,0x86,0x95,0x80,0xFD,0x06,0xC0,
0xE0,0x91,0x64,0x00,0xF0,0x91,0x65,0x00,0x84,0x91,0x8F,0xDE,0x80,0x91,0x64,0x00,
0x90,0x91,0x65,0x00,0x01,0x96,0x90,0x93,0x65,0x00,0x80,0x93,0x64,0x00,0x21,0x96,
0xDB,0xCF,0x85,0x37,0x79,0xF4,0x5A,0xDE,0x80,0x32,0x09,0xF0,0xBF,0xCE,0x84,0xE1,
0x7C,0xDE,0x8E,0xE1,0x7A,0xDE,0x83,0xE9,0x78,0xDE,0x87,0xE0,0x76,0xDE,0x80,0xE1,
0x74,0xDE,0xB4,0xCE,0x86,0x37,0x09,0xF0,0xB1,0xCE,0x80,0xE0,0x7B,0xDE,0xAE,0xCE,
0xE1,0x99,0xFE,0xCF,0x9F,0xBB,0x8E,0xBB,0xE0,0x9A,0x99,0x27,0x8D,0xB3,0x08,0x95,
0xE1,0x99,0xFE,0xCF,0x9F,0xBB,0x8E,0xBB,0x6D,0xBB,0x0F,0xB6,0xF8,0x94,0xE2,0x9A,
0xE1,0x9A,0x0F,0xBE,0x08,0x95,
0x80,0x00,
0x00,0x00,0x1C,0x00
};

// PINS
#define SCK    13
// serial clock to target avr
#define MISO   12
// input from target avr
#define MOSI   11
// output to target avr
#define RESET  10
// reset pin of the target avr

#define START_BTN  9
// active low - starts burning the bootloader to the new chip
#define IDLE_LED   8
#define RUN_LED    7
#define ERR_LED    6

// on the target avr, wire these other pins:
// GND: pins 22 (GND), 8 (GND)
// +VCC: pin 7 (VCC)
// XTAL1 & XTAL2

#define CKEDGE  LOW
// SCK transmits the bit from MOSI on the rising edge of the clock pulse
//   CKEDGE should be LOW, which means SCK pulses "...LOW->HIGH->LOW..."

// ISP Command Words (use the functions defined further below)
#define PE        0xAC53
#define ER        0xAC80
#define RD_PL        0x2000
#define RD_PH   0x2800
#define LD_PL   0x4000
#define LD_PH   0x4800
#define WR_P    0x4C00
#define RD_E    0xA000
#define WR_E    0xC000
#define RD_L    0x5800
#define WR_L    0xACE0
#define RD_S    0x3000
#define WR_F    0xACA0
#define WR_FH   0xACA8
#define RD_F    0x5000
#define RD_FH   0x5808
#define RD_C    0x3800

// Arduino lock bits (default 0xCF ~ prevented reading the boot sector with LPM)
#define LockBits    0xEF
// 11101111 = SPM is not allowed to write to the boot loader section (prevents bootloader corruption)
// Your mega8 running this program probably has bit 6 is programmed. That lock bit makes the bootloader unreadable... (doh!)
// When you use this program to burn new bootloaders, those chips WILL be able to use LPM in the boot flash section.
// You could reduce this program's size by 1K, if LPM can read the boot flash. (there'd be no need for the bootloader table above)

// Arduino fuse bits
#define FuseLow     0xDF
// default 11011111 = 0xDF, bits 1-4 (rightmost) are CKSEL clock select, bits 5-6 are SUT1 & SUT0 start up time delay
// bits 7-8 are BOD brown out detect, which is disabled

#define FuseHigh    0xCA
// default 11001010 = 0xCA
// bit 1 select reset vector (on)
// bits 2-3 boot size (1K)
// bit 4 EESAVE eeprom preserved through chip erase (off)
// bit 5 CKOPT clock options (on)
// bit 6 SPIEN SPI enabled (on)
// bit 7 WDT watchdog timer (off)
// bit 8 RSTDISBL reset disable (off)

// MACRO DECLARATION

#define PULSE_SCK(level)  { digitalWrite((SCK),(level)); digitalWrite((SCK),!(level)); }
// slow pulse, max 60KHz

#define GetWordHigh(a)  ( ((a) & 0xFF00) >> 8 )
#define GetWordLow(a)   ( ((a) & 0x00FF) )
// these macros are used by the function declarations below

// FUNCTION DECLARATION

// sends 4 bytes out with SCK, MOSI (output) and gets the return value of the last byte from MISO (input)
unsigned char Send_ISP(unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3);

#define CMD_Program_Enable()                (Send_ISP(GetWordHigh(PE),GetWordLow(PE),0x22,0x22))
// Programming Enable: enable serial programming after reset goes low

#define CMD_Erase_Flash()                   (Send_ISP(GetWordHigh(ER),GetWordLow(ER),0x22,0x22))
// Chip Erase: chip erase eeprom and flash

#define CMD_Read_Flash_Low(addr)     (Send_ISP(GetWordHigh(RD_PL), (GetWordLow(RD_PL) | (((addr) & 0xF00) >> 8)), ((addr) & 0xFF), 0))
// Read Program Memory - Low Byte: reads and returns low data from 12 bit word address (divide byte address by 2 for word address)

#define CMD_Read_Flash_High(addr)    (Send_ISP(GetWordHigh(RD_PH), (GetWordLow(RD_PH) | (((addr) & 0xF00) >> 8)), ((addr) & 0xFF), 0))
// Read Program Memory - High Byte: reads and returns high data from 12 bit word address

#define CMD_Load_Page_Low(addr,data)        (Send_ISP(GetWordHigh(LD_PL),GetWordLow(LD_PL), (addr), (data)))
// Load Program Memory Page - Low Byte: loads a low byte to the selected memory page, at word address "page" (page is 4 bits)
// data low byte must be loaded before data high byte; the flash data is entered by pages, then that whole page is written
// pages are 32 words (64 bytes)

#define CMD_Load_Page_High(addr,data)       (Send_ISP(GetWordHigh(LD_PH),GetWordLow(LD_PH), (addr), (data)))
// Load Program Memory Page - High Byte: loads a high byte to program memory page at word address "page" (page is 4 bits)
// data low byte must be loaded before data high byte; the flash data is entered by pages, then that whole page is written
// pages are 32 words (64 bytes)

//#define CMD_Write_Page(addr)
//(Send_ISP(GetWordHigh(WR_P),(GetWordLow(WR_P) | (((addr) & 0xF0) >> 4)), (((addr) & 0x0F) << 4), 0))
// this is how it's supposed to be done, according to the documentation, but it doesn't work as it's supposed to.
// the code below works correctly, by multiplying the address by 2?... very weird
#define CMD_Write_Page(addr)                (Send_ISP(GetWordHigh(WR_P),(((addr)*2) & 0xF0) >> 4, ((addr)*2) << 4, 0))
// Write Program Memory Page: write the current page into flash memory at the 8 bit page address "addr"
// your program must wait or poll after performing this command; otherwise the page writing will be halted
// each page is 32 words (64 bytes) - 8K bytes flash, or 4096 words, is 128 pages (0 thru 127)
// 1K flash (bootloader) is 1024 bytes, 512 words - which is 16 pages
// the bootloader begins at 7K (7168 /2=3584) which is page address 112

#define CMD_Read_EEPROM(addrH,addrL)        (Send_ISP(GetWordHigh(RD_E),(GetWordLow(RD_E) | ((addrH) & 0x01)), (addrL), 0))
// Read EEPROM Memory: reads and returns data from the 9 bit address to the EEPROM (addrH is 1 bit, addrL is 8 bit)

#define CMD_Write_EEPROM(addrH,addrL,data)  (Send_ISP(GetWordHigh(WR_E),(GetWordLow(WR_E) | ((addrH) & 0x01)), (addrL), (data)))
// Write EEPROM Memory: writes data from the 9 bit address to the EEPROM (addrH is 1 bit, addrL is 8 bit)

#define CMD_Read_Lock()                 (Send_ISP(GetWordHigh(RD_L),GetWordLow(RD_L), 0, 0))
// Read Lock Bits: read the 6 lock bits; "0" is programmed, 1 is unprogrammed

#define CMD_Write_Lock(data)            (Send_ISP(GetWordHigh(WR_L),GetWordLow(WR_L), 0, (0xC0 | ((data) & 0x3F)) ))
// Write Lock Bits: write the 6 lock bits; "0" is programmed, 1 is unprogrammed

#define CMD_Read_Signature(addr)            (Send_ISP(GetWordHigh(RD_S),GetWordLow(RD_S), ((addr) & 0x03) , 0))
// Read Signature Byte: reads and returns the signature byte from the 2 bit address

#define CMD_Write_Fuse_Low(data)            (Send_ISP(GetWordHigh(WR_F),GetWordLow(WR_F), 0, (data) ))
// Write Fuse Bits - Low: writes the low fuse bits (8 bits)

#define CMD_Write_Fuse_High(data)           (Send_ISP(GetWordHigh(WR_FH),GetWordLow(WR_FH), 0, (data) ))
// Write Fuse Bits - High: writes the high fuse bits (8 bits)

#define CMD_Read_Fuse_Low()                 (Send_ISP(GetWordHigh(RD_F),GetWordLow(RD_F), 0, 0 ))
// Read Fuse Bits - Low: reads and returns the low fuse bits (8 bits)

#define CMD_Read_Fuse_High()                (Send_ISP(GetWordHigh(RD_FH),GetWordLow(RD_FH), 0, 0 ))
// Read Fuse Bits - High: reads and returns the high fuse bits (8 bits)

#define CMD_Read_Calibration()              (Send_ISP(GetWordHigh(RD_C),GetWordLow(RD_C), 0, 0 ))
// Read Calibration Byte: reads and returns the calibration byte (8 bits)


void Reset_Target();    // resets the target avr
void Read_Signature();  // prints the 16 signature bytes (device codes)
void Read_Flash();      // prints the target flash memory
void Read_Fuse();       // prints the lock and fuse bits (no leading zeros)
void Show_Bootloader(); // prints the contents of the bootloader table (for debugging)
void Write_Test();      // testing/debugging; writes the address number to each address

void setup(void) {
  pinMode(SCK,OUTPUT);
  pinMode(MISO,INPUT);
  pinMode(MOSI,OUTPUT);
  pinMode(RESET,OUTPUT);

  // user interface
  pinMode(START_BTN,INPUT);
  pinMode(IDLE_LED,OUTPUT);
  pinMode(RUN_LED,OUTPUT);
  pinMode(ERR_LED,OUTPUT);

  Serial.begin(19200);
}

void loop(void) {
  unsigned int result = 0; // used for debugging & showing errors

  digitalWrite(ERR_LED,LOW);
  digitalWrite(RUN_LED,LOW);
  digitalWrite(IDLE_LED,HIGH); // indicate idle/waiting

  do {} while (digitalRead(START_BTN));

  digitalWrite(ERR_LED,LOW);
  digitalWrite(RUN_LED,HIGH);
  digitalWrite(IDLE_LED,LOW); // indicate running

  Serial.println("Starting...");

  Reset_Target();
  if ( result=CMD_Program_Enable() != 0x22 ) {
    Serial.print("Program Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
    // error detection routine isn't foolproof.
  }

  Serial.println("Setting Fuses");
  CMD_Write_Fuse_Low(FuseLow);
  delay(20);
  CMD_Write_Fuse_High(FuseHigh);
  delay(20);
  CMD_Write_Lock(LockBits);
  delay(20);

  Reset_Target();
  if ( result=CMD_Program_Enable() != 0x22 ) {
    Serial.print("Program Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
    // error detection routine isn't foolproof.
  }

  Serial.println("Erasing Flash");
  CMD_Erase_Flash();
  delay(20);

  Reset_Target();
  if ( result=CMD_Program_Enable() != 0x22 ) {
    Serial.print("Program Enable "); // an error occurred; expected 0x22
    goto SHOW_ERROR;
  }

  for ( unsigned char page = BOOT_PAGE ; page <= BOOT_PAGE+BOOT_MAX/2/PAGE_WORDS ; page++ ) {

    for ( unsigned char index = 0 ; index < PAGE_WORDS && (index+(page-BOOT_PAGE)*PAGE_WORDS)*2 < BOOT_MAX ; index++ ) {
      CMD_Load_Page_Low(index,pgm_read_byte(&bootloader[((page-BOOT_PAGE)*PAGE_WORDS+index)*2]));
      CMD_Load_Page_High(index,pgm_read_byte(&bootloader[((page-BOOT_PAGE)*PAGE_WORDS+index)*2+1]));
      //Serial.println(((page-BOOT_PAGE)*PAGE_WORDS+index)*2,DEC);
    }
    Serial.print("Writing page ");
    Serial.println(page,DEC);
    CMD_Write_Page(page);
    delay(20);
  }
  // in the condition of the outermost, first loop, BOOT_MAX is number of bytes in the bootloader table
  // that's divided by 2 to get words (a word is 2 bytes) and divided by PAGE_WORDS (32) to determine
  // the total number of pages to be written

  // in the condition of the innermost loop, the stuff following && prevents the last page from being completely written
  // when the bootloader isn't an even multiple of 32. (it'd write random junk from this chips flash memory)
  // the condition checks to see if the index, plus the page, exceeds the number of bytes in the bootloader table.

  // the CMD_Load_Page_Low(...) does some math to convert index & page into an index for the bootloader table
  // the Low byte must be written before the High byte, when programming

  // once the page buffer is filled, the CMD_Write_Page() is issued, which commits the page to flash memory.

  //Read_Flash();
  // prints the contents of the target microcontroller's flash (slow)

  return;

  SHOW_ERROR:
  Serial.print("ERROR (result ");
  Serial.print(result,BIN);
  Serial.println(")");

  digitalWrite(ERR_LED,HIGH);
  digitalWrite(RUN_LED,LOW);
  digitalWrite(IDLE_LED,LOW); // indicate error

  do {} while (digitalRead(START_BTN));
  return;
}

// send 4 bytes to target microcontroller, returns the fourth MISO byte
unsigned char Send_ISP(unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3) {
  // MO output
  // MI input
  unsigned char result = 0;

  // first byte
  for ( int i = 0x80 ; i>0 ; i /= 2 ) {
    digitalWrite(MOSI,(v0 & i));
    PULSE_SCK(CKEDGE);
    //result = ((result << 1) | digitalRead(MISO)); // shift contents of result left one bit, set LSB with MISO value
  }

  for ( int i = 0x80 ; i>0 ; i /= 2 ) { // second byte - MISO echos first byte
    digitalWrite(MOSI,(v1 & i));
    PULSE_SCK(CKEDGE);
    result = ((result << 1) | digitalRead(MISO));
  }
  if (result != v0 ) { // handle error
  }

  for ( int i = 0x80 ; i>0 ; i /= 2 ) { // third byte - MISO echos second byte
    digitalWrite(MOSI,(v2 & i));
    PULSE_SCK(CKEDGE);
    result = ((result << 1) | digitalRead(MISO));
  }
  if (result != v1 ) { // handle error
  }

  for ( int i = 0x80 ; i>0 ; i /= 2 ) { // fourth byte - MISO returns some value (depends on command)
    digitalWrite(MOSI,(v3 & i));
    PULSE_SCK(CKEDGE);
    result = ((result << 1) | digitalRead(MISO));
  }

  return result;
}

void Reset_Target() {
  digitalWrite(RESET,HIGH);
  digitalWrite(SCK,LOW); // has to be set LOW at startup, or PE fails
  delay(30);
  digitalWrite(RESET,LOW);
  delay(30); // minimum delay here is 20ms for the ATmega8
}

// prints the 16 signature bytes (device codes)
/*void Read_Signature() {
  Serial.println("SIGNATURES");
  for ( unsigned char x = 0 ; x<16 ; x++ ) {
    Serial.print(CMD_Read_Signature(x),HEX);
    Serial.print(",");
  }
  Serial.println("");
  Serial.println("END SIGNATURES");
}*/

// prints the flash memory
void Read_Flash() {
  unsigned int value = 0;
  Serial.println("READING FLASH");
  for ( unsigned int index = 0 ; index<(FLASH_MAX/2) ; index++ ) {
    if ( (index % PAGE_WORDS) == 0) {
      Serial.println("");
      Serial.print("Page ");
      Serial.print(index/PAGE_WORDS,DEC);
      Serial.print(" = ");
      if ( index/PAGE_WORDS < 100)
        Serial.print(" ");
    } else if ( (index % (PAGE_WORDS/2)) == 0) {
      Serial.println("");
      Serial.print("           ");
    }
    Serial.print(CMD_Read_Flash_Low(index),HEX);
    Serial.print(" ");
    Serial.print(CMD_Read_Flash_High(index),HEX);
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("END FLASH");
}

// prints the lock and fuse bits (no leading zeros)
void Read_Fuse() {
  Serial.print("Lock Bits: ");
  Serial.println(CMD_Read_Lock(),BIN);
  Serial.print("Fuse Low: ");
  Serial.println(CMD_Read_Fuse_Low(),BIN);
  Serial.print("Fuse High: ");
  Serial.println(CMD_Read_Fuse_High(),BIN);
}

// prints the contents of the bootloader table
/*void Show_Bootloader() {
  Serial.println("SHOWING BOOTLOADER");
  for ( unsigned int index = 0 ; (index <= BOOT_MAX) ; index++ ) {
    Serial.print(pgm_read_byte(&bootloader[index]),HEX);
    Serial.print(",");
  }
  Serial.println("");
  Serial.println("END BOOTLOADER");
}*/

/*void Write_Test() {
  for ( unsigned char page = 0 ; page<128 ; page++ ) {
    Serial.print("Writing page ");
    Serial.println(page,DEC);
    for ( unsigned char index = 0 ; index<32 ; index++ ) {
      CMD_Load_Page_Low(index,(page*32)+index);
      CMD_Load_Page_High(index,((page*32)+index) >> 8);
    }  
    CMD_Write_Page(page);
    delay(20);
  }
}*/


Projects Built with Arduino


Manuals


Arduino Tutorials

Official tutorial page
Information on the Arduino Mini
Bluetooth tutorial
Xbee (Zigbee) tutorial
DIY Arduino Shield
Serial LCD tutorial
Learning Electronics
Learning Programming
Asuro Robot and Arduino
Let the Arduino Sleep
Burning Bootloaders
CourseWare
SFU-SIAT Arduino Course Site
Stand alone 3.3V 8 MHz
Programming the Bluetooth WT11
Retrofitting Diecimila AutoReset
Bare Bones "Diecimila" Upgrade

Run Arduino on...

Linux
Ubuntu Linux
Debian Linux
Gentoo Linux
Slackware Linux
FreeBSD
Fedora Linux
The command line

Interface Arduino with...

Instant Reality (X3D)
Flash
Processing
PD (Pure Data)
Max/MSP/Jitter
VVVV
Director
Ruby
C
Linux TTY
Windows HyperTerminal
SuperCollider
Second Life
Firmata
SimpleMessageSystem Library
Python
other

Connect Hardware...

Code for the 74XX151
analog De/Mutliplexer 4051
Code for LCD displays
Serial LCD tutorial
Sparkfun SerLCD
DMX512
LED_Matrix
LED Sign
Rotary encoders
PS2 mouse interface
Effects processor controller
XBee Shield
ArduinoBT to Mobile Phone
Telephone style keypad
Computer brushless fan
SID-emulator
VMUSIC
Arduino Synth Page
Usb Memory Stick

Code Library

Native Capacitive Sensors
EEPROM and Flash tricks
Simple Message System
Metro Library
Interrupt example
Bit Math Tutorial
Windows command-line build
Make Arduino 0007 sketches smaller
Copy Bootloaders - BootCloner
Bootloader Development
Python 2B Protocol
Sketch Library
dataflash memory library

Resources

online electronic suppliers
local shops
datasheets
Arduino-like boards

Workshops


Languages?

Espa&ntilde;ol - Spanish
Fran&ccedil;ais
Projets
Italiano

People/Groups & Sites



--------------------------------------------------------------------------------


PARTICIPATE

request contributor access
suggestions
formatting suggestions
PmWiki
WikiSandBox training
Basic Editing
Cookbook (addons)
Documentation Index)


--------------------------------------------------------------------------------

login logout edit SideBar admin

Login

出0入0汤圆

发表于 2007-10-23 01:30:23 | 显示全部楼层
楼主的确应该指明出处,搜了一下,在这里:
http://www.arduino.cc/playground/BootCloner/BootCloner
头像被屏蔽

出0入0汤圆

发表于 2007-10-23 07:48:18 | 显示全部楼层
【23楼】 asdfasdf “去银行抢了100W,然后捐给慈善机构,按照你的伟大逻辑,是不是我就成英雄了? ”

是的,你就成了英雄。

目前的许多伟大的慈善家都是这样起家的。

网上的资料很多,相当部分的资料是互相参考的。我们推荐会员发贴时尽量注明出处, 不过实际操作中很难,而且我们也没有能力较对原始出处。

怎么评价 asdfasdf 呢? 无可否认是高手,但高手如果能歉虚的一面及乐于助人的一面,会更爱大家尊重。 不断针对本网站及我本人进行冷嘲热讽,有什么用处呢?

出0入0汤圆

发表于 2007-10-23 07:52:54 | 显示全部楼层
老大,你把那人给“瓶蔽”不就完了,影响气氛
头像被屏蔽

出0入0汤圆

发表于 2007-10-23 07:56:09 | 显示全部楼层
asdfasdf 的存在对我们网站的发展是一个促进。虽然有几次我也对asdfasdf 发表过不友善的评论,但仍是感激asdfasdf对我们做过的贡献。

而且,在许多地方,可以看得出 asdfasdf 是一位超级高手。

欢迎asdfasdf 加入我们网站。或者我们来一次和平的谈判吧。大家能在网上聚在一起也算是缘分,我们其实并没有什么过节,可能有一些小误会,其实大家都清楚对方不是坏人。

出0入0汤圆

发表于 2007-10-23 08:28:02 | 显示全部楼层
【27楼】 chuxue
积分:338
派别:
等级:------
来自:上海
老大,你把那人给“瓶蔽”不就完了,影响气氛  
=====================
小狗腿子,你看好了,站长说我是有贡献的。
只不过,正所谓忠言逆耳而已。对于这个怎么看,
要看一个人的度量,不过,对于你这种只会没有
根据狂吠的animal来说,是很难理解的。

出0入0汤圆

发表于 2007-10-23 08:39:52 | 显示全部楼层
这种含有英文注释的程序,一看就是抄袭老外的。说实话,还没有看到那个程序员的注释用的英文能够很地道没有语病。

出0入228汤圆

 楼主| 发表于 2007-10-23 09:48:57 | 显示全部楼层
唉,,,,,,,,,,,,,,,
一不小心就成了剽窃专家了,看来还是不敢乱发贴呀,
都被大家拍砖拍死了....

很多东西,网上都有类似的代码,问题是你有没想到能够帮助到你,能够应用到你的项目中去.
比如我在做(呵,要写成"改",是吧?大侠们???)这个东西的时候,目的就是找到一段单片机中的ISP程序而已.
就能做脱机复制机了.
这个东西的目的也就是读一块芯片到另一块芯片中.
很简单的应用呀!?
只不过我跨了一步,因为好象没有人这样做过,用另一片单片机做为源,有人做的都是买一块专用的FLASH芯片.这就
加大了一些难度,而我用另一片同型号的芯片做源,就很明了了.因为大家手上可能都不止有两片芯片吧.

我想我这个想法还是有一点点小价值的.

正因为简单,所以我也贴出来,让大家看看,能够得到大家评论,能够引起大家共鸣也是很开心的.
心里并不是希望有人来评价我的代码写得多好,语法有没毛病.因为我也不是什么大师.
偶尔敢把抄来的东西改一下贴出来也是需要有些小勇气的.呵.


关于ARDUINO,大家讨论的人也少,而我却搞了很长一段时间了.想来在国内也算早的.听不到大家对这个东西有什么评论,
好象见过的都说他太小儿科,碰都不去碰.
不过正好对我这种"低手+剽窃专家"的胃口.
呵,,,,,,,,,,

出0入4汤圆

发表于 2007-10-23 10:02:46 | 显示全部楼层
Arduino 很好,我去年按照它网站上的资料做了一个实验板,准备送给一个在读高中的朋友,让他可以学一下AVR,有几个零件没去找,我实在是太懒了 :)

Arduino 的 IDE 是用 java 写的,界面非常友好。我自己在 FreeBSD 中玩 AVR,Arduino 的网站上正好有一篇文章是讲这个东西的 "Arduino Software Under FreeBSD"(URL: http://www.arduino.cc/playground/Learning/FreeBSD),讲到如何在 FreeBSD 下面安装 java, 大家可以交流一下。

出0入228汤圆

 楼主| 发表于 2007-10-23 10:03:24 | 显示全部楼层
关于这个的进一步应用,我也想了很多,
可以搞成USBISP+复制一体机,
也可以加深一步做一下多种型号芯片的识别,
自动加密,
自动序列号控制,
...
...
...
这样的话好象与商品机也差不多了吧?本来我是想完成后贴出来或提出来的.
正是因为大家一起研究才好玩,所以才做了一个开始就发出来.
如果我做完这些再贴出来,"asdfasdf大侠"是不是也认为是我抄袭??

是不是"asdfasdf大侠"给我们大家造造福?
满足一下大家的期望?
把这些都完成了贴出来?
给大家看看你是不是从来不"借鉴"人家的代码?

我刚才搜了一下"asdfasdf大侠"发的贴子,好象从来没贴过代码哟,
也让我们大家见识一下嘛.

出0入228汤圆

 楼主| 发表于 2007-10-23 10:12:18 | 显示全部楼层
atommann:
arduino是一个开放的平台,PC,MAC,LINUX,下都能使用,而且上手简单.正因为如此,获得了
很多门外汉(比如我,我就是用这个上手的以前买过几块8051的开发板,就是因为太复杂,玩几天就扔一边)的
欢迎,
我认为学习单片机,不要把他想得太复杂,就是抄,你学会了抄,你的水平也就差不多啦.
不要小看抄,你会抄,而且抄得好,就已经证明了你是一个成熟的玩家了,
我想任何一个产品,都需要一个好的想法,其实很多的技术现在根本不需要我们一个一个去克服,
都有先人们研究过来了.就说这个AVR的"isp"功能,好象也是抄的吧?

主要是有想法,有创意,才会变成你自己的东西.

出0入0汤圆

发表于 2007-10-23 11:31:46 | 显示全部楼层
【29楼】 asdfasdf
/**********************************************
“小狗腿子,你看好了,站长说我是有贡献的。
  只不过,正所谓忠言逆耳而已。对于这个怎么看,
  要看一个人的度量,不过,对于你这种只会没有
  根据狂吠的animal来说,是很难理解的。       ”
**********************************************/

说话有个性,风格我喜欢。。哈哈。

出0入0汤圆

发表于 2007-10-23 11:55:12 | 显示全部楼层
我想,理性的朋友们应该仔细看这个帖子;

忠言逆耳啊!自古以来都是如此,被人误会,也是有可能的,但为了论坛的长远,我愿意背这个黑锅啊!!!

我们一直以来,都是极度反感别人剽窃我们的辛勤劳动成果的,对于开源的,我们应该更加尊重才是。


如果你站在别人的肩膀上,请记住那个人!就如你要记住你的恩师一样!不能有一点儿成绩,就忘了挖井人!!!


抄袭别人东西,并把别人版权换成自己,说自己是原创的,居然咄咄有理,真是伤感啊!我不多上说了!

出0入0汤圆

发表于 2007-10-23 12:48:55 | 显示全部楼层
在这里的应该都是技术、开发人员吧。

什么人我们最痛恨?

应该是用我们的工作成果,打上自己的名字去赚钱(名)的人吧。

“wxws”之前所做的和我说的有区别吗?即使有区别也仅仅是五十步与一百步的关系。

/***************************************************************
“我认为学习单片机,不要把他想得太复杂,就是抄,你学会了抄,你的水平也就差不多啦.
不要小看抄,你会抄,而且抄得好,就已经证明了你是一个成熟的玩家了, ”
***************************************************************/

诚然,抄是学习的必经过程。但是,盗亦有道。你抄也要注明从哪里抄的。

如果觉得“抄”这个字不好可以换成“参考”啊。就像国内绝大多数论文那样。

楼主把人家的版权信息删掉换成自己名字的行为就必然要遭到唾弃……

出0入0汤圆

发表于 2007-10-23 13:57:17 | 显示全部楼层
火药味好浓,我想是楼主一时忘了写上出处了.再说楼主发这个贴他没有想得到什么利益,出发点还是好的.

但若没有ASDFASDF的异议,我们根本不知道楼主借鉴别人的.我们把楼主想成是个非常厉害的高手了.

可是没有楼主发出来,像我这种小菜鸟,找不到国外别人的源程序,呵呵,看来楼主还是有一定贡献的.

出0入0汤圆

发表于 2007-10-23 14:37:16 | 显示全部楼层
回【21楼】 asdfasdf
你现在用来上网的电脑也是用盗版的操作系统吧?
你现在所写的每一个文字也有版权哦。
请您把你写的每个字也注明是从那个出版社出的书上学来的吧。
这里是学习的地方,请不要污染环境。
头像被屏蔽

出0入0汤圆

发表于 2007-10-23 15:38:27 | 显示全部楼层
呵呵,就此打住吧。这个问题永远不会有结论的。

【38楼】 yulutong 的评论比较中肯。

大家是来交流,吵起来大家的心情都不会舒畅,何必呢。

出0入0汤圆

发表于 2007-10-23 16:01:50 | 显示全部楼层
其实,不以商业目的也没什么。如果用于商业还是自己开发为好

出0入0汤圆

发表于 2007-10-23 16:04:01 | 显示全部楼层
中国人吗,中庸和谐吗。搞技术的应该不是打击对象

出0入228汤圆

 楼主| 发表于 2007-10-23 19:50:46 | 显示全部楼层
没劲!
头一次发贴就这样,呵呵,,,,,



我如果想真的呼悠大家,还不致于傻到不把里面的英文注释去掉吧?
或者改头换面,这样做也不复杂吧?
程序我是抄了,但想法是我原创的吧?
有了那个中文的ISP翻译,想代码化也不是很难的事吧?
还有那些下载器的源代码呢,也可以一样用吧?

那怎么这么多高手都没想到这个应用????????
偏偏搞得我这个"抄手"来这里献宝!!!!!!!!!!!!!

出0入0汤圆

发表于 2007-10-23 19:59:23 | 显示全部楼层
LZ,我支持你,其他的就当他们放P

出0入0汤圆

发表于 2007-10-23 22:11:25 | 显示全部楼层
支持!!!!!!!!!

出0入0汤圆

发表于 2007-10-23 22:56:43 | 显示全部楼层
支持楼主!
头像被屏蔽

出0入0汤圆

发表于 2007-10-24 06:49:20 | 显示全部楼层
我也支持楼主

出0入8汤圆

发表于 2007-10-24 16:51:19 | 显示全部楼层
支持楼主

出0入0汤圆

发表于 2007-10-24 20:40:49 | 显示全部楼层
支持有东西就共享的楼主

出0入0汤圆

发表于 2007-10-24 23:24:54 | 显示全部楼层
支持!  没有抄怎么有进步

出0入0汤圆

发表于 2007-10-25 01:26:35 | 显示全部楼层
学习这个东西,本来就是这样的,谁一开始就完全会的!
在说看看原出处,未必作者就有要求你要著名出处!~~
况且原作者能大度的公开代码,就表示愿意给大家学习,与使用这段代码,著不著名出处,是个问题,但是不严重!~

某些人确实太小题大做了

出0入0汤圆

发表于 2007-10-25 08:49:43 | 显示全部楼层
支持楼主,支持共享,更加支持辛苦的原创,其实我们写的每个字都是抄的字典上的,呵呵....
头像被屏蔽

出0入0汤圆

发表于 2007-10-25 08:54:10 | 显示全部楼层
【52楼】 aprilis 也不用将它举例成抄字典 ...

尊重版权是对的。 尽量注明出处就行。但网上发表一些共享资料,与写正规论文不同,不需要严格的引经据典。 本贴楼主虽然疏忽了注明出处,但也明显看出是无心之失。 而且楼主的共享精神值得表扬。

出0入0汤圆

发表于 2007-10-25 09:28:52 | 显示全部楼层
呵呵...armok回帖真快啊!我是开个玩笑哦,原创肯定是要尊重的,做技术的,都希望自己的作品能得到更多人的认同.

出0入0汤圆

发表于 2008-11-17 21:54:32 | 显示全部楼层
这个很好玩哦

出0入0汤圆

发表于 2008-11-17 22:17:10 | 显示全部楼层
点击此处下载&nbsp;ourdev_502414.rar(文件大小:84K)&nbsp;(原文件名:myisp_mega48.rar)&nbsp;



我自己写的mega48拷贝机,绝对是中国人写的,原理是通用的,用的icc编译器.

供大家参考,硬件电路根据注释可以推导出来.

出0入0汤圆

发表于 2008-11-17 22:58:56 | 显示全部楼层
56楼是珠海哪的,交个朋友!

出0入0汤圆

发表于 2008-11-18 09:13:38 | 显示全部楼层
挺好的东西

出0入0汤圆

发表于 2008-12-11 19:46:40 | 显示全部楼层
56楼,能再给详细的资料吗?比如原理图,制作方法,使用方法。

出0入70汤圆

发表于 2008-12-11 20:49:33 | 显示全部楼层
其实这样交流才带劲

^-~

出0入0汤圆

发表于 2008-12-11 22:00:20 | 显示全部楼层
LZ不要在意,大家都是支持你滴~~这里又不是国家专利局,谈什么“剽窃”呢?能够把资料整理出来使大家能够检索得到,就是好事一件啊,相信弄一堆英文上来大多数的朋友都看不懂,跟没有一样

出0入0汤圆

发表于 2008-12-11 22:04:48 | 显示全部楼层
其实我很反感“技术高手”的酸腐气,本坛的资料虽然大多数已经整理得很好(相信在国内能达到这种水平的论坛少之又少),但很多还是没有充分考虑菜鸟的需要,点拨的不够详细。谁都是从菜鸟过来的,所以任何对菜鸟的冷嘲热讽都是不足取的。这种启蒙的工作,“高手”同志不屑去做的话,请保持沉默,不要把想做这工作的热心人恶心跑了

出0入0汤圆

发表于 2010-12-12 23:37:32 | 显示全部楼层
mark~~

出0入0汤圆

发表于 2010-12-13 09:38:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-28 22:02:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-29 13:10:53 | 显示全部楼层
有用

出0入0汤圆

发表于 2011-4-30 15:28:59 | 显示全部楼层
顶一下。

出0入0汤圆

发表于 2011-7-25 18:15:20 | 显示全部楼层
请问你做的那个M8芯片复制机,好不好改成MEGA64对MEGA64的,用你M8的HEX文件PROTEUS调试通讯显示不正常,

出0入0汤圆

发表于 2011-7-25 18:16:58 | 显示全部楼层
晶振10M,BPS 19200,

出0入0汤圆

发表于 2011-7-25 18:30:26 | 显示全部楼层
老帖重看

出0入0汤圆

发表于 2011-7-25 18:33:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-25 23:15:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-25 23:34:54 | 显示全部楼层
MARK....顶楼主.....

出0入0汤圆

发表于 2011-7-25 23:45:56 | 显示全部楼层
MARK!

出0入0汤圆

发表于 2011-9-24 10:55:34 | 显示全部楼层
mark  顶一下

出0入0汤圆

发表于 2015-2-11 10:00:49 | 显示全部楼层
这贴非常有份量 感谢感谢

出0入13汤圆

发表于 2015-2-11 20:47:58 来自手机 | 显示全部楼层
这个帖不错

出0入0汤圆

发表于 2015-2-20 12:57:02 | 显示全部楼层
waltonzxh 发表于 2008-11-17 22:17
点击此处下载&nbsp;ourdev_502414.rar(文件大小:84K)&nbsp;(原文件名:myisp_mega48.rar)&nbsp;



我自己写的 ...

您好!您这个复制机是把24C256里的程序复制到目标芯片?还是直接把源芯片的程序复制到目标芯片?

出0入0汤圆

发表于 2015-2-28 13:20:11 | 显示全部楼层
中国人喜欢把抄袭的东西说成自己研发的,各行各业都是,大到军事,小到民用,在中国专利没屁用,以前美国人喜欢抄袭英国,后来美国自羞,奋发图强居上

出0入0汤圆

发表于 2015-3-1 09:06:39 | 显示全部楼层
支持一下,什么事情都有个过程,知识产权也是,商业环境成熟后越来越好
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 05:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表