目次
前
次
ROM emulator
32バイト程度のROMが必要になり、PICで
代用してみました。
5ビット入力、8ビット出力の回路として
使えるようにします。
常に5ビット値を入力し、EEPROMに格納している
8ビット値を出力します。
内部ブロック図は、以下。
回路図は、以下。
ファームウエアの構成を考えます。
- ポートAの5ビットを入力
- 現在の5ビットとひとつ前の5ビットを比較し、同じなら4へ
- 5ビットをアドレスとみなし、EEPROMからデータを引出し、ポートBに出力
- 5ビットの値を更新
- 1にもどる
大まかなコードを書きます。
/* get bit state */
tmp = PORTA & MASK1F ;
/* judge */
if ( tmp != ptmp ) {
PORTB = eeprom_read( tmp ) ;
}
/* update */
ptmp = tmp ;
EEPROMの内容を変更するには、シリアル通信を
利用します。PIC16F84では、通信インタフェース
を持たないので、PIC16F873を利用します。
シリアル通信で使うコマンドを定義します。
EEPROMの内容表示と値設定ができればよいので
コマンドを次のように決めました。
- ? コマンド一覧表示
- E アドレスとデータを指定して、EEPROMに書込み
- e 256バイト分の内容表示
コマンドは、いつ与えられるかわからないので
受信割込みを使い、取りこぼさないようにします。
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 ;
}
目次
前
次