目次

ファームウエア仕様検討

 ファームウエアの仕様を検討します。

 ヒューズリセッターは、何度も使うことがないので、次の3機能が
 実現できればよいと判断しました。
  1. 電源制御とパラレルモードへの遷移
  2. チップイレーズ
  3. ヒューズバイト書込み
 機能は、ファームウエアが担当しますが、処理シーケンスはパーソナル  コンピュータから指定します。  パーソナルコンピュータとは、シリアルインタフェースで接続します。  最近のパーソナルコンピュータは、インタフェースI/OがUSBだけという  ので、その場合、USB/シリアル変換器を接続して対応します。  シリアルインタフェースを利用する場合は、プロトコルを決めます。  プロトコルは、以下とします。  USB/シリアル変換器とマイコンを接続するために、簡易レベルコンバータを  利用。レベルコンバータの回路図は、以下。  ファームウエアを考える場合、ハードウエアがどうなっているか明らかに  しておかなければなりません。マイコンから制御する回路の図面は以下。  3チャネルのコネクタで、マイコンと接続します。  各チャネルに、必要な機能を割当てます。  ハードウエアの仕様が固まったので、3機能に分割して処理内容を検討します。

電源制御とパラレルモードへの遷移

 電源制御は、+12V、+5Vを端子に出力するか否かを制御します。  ポートBの7ビット、6ビットに1か0を出力すればよいので、個別に  該当ビットに1か0を出力します。   5V出力  PORTB &= ~(1 << con_5V) ;   12V出力  PORTB &= ~(1 << con_12V) ;   5V停止  PORTB |= (1 << con_5V) ;   12V停止  PORTB |= (1 << con_12V) ;  パラレルモードへの遷移は、次の信号線をすべて0にしてから  XTAL1に最低6回Hパルスを出力します。   PAGEL   XA1   XA0   BS1  XTAL1は、他の処理でも、1パルスを出力するがあるのでN回  (Nは、1〜255)出力できるようにします。 void send_pulse(UBYTE x) { UBYTE i ; /* loop */ for ( i = 0 ; i < x ; i++ ) { /* high */ PORTC |= (1 << XTAL1) ; /* low */ PORTC &= ~(1 << XTAL1) ; } }  電源の接続と切断は、パラメータ指定で選べるようにした方が  ミスは少なくなるので、ひとつにまとめておきます。 void transfer_pgm(UBYTE x) { /* set parallel mode */ PORTC &= 0x0f ; /* transfer program mode */ if ( x == ON ) { /* enable +5V */ PORTB &= ~(1 << con_5V) ; /* send pulse */ send_pulse(8); /* delay */ delay_ms(1); /* enable +12V */ PORTB &= ~(1 << con_12V) ; } else { /* disable +12V */ PORTB |= (1 << con_12V) ; /* delay */ delay_ms(1); /* disable +5V */ PORTB |= (1 << con_5V) ; } /* delay */ delay_ms(1); }  電源の接続と切断を、パーソナルコンピュータから制御するため  コマンドを用意します。   電源接続 'R'コマンド   電源切断 'r'コマンド  コマンドには、デリミタとして'\r'を付加します。

チップイレーズ

 チップイレーズは、プログラムROM、EEPROMの内容をクリアします。  また、LockBitを解除します。  LockBitの設定で、FuseByteを設定可能か禁止を指定可能。  LockBitの解除では、FuseByte設定を可能。  チップイレーズのためのシーケンスは、以下。
  1. (XA1,XA0,BS2,BS1)=(1,0,0,0)に指定
  2. チップイレーズコマンド(0x80)を出力
  3. XTAL1に、Hパルスを1つ出力
  4. WRに、Lパルスを1つ出力
  5. 時間待ち
  6. RDY/BUSYが、Hになることを確認
 シーケンスを、一つにまとめます。 void erase_chip(void) { /* select command XA1 = 1 , XA0 = 0 */ /* BS1 = 0 */ set_signal(2,0); /* command */ PORTA = 0x80 ; /* XTAL1 pulse */ send_pulse(1); /* wr pulse */ send_wr(ON); send_wr(OFF); /* delay */ delay_ms(1); /* check */ while ( !(PINC & (1 << RDY_BUSY)) ) ; }  XA1とXA0、BS2とBS1はペアで利用されるので、まとめて1と0を  指定できるようにします。 void set_signal(UBYTE xa,UBYTE bs) { /* XA handling */ PORTC &= ~(1 << XA1); PORTC &= ~(1 << XA0); if ( xa == 1 ) { PORTC |= (1 << XA0); } if ( xa == 2 ) { PORTC |= (1 << XA1); } /* BS handling */ PORTC &= ~(1 << BS1); PORTB &= ~(1 << BS2); if ( bs == 1 ) { PORTC |= (1 << BS1); } if ( bs == 2 ) { PORTB |= (1 << BS2); } if ( bs == 3 ) { PORTB |= (1 << BS1); PORTB |= (1 << BS2); } }  WRは、H、Lを出力できるようにします。 void send_wr(UBYTE x) { if ( x == ON ) { PORTC &= ~(1 << nWR); } else { PORTC |= (1 << nWR); } }

ヒューズバイト書込み

 ヒューズバイトは、3バイトあります。  3バイトはユーザー指定なので、これらはパーソナルコンピュータ  から設定することにします。  ヒューズバイトの1バイト設定シーケンスは、以下です。
  1. (XA1,XA0,BS2,BS1)=(1,0,0,0)に指定
  2. ヒューズコマンド(0x40)を出力
  3. XTAL1に、Hパルスを1つ出力
  4. (XA1,XA0)=(0,1)に指定
  5. (BS2,BS1)=(0,0)、(0,1)、(1,0)のいずれかに設定
  6. ヒューズデータを出力
  7. XTAL1に、Hパルスを1つ出力
  8. WRに、Lパルスを1つ出力
  9. 時間待ち
  10. RDY/BUSYが、Hになることを確認
 ヒューズバイトは3バイトあるので、(BS2,BS1)の組み合わせで、どの  バイトかを指定します。  ヒューズバイトが配列変数fsの中にあるとして、3回繰り返す処理で  記述します。 void set_fuse(void) { UBYTE i ; UBYTE tmp ; /* send command (Write Fuse)*/ set_signal(2,0); PORTA = 0x40 ; send_pulse(1); /* write bytes */ for ( i = 0 ; i < 3 ; i++ ) { /* send data */ set_signal(1,i); PORTA = *(fs+i) ; send_pulse(1); /* write data */ send_wr(ON); send_wr(OFF); /* delay */ delay_ms(1); /* check */ while ( !(PINC & (1 << RDY_BUSY)) ) ; /* return */ set_signal(1,0); } }

全ソースコード

 複数のマイコンチップに対応できるように、一部を修正しています。  また、シリアルインタフェースとコマンドインタプリタを入れてます。 #include <avr/io.h> #include <avr/io8535.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define OFF 0 #define ON OFF+1 typedef unsigned char UBYTE ; typedef unsigned short UWORD ; typedef unsigned long ULONG ; typedef signed char SBYTE ; typedef signed short SWORD ; typedef union { struct { unsigned char B0:1; unsigned char B1:1; unsigned char B2:1; unsigned char B3:1; unsigned char B4:1; unsigned char B5:1; unsigned char B6:1; unsigned char B7:1; } BIT ; unsigned char DR ; } FLAGSP ; volatile FLAGSP x_flags ; #define SFLAG x_flags.BIT.B0 #define TFLAG x_flags.BIT.B1 #define DFLAG x_flags.BIT.B7 #define BUFSIZE 8 volatile UBYTE sbuf[BUFSIZE] ; volatile UBYTE sindex; #define NO 0 #define YES NO+1 #define PAGEL 7 #define XA1 6 #define XA0 5 #define BS1 4 #define nWR 3 #define nOE 2 #define XTAL1 1 #define RDY_BUSY 0 #define con_12V 7 #define con_5V 6 #define MBIT 1 #define BS2 0 #define CKND_644 0 #define CKND_1200 1 #define CKND_t2313 2 #define CKND_328 3 volatile ULONG tickcount ; volatile UBYTE fs[3] ; const prog_char msg_h[] PROGMEM = "? help" ; const prog_char msg_r[] PROGMEM = "R set program mode" ; const prog_char msg_sr[] PROGMEM = "r exit program mode" ; const prog_char msg_e[] PROGMEM = "E chip erase" ; const prog_char msg_p[] PROGMEM = "P set fuse bits" ; const prog_char msg_sp[] PROGMEM = "p show fuse bits" ; const prog_char msg_f[] PROGMEM = "F send fuse bits" ; const prog_char msg_c[] PROGMEM = "C chose chip" ; const prog_char msg_sc[] PROGMEM = "c show chip" ; const prog_char chip644[] PROGMEM = "644" ; const prog_char chip1200[] PROGMEM = "1200" ; const prog_char chipt2313[] PROGMEM = "t2313" ; const prog_char chip328[] PROGMEM = "t328" ; const prog_char asc_code[] PROGMEM = "0123456789ABCDEF" ; volatile UBYTE lcnt ; volatile UBYTE cknd ; /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); UBYTE get_hex(UBYTE x); void uart_putchar(UBYTE x); void uart_puts(UBYTE *x); void crlf(void); void erase_chip(void); void send_pulse(UBYTE x); void send_wr(UBYTE x); void delay_ms(UBYTE x); void transfer_pgm(UBYTE x); void set_fuse(void); void set_signal(UBYTE xa,UBYTE bs); void command_interpret(void); #define MASKFF 0xff #define MASK0F 0x0f #define MASKF0 0xf0 /*------*/ /* main */ /*------*/ int main(void) { /* disable interrupt */ cli(); /* */ user_initialize(); /* enable interrupt */ sei(); /* loop */ while ( ON ) { /* watch flag */ if ( SFLAG ) { /* clear flag */ SFLAG = OFF ; /* command interpreter */ command_interpret(); } if ( TFLAG == OFF ) { /* clear flag */ TFLAG = OFF ; /* command interpreter */ lcnt++ ; PORTB &= ~(1 << MBIT); if ( lcnt & 1 ) { PORTB |= (1 << MBIT); } } } /* dummy */ return 0 ; } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ #define FOSC 8000000 #define BAUD 9600 #define MYUBRR (FOSC/16/BAUD)-1 void user_initialize(void) { /* PORT A */ PORTA = 0b00000000 ; /* 00000000 */ DDRA = 0b11111111 ; /* oooooooo */ /* PORT C */ PORTC = 0b00001100 ; /* 00001100 */ DDRC = 0b11111110 ; /* oooooooi */ /* PORT B */ PORTB = 0b11000000 ; /* 11000000 */ DDRB = 0b11111111 ; /* oooooooo */ /* PORT D */ PORTD = 0b00000000 ; /* 00000000 */ DDRD = 0b11111110 ; /* oooooooi */ /* */ x_flags.DR = 0 ; *(fs+0) = 0xE2 ; *(fs+1) = 0xD9 ; *(fs+2) = 0xFF ; tickcount = 0 ; lcnt = 0 ; /* initialize serial */ { /* clear index */ sindex = 0 ; /* clear buffer */ *(sbuf+0) = 0 ; /* set Baud Rate Registers */ UBRR = MYUBRR ; /* Enable receive interrupt , receive module and transmit module */ UCR = (1 << RXCIE) | (1 << TXEN) | (1 << RXEN) ; } /* initialize timer1 */ { /* clear counter */ TCNT1 = 0 ; /* set value */ OCR1A = 999; OCR1B = 1500; /* select /8 prescale (1MHz) */ TCCR1B = (1 << CS11) ; /* Enable compare match interruption */ TIMSK = (1 << OCIE1A) ; } } /* timer1 */ ISR(TIMER1_COMPA_vect) { tickcount++; TFLAG = ON ; } /* UART receive interrupt */ ISR(UART_RX_vect) { UBYTE ch ; /* get 1 charactoer */ ch = UDR ; /* store */ *(sbuf+sindex) = ch ; sindex++ ; /* judge */ if ( ch == '\r' ) { SFLAG = ON ; sindex = 0 ; } } UBYTE get_hex(UBYTE x) { volatile UBYTE result ; /* default */ result = 0 ; if ( '0' <= x && x <= '9' ) { result = x - '0' ; } if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10; }; if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10; }; return result ; } void uart_putchar(UBYTE x) { while ( !(USR & (1 << UDRE)) ) {} UDR = x ; } void uart_puts(UBYTE *x) { while ( *x != '\0' ) { uart_putchar( *x ) ; x++ ; } crlf(); } void crlf(void) { uart_putchar('\r'); uart_putchar('\n'); } void erase_chip(void) { /* select command XA1 = 0 , XA0 = 1 */ /* (BS2,BS1) = (0,0) */ set_signal(1,0); /* command */ PORTA = 0x80 ; /* XTAL1 pulse */ send_pulse(1); /* wr pulse */ send_wr(ON); send_wr(OFF); /* delay */ delay_ms(1); /* check */ if ( cknd != CKND_1200 ) { while ( !(PINC & (1 << RDY_BUSY)) ) ; } } void send_pulse(UBYTE x) { UBYTE i ; /* loop */ for ( i = 0 ; i < x ; i++ ) { /* high */ PORTC |= (1 << XTAL1) ; /* low */ PORTC &= ~(1 << XTAL1) ; } } void send_wr(UBYTE x) { if ( x == ON ) { PORTC &= ~(1 << nWR); } else { PORTC |= (1 << nWR); } } void delay_ms(UBYTE x) { ULONG target ; /* calculate target */ target = tickcount + x ; /* wait */ while ( target > tickcount ) ; } void transfer_pgm(UBYTE x) { /* set parallel mode */ PORTC &= 0x0f ; /* transfer program mode */ if ( x == ON ) { /* set tiny2313 port value (nWR = 0) */ if ( cknd == CKND_t2313 ) { PORTC &= ~(1 << nWR) ; } /* enable +5V */ PORTB &= ~(1 << con_5V) ; /* send pulse */ if ( cknd == CKND_644 ) { send_pulse(8); } /* delay */ delay_ms(1); /* enable +12V */ PORTB &= ~(1 << con_12V) ; /* delay */ delay_ms(1); /* reset tiny2313 port value (nWR = 1) */ if ( cknd == CKND_t2313 ) { PORTC |= (1 << nWR) ; } } else { /* disable +12V */ PORTB |= (1 << con_12V) ; /* delay */ delay_ms(1); /* disable +5V */ PORTB |= (1 << con_5V) ; /* delay */ delay_ms(1); } } void set_fuse(void) { UBYTE i ; UBYTE tmp ; /* send command (Write Fuse) */ set_signal(2,0); PORTA = 0x40 ; send_pulse(1); /* write bytes */ for ( i = 0 ; i < 3 ; i++ ) { /* send data */ set_signal(1,i); PORTA = *(fs+i) ; send_pulse(1); /* write data */ send_wr(ON); send_wr(OFF); /* delay */ delay_ms(1); /* check */ while ( !(PINC & (1 << RDY_BUSY)) ) ; /* return */ set_signal(1,0); } } void set_signal(UBYTE xa,UBYTE bs) { /* XA handling */ PORTC &= ~(1 << XA1); PORTC &= ~(1 << XA0); if ( xa == 1 ) { PORTC |= (1 << XA0); } if ( xa == 2 ) { PORTC |= (1 << XA1); } /* BS handling */ PORTC &= ~(1 << BS1); PORTB &= ~(1 << BS2); if ( bs == 1 ) { PORTC |= (1 << BS1); } if ( bs == 2 ) { PORTB |= (1 << BS2); } } void command_interpret(void) { UBYTE cmd ; UBYTE tmp ; UBYTE chx ; UBYTE sd[2] ; char msg[20] ; /* get command */ cmd = *(sbuf+0) ; /* transfer program mode */ if ( cmd == 'R' ) { transfer_pgm(ON) ; } /* exit program mode */ if ( cmd == 'r' ) { transfer_pgm(OFF) ; } /* perform chip erase */ if ( cmd == 'E' ) { erase_chip() ; } /* set fuse byte */ if ( cmd == 'P' ) { /* get channel */ chx = get_hex( *(sbuf+3) ) ; /* get code */ tmp = get_hex( *(sbuf+1) ) ; tmp <<= 4 ; tmp |= get_hex( *(sbuf+2) ) ; /* deliver */ *(fs+chx) = tmp ; } /* show fuse byte */ if ( cmd == 'p' ) { /* get ascii code */ strcpy_P(msg,asc_code) ; for ( chx = 0 ; chx < 3 ; chx++ ) { /* get code */ tmp = *(fs+chx) ; /* separate */ tmp >>= 4 ; tmp &= MASK0F ; *(sd+0) = (UBYTE)msg[tmp]; /* get code */ tmp = *(fs+chx) ; /* separate */ tmp &= MASK0F ; *(sd+1) = (UBYTE)msg[tmp]; /* show */ uart_putchar( *(sd+0) ); uart_putchar( *(sd+1) ); crlf(); } } /* store fuse byte */ if ( cmd == 'F' ) { set_fuse(); } /* chose chip type */ if ( cmd == 'C' ) { cknd = CKND_644 ; if ( *(sbuf+1) == '1' ) { cknd = CKND_1200 ; } if ( *(sbuf+1) == '2' ) { cknd = CKND_t2313 ; } if ( *(sbuf+1) == '3' ) { cknd = CKND_328 ; } } /* show chip type */ if ( cmd == 'c' ) { if ( cknd == CKND_644 ) { strcpy_P(msg,chip644) ; } if ( cknd == CKND_1200 ) { strcpy_P(msg,chip1200) ; } if ( cknd == CKND_t2313 ) { strcpy_P(msg,chipt2313); } if ( cknd == CKND_328 ) { strcpy_P(msg,chip328) ; } uart_puts((UBYTE *)msg) ; } /* help */ if ( cmd == '?' ) { strcpy_P(msg,msg_h) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_r) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_sr); uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_e) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_p) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_sp); uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_f) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_c) ; uart_puts((UBYTE *)msg) ; strcpy_P(msg,msg_sc); uart_puts((UBYTE *)msg) ; } crlf(); }  ATtiny2313を利用したファームウエアの  ソースコードは以下です。 #include <avr/io.h> #include <avr/interrupt.h> #define ON 1 #define OFF 0 #define PWR_BIT 4 #define CON_BIT 5 #define D_BIT 6 #define PWR12 2 #define PWR5 1 #define CMD_CHIP_ERASE 0x80 #define CMD_WR_FUSE 0x40 typedef unsigned char UBYTE ; typedef unsigned int UWORD ; typedef unsigned long ULONG ; void usr_init(void); void send_pwr(UBYTE x); void send_con(UBYTE x); void send_dat(UBYTE x); void send_pcd(UBYTE kind,UBYTE x); void delay_ms(UBYTE x); volatile ULONG timcnt ; volatile UBYTE state ; volatile UBYTE eflag ; int main(void) { /* initialize */ usr_init() ; /* enable interrupt */ sei(); /* endless loop */ while ( ON ) { /* state machine */ switch ( state ) { /* wait trigger */ case 0 : state = 0 ; if ( eflag == ON ) { /* clear flag */ eflag = OFF ; /* next */ state = 1 ; } break ; /* impress +5V */ case 1 : state = 2 ; send_pwr( PWR5 ) ; delay_ms(1); break ; /* impress +12V */ case 2 : state = 3 ; send_pwr( PWR12 | PWR5 ) ; delay_ms(2); break ; /* chip erase <0> */ case 3 : state = 4 ; send_dat( CMD_CHIP_ERASE ); send_con( 0x13 ); break ; /* chip erase <1> latch command */ case 4 : state = 5 ; send_con( 0x93 ); send_con( 0x13 ); break ; /* chip erase <2> write pulse */ case 5 : state = 6 ; send_con( 0x11 ); send_con( 0x13 ); break ; /* chip erase <3> delay */ case 6 : state = 7 ; delay_ms(10); break ; /* Write LOW fuse bit <0> */ case 7 : state = 8 ; send_dat( CMD_WR_FUSE ); send_con( 0x13 ); break ; /* write LOW fuse bit <1> latch command */ case 8 : state = 9 ; send_con( 0x93 ); send_con( 0x13 ); break ; /* Write LOW fuse bit <2> */ case 9 : state = 10 ; send_dat( 0xdf ); send_con( 0x0b ); break ; /* write LOW fuse bit <3> latch data */ case 10: state = 11 ; send_con( 0x8b ); send_con( 0x0b ); break ; /* write LOW fuse bit <4> write pulse */ case 11: state = 12 ; send_con( 0x09 ); send_con( 0x0b ); break ; /* write LOW fuse bit <5> delay */ case 12: state = 13 ; delay_ms(5); break ; /* Write HIGH fuse bit <0> */ case 13: state = 14 ; send_dat( CMD_WR_FUSE ); send_con( 0x13 ); break ; /* write HIGH fuse bit <1> latch command */ case 14: state = 15 ; send_con( 0x93 ); send_con( 0x13 ); break ; /* Write HIGH fuse bit <2> */ case 15: state = 16 ; send_dat( 0xdf ); send_con( 0x0b ); break ; /* write HIGH fuse bit <3> latch data */ case 16: state = 17 ; send_con( 0x8b ); send_con( 0x0b ); break ; /* write HIGH fuse bit <4> write pulse */ case 17: state = 18 ; send_con( 0x0f ); send_con( 0x0d ); send_con( 0x0f ); break ; /* write HIGH fuse bit <5> delay */ case 18: state = 19 ; send_con( 0x0b ); delay_ms(5); break ; /* Write EXT fuse bit <0> */ case 19: state = 20 ; send_dat( CMD_WR_FUSE ); send_con( 0x13 ); break ; /* write EXT fuse bit <1> latch command */ case 20: state = 21 ; send_con( 0x93 ); send_con( 0x13 ); break ; /* Write EXT fuse bit <2> */ case 21: state = 22 ; send_dat( 0xff ); send_con( 0x0b ); break ; /* write EXT fuse bit <3> latch data */ case 22: state = 23 ; send_con( 0x8b ); send_con( 0x0b ); break ; /* write EXT fuse bit <4> write pulse */ case 23: state = 24 ; send_con( 0x2b ); send_con( 0x29 ); send_con( 0x2b ); break ; /* write EXT fuse bit <5> delay */ case 24: state = 25 ; send_con( 0x0b ); delay_ms(5); break ; /* default cmd and data */ case 25: state = 26 ; send_dat( 0x00 ); send_con( 0x03 ); break ; /* disable +12V */ case 26: state = 27 ; send_pwr( PWR5 ); delay_ms(1); break ; /* disable +5V */ case 27: state = 0 ; send_pwr( 0x00 ); delay_ms(5); break ; default : state = 0 ; break ; } } /* dummy */ return 0 ; } void usr_init(void) { /* PORTB */ PORTB = 0b00000000 ; DDRB = 0b11111111 ; /* PORTD */ PORTD = 0b00000100 ; DDRD = 0b11111011 ; /* clear timer counter */ timcnt = 0 ; /* clear state */ state = 0 ; /* clear flag */ eflag = OFF ; /* impress start condition */ send_pwr( 0x00 ); send_con( 0x01 ); send_dat( 0x00 ); /* initialize timer1 */ { /* select CTC , (10MHz / 8) => 1,250kHz */ TCCR1B = (1 << WGM12) | (1 << CS11) ; /* clear timer/counter */ TCNT1 = 0 ; OCR1A = 1249 ; OCR1B = 2500 ; /* Enable Compare match interruption */ TIMSK = (1 << OCIE1A) ; } /* enable external interrupt */ { /* select falling edge */ MCUCR = (1 << ISC01) ; /* Enable external interruption */ GIMSK = (1 << INT0) ; } } void send_pwr(UBYTE x) { send_pcd(PWR_BIT,x); } void send_con(UBYTE x) { send_pcd(CON_BIT,x); } void send_dat(UBYTE x) { send_pcd(D_BIT,x); } void send_pcd(UBYTE kind,UBYTE x) { /* impress data */ PORTB = x ; /* trigger H */ if ( kind == PWR_BIT ) { PORTD |= (1 << PWR_BIT) ; } if ( kind == CON_BIT ) { PORTD |= (1 << CON_BIT) ; } if ( kind == D_BIT ) { PORTD |= (1 << D_BIT) ; } /* dummy delay */ x >>= 1 ; /* trigger L */ PORTD &= 0x0f ; } void delay_ms(UBYTE x) { volatile ULONG last ; last = timcnt + x ; while ( timcnt < last ) ; } /* INT0 interrupt */ ISR(INT0_vect) { eflag = ON ; } /* TIMER1 interrupt */ ISR(TIMER1_COMPA_vect) { timcnt++ ; if ( timcnt & 1 ) { PORTD &= 0xfe ; } else { PORTD |= 0x01 ; } }
目次

inserted by FC2 system