目次

ROM emulator

 32バイト程度のROMが必要になり、PICで
 代用してみました。

 5ビット入力、8ビット出力の回路として
 使えるようにします。



 常に5ビット値を入力し、EEPROMに格納している
 8ビット値を出力します。

 内部ブロック図は、以下。



 回路図は、以下。



 ファームウエアの構成を考えます。
  1. ポートAの5ビットを入力
  2. 現在の5ビットとひとつ前の5ビットを比較し、同じなら4へ
  3. 5ビットをアドレスとみなし、EEPROMからデータを引出し、ポートBに出力
  4. 5ビットの値を更新
  5. 1にもどる
 大まかなコードを書きます。 /* get bit state */ tmp = PORTA & MASK1F ; /* judge */ if ( tmp != ptmp ) { PORTB = eeprom_read( tmp ) ; } /* update */ ptmp = tmp ;  EEPROMの内容を変更するには、シリアル通信を  利用します。PIC16F84では、通信インタフェース  を持たないので、PIC16F873を利用します。  シリアル通信で使うコマンドを定義します。  EEPROMの内容表示と値設定ができればよいので  コマンドを次のように決めました。  コマンドは、いつ与えられるかわからないので  受信割込みを使い、取りこぼさないようにします。 void interrupt(void) { UBYTE chx ; /* receive interrupt */ if ( PIR1.RCIF == ON ) { /* clear flag */ PIR1.RCIF = OFF ; /* get 1 charactor */ chx = RCREG ; /* store */ *(sbuf+sindex) = chx ; /* increment */ sindex++ ; /* judge */ if ( chx == '\r' ) { sindex = 0 ; uflag = ON ; } } }  PIC16F873Aを利用し、4MHzをシステムクロックに  した場合、ボーレート、内蔵モジュールの設定を  します。 /* initialize UART */ { sindex = 0 ; /* BAUD rate 9600bps */ SPBRG = 25 ; /* TxD */ TXSTA.TXEN = ON ; TXSTA.SYNC = OFF ; TXSTA.BRGH = ON ; /* RxD */ RCSTA.SPEN = ON ; RCSTA.CREN = ON ; /* enable receive interrupt */ PIE1.RCIE = ON ; INTCON.PEIE = ON ; }  A/Dコンバータを内蔵するPICでは、デフォルトで  A/Dコンバータを利用する設定になるので、利用  しないときは、ディセーブルにしておきます。  初期化処理をまとめると以下。 void init_usr(void) { /* disable A/D converter */ ADCON1 = 0x07 ; /* disable comparator */ CMCON = 0x00 ; /* I/O state */ PORTA = 0x00 ; PORTB = 0x00 ; PORTC = 0x01 ; /* I/O directions */ TRISA = 0xff ; /* all inputs */ TRISB = 0x00 ; /* all outputs */ TRISC = 0x80 ; /* initialize UART */ { sindex = 0 ; /* BAUD rate 9600bps */ SPBRG = 25 ; /* TxD */ TXSTA.TXEN = ON ; TXSTA.SYNC = OFF ; TXSTA.BRGH = ON ; /* RxD */ RCSTA.SPEN = ON ; RCSTA.CREN = ON ; /* enable receive interrupt */ PIE1.RCIE = ON ; INTCON.PEIE = ON ; } /* enable general interrupt */ INTCON.GIE = ON ; /* clear flag */ uflag = OFF ; /* disable Flash ROM */ EEADRH = 0 ; EEDATH = 0 ; /* others */ tmp = 0 ; ptmp = 0 ; PORTB = eeprom_read( 0 ) ; }  内蔵EEPROMを使うので、1バイトのリード、ライト  の専用関数を定義しておきます。 UBYTE eeprom_byte_read(UBYTE xadr) { /* set address */ EEADR = xadr ; /* enable read */ EECON1 = (1 << RD) ; /* wait */ while ( EECON1 & (1 << RD) ) ; return EEDATA ; } void eeprom_byte_write(UBYTE xadr,UBYTE xdat) { /* set address */ EEADR = xadr ; /* set data */ EEDATA = xdat ; /* enable write */ EECON1.EEPGD = OFF ; EECON1.WREN = ON ; /* write sequence */ EECON2 = 0x55 ; EECON2 = 0xaa ; EECON1.WR = ON ; /* wait */ while ( EECON1 & (1 << WR) ) ; /* disable */ EECON1.WREN = OFF ; }  まとめます。 typedef unsigned char UBYTE ; typedef unsigned int UWORD ; #define OFF 0 #define ON OFF+1 #define MASK0F 0x0f #define MASK1F 0x1f volatile UBYTE uflag ; volatile char sbuf[8]; volatile UBYTE sindex ; volatile char cmd ; volatile UBYTE tmp ; volatile UBYTE ptmp ; volatile UBYTE eadrx ; volatile UBYTE edatx ; volatile UWORD loopx ; /* function prototype */ void init_usr(void); void rs_putchar(UBYTE x); void rs_puts(UBYTE *ptr); void crlf(void); UBYTE get_hex(char x); void perform_rom(void) ; UBYTE eeprom_byte_read(UBYTE xadr); void eeprom_byte_write(UBYTE xadr,UBYTE xdat); void show_help(void); char get_asc(UBYTE x); /* interrupt handler */ void interrupt(void) { UBYTE chx ; /* receive interrupt */ if ( PIR1.RCIF == ON ) { /* clear flag */ PIR1.RCIF = OFF ; /* get 1 charactor */ chx = RCREG ; /* store */ *(sbuf+sindex) = chx ; /* increment */ sindex++ ; /* judge */ if ( chx == '\r' ) { sindex = 0 ; uflag = ON ; } } } void main(void) { char msg[2] ; /* user initialize */ init_usr(); /* endless loop */ while ( ON ) { /* ROM emulate */ perform_rom() ; /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* new line */ crlf(); /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help() ; } /* set data */ if ( cmd == 'E' ) { /* get address */ eadrx = get_hex( *(sbuf+1) ) ; eadrx <<= 4 ; eadrx |= get_hex( *(sbuf+2) ) ; /* get data */ edatx = get_hex( *(sbuf+3) ) ; edatx <<= 4 ; edatx |= get_hex( *(sbuf+4) ) ; /* store */ eeprom_byte_write(eadrx,edatx); } /* show EEPROM context */ if ( cmd == 'e' ) { for ( loopx = 0 ; loopx < 256 ; loopx++ ) { /* get EEPROM data */ edatx = eeprom_byte_read((UBYTE)loopx); /* convert */ *(msg+0) = get_asc( (edatx >> 4) & MASK0F ); *(msg+1) = get_asc( edatx & MASK0F ); /* show */ rs_putchar(' ') ; rs_putchar(*(msg+0)) ; rs_putchar(*(msg+1)) ; /* judge new line */ if ( (loopx & MASK0F) == 15 ) { crlf() ; } } } } } } /* define function body */ void init_usr(void) { /* disable A/D converter */ ADCON1 = 0x07 ; /* disable comparator */ CMCON = 0x00 ; /* I/O state */ PORTA = 0x00 ; PORTB = 0x00 ; PORTC = 0x01 ; /* I/O directions */ TRISA = 0xff ; /* all inputs */ TRISB = 0x00 ; /* all outputs */ TRISC = 0x80 ; /* initialize UART */ { sindex = 0 ; /* BAUD rate 9600bps */ SPBRG = 25 ; /* TxD */ TXSTA.TXEN = ON ; TXSTA.SYNC = OFF ; TXSTA.BRGH = ON ; /* RxD */ RCSTA.SPEN = ON ; RCSTA.CREN = ON ; /* enable receive interrupt */ PIE1.RCIE = ON ; INTCON.PEIE = ON ; } /* enable general interrupt */ INTCON.GIE = ON ; /* clear flag */ uflag = OFF ; /* */ tmp = 0 ; ptmp = 0 ; PORTB = eeprom_read( 0 ) ; } void rs_putchar(UBYTE x) { /* judge */ while ( !TXSTA.TRMT ) ; /* set data */ TXREG = x ; } void rs_puts(UBYTE *ptr) { while ( *ptr ) { rs_putchar( *ptr ); ptr++ ; } } void crlf(void) { rs_putchar('\r'); rs_putchar('\n'); } UBYTE get_hex(char x) { UBYTE result ; /* default */ result = 0 ; /* convert */ 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 perform_rom(void) { /* get bit state */ tmp = PORTA & MASK1F ; /* judge */ if ( tmp != ptmp ) { PORTB = eeprom_read( tmp ) ; } /* update */ ptmp = tmp ; } UBYTE eeprom_byte_read(UBYTE xadr) { /* set address */ EEADR = xadr ; /* enable read */ EECON1 = (1 << RD) ; /* wait */ while ( EECON1 & (1 << RD) ) ; return EEDATA ; } void eeprom_byte_write(UBYTE xadr,UBYTE xdat) { /* set address */ EEADR = xadr ; /* set data */ EEDATA = xdat ; /* enable write */ EECON1.EEPGD = OFF ; EECON1.WREN = ON ; /* write sequence */ EECON2 = 0x55 ; EECON2 = 0xaa ; EECON1.WR = ON ; /* wait */ while ( EECON1 & (1 << WR) ) ; /* disable */ EECON1.WREN = OFF ; } void show_help(void) { rs_puts("? help"); crlf(); rs_puts("E set data to EEPROM"); crlf(); rs_puts("e show EEPROM context"); crlf(); } char get_asc(UBYTE x) { char result ; /* judge */ if ( x < 10 ) { result = x + '0' ; } else { result = x + 55 ; } return result ; }

目次

inserted by FC2 system