// // ATmaga8のヒューズ変更用 パラレルプログラマ // // MCU:AT90S4433 // // 2003.9.15 KAWAKAMI Yukio // #include #include #include #include #include // 書きこむヒューズデータ //#define FUSE_H 0xD9 #define FUSE_H 0xD1 // チップ消去から EEPROMを保護 //#define FUSE_L 0xEF // クロック外部発振 3〜8MHz //#define FUSE_L 0xE0 // クロック外部入力 #define FUSE_L 0xE3 // クロック内部 4MHz //#define FUSE_L 0xAF // BOD許可、クロック外部発振 3〜8MHz #define ERASE_CHIP 0x80 // チップ消去コマンド #define WRITE_FUSE 0x40 // ヒューズ書き込みコマンド #define READ_FUSE 0x04 // ヒューズ読みだしコマンド #define LF 10 #define ON 1 #define OFF 0 #define SWITCH 0 // PORTD #define LED 1 #define LED_ON sbi(PORTD,LED) #define LED_OFF cbi(PORTD,LED) #define OE 2 // PORTD #define OE_H sbi(PORTD,OE) #define OE_L cbi(PORTD,OE) #define WR 3 #define WR_H sbi(PORTD,WR) #define WR_L cbi(PORTD,WR) #define BS1 4 #define BS1_H sbi(PORTD,BS1) #define BS1_L cbi(PORTD,BS1) #define XA0 5 #define XA0_H sbi(PORTD,XA0) #define XA0_L cbi(PORTD,XA0) #define XA1 6 #define XA1_H sbi(PORTD,XA1) #define XA1_L cbi(PORTD,XA1) #define PAGEL 7 #define PAGEL_H sbi(PORTD,PAGEL) #define PAGEL_L cbi(PORTD,PAGEL) #define BS2 2 // PORTC #define BS2_H sbi(PORTC,BS2) #define BS2_L cbi(PORTC,BS2) #define XTAL1 3 #define XTAL1_H sbi(PORTC,XTAL1) #define XTAL1_L cbi(PORTC,XTAL1) #define RDY 4 #define RESET 5 #define RESET_H cbi(PORTC,RESET) #define RESET_L sbi(PORTC,RESET) typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; void wait(void); void wait0(void); void set_command(uchar com); void set_data(uchar data); uchar read_data(void); void write_puls(void); void error(void); #define NOP asm volatile("nop\n"::) #define WDR asm volatile("wdr\n"::) //********************************* // メインルーチン //********************************* int main (void) { uint i; int t, retry; outp(0x00, PORTB); // PB5〜0 L outp(0x00, DDRB); // PB5〜0 out outp(0x00, PORTC); // PC5 H, PC4〜0 L outp(0x2C, DDRC); // PC5, PC4〜0 out outp(0x01, PORTD); // PD0 pull up outp(0xFE, DDRD); // PD7〜1 out, PD0 in outp(0x03, TCCR0); // タイマープリスケーラ 1/64 // 起動時に3回点滅 for (i=0; i<3; i++){ LED_ON; for (t=0; t<200; t++){ wait(); } LED_OFF; for (t=0; t<200; t++){ wait(); } } // スイッチ入力待ち while(inp(PIND)&(1<= 8) error(); wait(); wait(); // ヒューズ上位バイト書込み for (retry = 0; retry < 8; retry++){ set_command(WRITE_FUSE); set_data(FUSE_H); BS1_H; BS2_L; write_puls(); wait(); wait(); set_command(READ_FUSE); BS1_H; BS2_H; if (read_data() == FUSE_H) break; } if (retry >= 8) error(); wait(); wait(); // 終わった outp(0x00, DDRB); cbi(DDRC, 0); cbi(DDRC, 1); LED_ON; RESET_L; outp(0x00, PORTB); // PB5〜0 L cbi(DDRC, 0); cbi(DDRC, 1); for(;;); } // エラー表示 void error(void){ int t; outp(0x00, DDRB); cbi(DDRC, 0); cbi(DDRC, 1); LED_ON; RESET_L; outp(0x00, PORTB); // PB5〜0 L cbi(DDRC, 0); cbi(DDRC, 1); for (;;){ LED_ON; for (t=0; t<200; t++){ wait(); } LED_OFF; for (t=0; t<200; t++){ wait(); } } } // 書込みパルス発生 void write_puls(void){ WR_L; wait0(); WR_H; while(!(inp(PINC) & (1<> 6), PORTC); XTAL1_H; wait0(); XTAL1_L; wait0(); } // 8bitデータセット void set_data(uchar data){ XA1_L; XA0_H; outp(0xFF, DDRB); sbi(DDRC, 0); sbi(DDRC, 1); outp((data & 0x3F), PORTB); outp((inp(PORTC) & 0xFC)|((data & 0xC0) >> 6), PORTC); XTAL1_H; wait0(); XTAL1_L; wait0(); } // 8bitデータ読みだし uchar read_data(void){ uchar data; outp(0, DDRB); cbi(DDRC, 0); cbi(DDRC, 1); outp(0xFF, PORTB); // プルアップ sbi(PORTC, 0); sbi(PORTC, 1); OE_L; wait0(); data = (inp(PINC) & 0x03) << 6; data |= inp(PINB) & 0x3F; OE_H; return data; } // 16〜32μS時間待ち void wait0(void){ uchar t; t = inp(TCNT0); while(inp(TCNT0) == t); t = inp(TCNT0); while(inp(TCNT0) == t); } // 約1mS時間待ち void wait(void){ int i; for (i = 0; i < 32; i++){ wait0(); } }