目次

外部EEPROMアクセス

 Arduinoには、内蔵EEPROMがありますが、256
 バイトから1024バイト程度で、大量の情報を
 保存するのには、向いていません。

 IICバスの8kバイト、32kバイトのEEPROMを
 接続して、大量の情報を保存するための基本
 実験をします。

 利用したEEPROMは、無線サークルの知人から
 貰った表面実装タイプで、DIP化基板に半田
 づけして利用。



 ArduinoのAPIには、IICバスを扱うライブラリが
 用意されているので、ライブラリを使って処理
 することを考えてます。

 1バイトのリード、ライトの関数を定義。

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write 1 byte */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.write(xx ); /* data */
  Wire.endTransmission();
  /* wait 6ms */
  delay(5);
}

byte get_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  byte result ;
  /* default */
  result = BSIZE ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* impress address */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* read 1 byte */
  Wire.requestFrom(ROM_ADRS,1);
  if ( Wire.available() ) { result = Wire.read() ; }

  return result ;
}

 2関数の中で利用しているEEPROMのデバイス
 IDは、ROMX_ADRSで0x50としました。

 IICバスは、ひとつのバスに最大8デバイスまで
 接続できます。デバイスIDに、ハードウエアで
 指定するIICバス上でのアドレスを加えて、各々
 のデバイスを区別していきます。

 今回利用したEEPROMは、24C64でピンアサインは
 次のようになっています。



 E0からE2で、デバイスのバス上のアドレスを決定。

 E0、E1、E2の3ビットは、0Vに接続したので
 EEPROMのアドレスは、0x50になります。

 IICバス上のアドレスは、3ビットですが
 デバイスIDは4ビット。合計7ビットで
 ターゲットEEPROMを指定。




 ArduinoのWireライブラリでは、7ビットを
 扱いますが、8ビットに拡張して与えれば
 各関数の動作は、問題になりません。

 1バイトのライト、リードは、次のタイミング
 チャートを利用して定義しました。



 ライトには、WCピンを0Vに接続していなければ
 ならず、ICソケットを利用して、基板に実装と
 いう場合に、半田付けして対応。

 1バイトのライトでも、32バイト(1ページ)の
 ライトでも、書き込まれるまでに、5msの時間が
 必要とデータシートに記載があります。




 リードは、その時点で与えられていたアドレスを
 利用するモードを使っています。

 アドレスは、デバイスID、IICバス上のアドレスに
 続けて、EEPROM内部のデータのアドレスを設定と
 なるので、関数内のコードは、次の記述になると
 わかります。

  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* impress address */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();

 1バイトのライトとリードの関数を用意したので
 実際に使ってみます。

 コマンドを用意して対応。

 コマンドを決めたなら、インタプリタを定義します。

  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* test transfer */
    if ( cmd == 'S' ) { saveEEPROM(); }
    /* show EEPROM context */
    if ( cmd == 'D' ) { showEEPROM(); }
    /* new line */
    crlf() ;
  }

 コマンド受信をイベント通知フラグuflagのセットで
 確認しておき、受信バッファからコマンドを取得して
 個々の処理に分岐します。

 コマンドは受信割込みを使えばよいので、定番のコード
 にて対応しました。

void serialEvent()
{
  char ch;
  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 個々の関数と手続きを、定義。

 ヘルプ

  ヘルプは、1文字コマンドと機能を説明だけにします。

void show_help()
{
  rs_puts("? help")            ; crlf();
  rs_puts("L load 256 data")   ; crlf();
  rs_puts("S save 256 data")   ; crlf();
  rs_puts("D display 256 date"); crlf();
}

  文字列表示は、自前で定義。

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

 データ取得

  256バイトと固定しているので、関数get_eepromを
  256回利用して、配列に格納します。

void loadEEPROM()
{
  word ii ;

  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    *(zdat+ii) = get_eeprom( ii ) ;
  }
}

  配列をzdatとして、256バイト分確保。

#define BSIZE 256

byte zdat[BSIZE] ;

 データ転送

  関数put_eepromを利用して、1バイトごとのデータを
  生成し、全体で256バイトをEEPROMに格納。

  同じデータを保存しては、正常に動作しているのか
  見分けがつかないので、アドレスにより数値を変動
  させます。

void saveEEPROM()
{
  word ii ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    put_eeprom( (word)ii , 255 - ii ) ;
  }
}

 データ表示

  配列に格納してあるデータを16進数で表示。
  一度EEPROMから配列にデータを取り出して
  あるので、配列の内容表示で対応。

void showEEPROM()
{
  byte tmp ;
  word ii ;
  char msg[2] ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    /* get */
    tmp = *(zdat+ii) ;
    /* lower */
    *(msg+1) = getHex( tmp & 15 ); 
    /* upper */
    *(msg+0) = getHex( (tmp >> 4) & 15 );
    /* impress */
    rs_putchar( *(msg+0) );
    rs_putchar( *(msg+1) );
    rs_putchar( ' ' );
    /* new line */
    if ( (ii & 15) == 15 ) { crlf(); }
  }
}

  数値を16進数の数字に変えるのは、関数を定義して
  対応すればよいはず。

char getHex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }
  
  return result ;
}

 必要な部品が揃ったので、スケッチにまとめます。

#include <Wire.h>

#define OFF 0
#define ON  OFF+1

#define BSIZE 256

#define ROM_ADRS  0x50

#define LED_BIT 5

boolean uflag ;

/* variables */
char sbuf[8] ;
byte sindex ;

byte cmd ;
byte zdat[BSIZE] ;

void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
byte get_eeprom(word xadr);
void loadEEPROM();
void saveEEPROM();
void showEEPROM();
char getHex(byte x);

void setup()
{
  Serial.begin(9600);
  rs_puts("Hello !");
  crlf();
  /* port value */
  PORTB = 0x00 ;
  PORTC = 0x00 ;
  PORTD = 0x00 ;
  /* port direction */
  DDRB = 0xff ;
  DDRC = 0xf0 ;
  DDRD = 0xfe ;
  /* flags */
  uflag = OFF ; 
  /* enable IIC bus */
  Wire.begin();
  /* get 256 bytes from EEPROM */
  loadEEPROM();
}

void loop()
{
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* test transfer */
    if ( cmd == 'S' ) { saveEEPROM(); }
    /* show EEPROM context */
    if ( cmd == 'D' ) { showEEPROM(); }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")            ; crlf();
  rs_puts("L load 256 data")   ; crlf();
  rs_puts("S save 256 data")   ; crlf();
  rs_puts("D display 256 date"); crlf();
}

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write 1 byte */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.write(xx ); /* data */
  Wire.endTransmission();
  /* wait 6ms */
  delay(5);
}

byte get_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  byte result ;
  /* default */
  result = BSIZE ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* impress address */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* read 1 byte */
  Wire.requestFrom(ROM_ADRS,1);
  if ( Wire.available() ) { result = Wire.read() ; }
   
  return result ;
}

void loadEEPROM()
{
  word ii ;

  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    *(zdat+ii) = get_eeprom( ii ) ;
  }
}

void saveEEPROM()
{
  word ii ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    put_eeprom( (word)ii , 255 - ii ) ;
  }
}

void showEEPROM()
{
  byte tmp ;
  word ii ;
  char msg[2] ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    /* get */
    tmp = *(zdat+ii) ;
    /* lower */
    *(msg+1) = getHex( tmp & 15 ); 
    /* upper */
    *(msg+0) = getHex( (tmp >> 4) & 15 );
    /* impress */
    rs_putchar( *(msg+0) );
    rs_putchar( *(msg+1) );
    rs_putchar( ' ' );
    /* new line */
    if ( (ii & 15) == 15 ) { crlf(); }
  }
}

char getHex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }
  
  return result ;
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 TeraTermを利用して、動作を確認します。

 端末ソフトの起動で、オープニングメッセージを表示。



 ヘルプコマンドのテスト。



 データ転送コマンド実行。



 データ取得コマンド実行。



 データ表示コマンド実行。



 EEPROMへの1バイトライトとEEPROMからの
 1バイトリードにラッパー関数を用意して
 コマンドインタプリタで処理できていると
 わかります。

 ページごとのリード、ライトも可能なので
 リードに限定し、処理するスケッチを作成。

 ページリードの関数は、次のように定義しました。

void get_page_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write entry address */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* get 32 bytes */
  Wire.requestFrom(ROM_ADRS,32);
  /* copy */
  if ( Wire.available() ) {
    for ( adl = 0 ; adl < 32 ; adl++ ) {
      *(ydat+adl) = Wire.read();
    }
  }
  /* show */  
  for ( adl = 0 ; adl < 32 ; adl++ ) {
    adh = *(ydat+adl) ;
    rs_putchar( getHex( (adh >> 4) & 15 ) );
    rs_putchar( getHex( adh & 15 ) );
    rs_putchar(' ');
    if ( (adl % 16) == 15 ) { crlf(); }
  }
}

 コマンドを増やし、ページリード関係の関数が
 使えるようにします。

 増やしたコマンドは、以下。

 スケッチは、次のようにまとめました。

#include <Wire.h>

#define OFF 0
#define ON  OFF+1

#define BSIZE 256

#define ROM_ADRS  0x50

#define LED_BIT 5

boolean uflag ;

/* variables */
char sbuf[4] ;
byte sindex ;

byte cmd ;
byte ydat[32];
byte zdat[BSIZE] ;

void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
void get_page_eeprom(word xadr);
void loadEEPROM();
void saveEEPROM();
void showBuffer();
void generateData();
char getHex(byte x);
byte getVal(char x);

void setup()
{
  Serial.begin(9600);
  rs_puts("Hello !");
  crlf();
  /* port value */
  PORTB = 0x00 ;
  PORTC = 0x00 ;
  PORTD = 0x00 ;
  /* port direction */
  DDRB = 0xff ;
  DDRC = 0xf0 ;
  DDRD = 0xfe ;
  /* flags */
  uflag = OFF ; 
  /* enable IIC bus */
  Wire.begin();
}

void loop()
{
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* show EEPROM context */
    if ( cmd == 'D' ) { showBuffer(); }
    /* get EEPROM with page mode */
    if ( cmd == 'E' ) { showPage(); }
    /* show EEPROM context */
    if ( cmd == 'F' ) { generateData(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* test transfer */
    if ( cmd == 'S' ) { saveEEPROM(); }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")             ; crlf();
  rs_puts("D display buffer")   ; crlf();
  rs_puts("E show page context"); crlf();
  rs_puts("F fill value")       ; crlf();
  rs_puts("L load 256 data")    ; crlf();
  rs_puts("S save 256 data")    ; crlf();
}

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write 1 byte */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.write(xx ); /* data */
  Wire.endTransmission();
  /* wait 5ms */
  delay(5);
}

void get_page_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write entry address */
  Wire.beginTransmission(ROM_ADRS);
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* get 32 bytes */
  Wire.requestFrom(ROM_ADRS,32);
  /* copy */
  if ( Wire.available() ) {
    for ( adl = 0 ; adl < 32 ; adl++ ) {
      *(ydat+adl) = Wire.read();
    }
  }
  /* show */  
  for ( adl = 0 ; adl < 32 ; adl++ ) {
    adh = *(ydat+adl) ;
    rs_putchar( getHex( (adh >> 4) & 15 ) );
    rs_putchar( getHex( adh & 15 ) );
    rs_putchar(' ');
    if ( (adl % 16) == 15 ) { crlf(); }
  }
}

void loadEEPROM()
{
  byte i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 8 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
    for ( j = 0 ; j < 32 ; j++ ) {
      *(zdat + j + xad) = *(ydat + j) ;
    }
  }
}

void saveEEPROM()
{
  word ii ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    put_eeprom( ii , *(zdat+ii) ) ;
  }
}

void showBuffer()
{
  byte tmp ;
  word ii ;
  char msg[2] ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    /* get */
    tmp = *(zdat+ii) ;
    /* lower */
    *(msg+1) = getHex( tmp & 15 ); 
    /* upper */
    *(msg+0) = getHex( (tmp >> 4) & 15 );
    /* impress */
    rs_putchar( *(msg+0) );
    rs_putchar( *(msg+1) );
    rs_putchar( ' ' );
    /* new line */
    if ( (ii & 15) == 15 ) { crlf(); }
  }
}

void generateData()
{
  byte xx ;
  /* get data from receive buffer */
  xx = getVal( *(sbuf+1) ) ;
  xx <<= 4 ;
  xx += getVal( *(sbuf+2) ) ;
  /* store */
  for ( word i = 0 ; i < BSIZE ; i++ ) { *(zdat+i) = xx ; }
}

void showPage()
{
  word xx ;
  /* get page number */
  xx = getVal( *(sbuf+1) );
  xx <<= 5 ;
  /* */
  get_page_eeprom( xx );
}

char getHex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }
  
  return result ;
}

byte getVal(char x)
{
  byte result ;
  /* default */
  result = 0 ;
  /* judge */
  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 ;
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 端末操作で、次のようになりました。

 コマンドを確認。



 'D'コマンドで、現在のバッファの内容を表示。



 'L'コマンドで、EEPROMの256バイトの内容を確認。



 バッファにデータを保存後、EEPROMに256バイトを
 格納し、'L'コマンドで、EEPROMの256バイトの内容
 を確認。



 問題なく動作していることがわかります。

 'E'コマンドが、正しく動いているのかを確認します。

 'L'コマンドで、EEPROMの先頭256バイトの内容を確認。



 'E'コマンドで、32バイトごとにデータを取得して
 表示されていることを確認できました。



 1個のEEPROMをアクセスできるようになったので
 2個のEEPROM(2個で、16kバイト)をアクセス
 できるように半田付けしました。



 スケッチは、次のように定義しました。

#include <Wire.h>

#define OFF 0
#define ON  OFF+1

#define BSIZE 256

#define ROM_ADRS   0x50
#define ROM_ADRSX  0x51

#define LED_BIT 5

boolean uflag ;
boolean cflag ;

/* variables */
char sbuf[4] ;
byte sindex ;

byte cmd ;
byte ydat[32];
byte zdat[BSIZE] ;

void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
void get_page_eeprom(word xadr);
void loadEEPROM();
void saveEEPROM();
void putPage();
void showAll();
void showBuffer();
void showPage();
void generateData();
char getHex(byte x);
byte getVal(char x);

void setup()
{
  Serial.begin(9600);
  rs_puts("Hello !");
  crlf();
  show_help();
  /* port value */
  PORTB = 0x00 ;
  PORTC = 0x00 ;
  PORTD = 0x00 ;
  /* port direction */
  DDRB = 0xff ;
  DDRC = 0xf0 ;
  DDRD = 0xfe ;
  /* flags */
  uflag = OFF ; 
  /* enable IIC bus */
  Wire.begin();
}

void loop()
{
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* show all area */
    if ( cmd == 'A' ) { showAll(); }
    /* show EEPROM context */
    if ( cmd == 'D' ) { showBuffer(); }
    /* get EEPROM with page mode */
    if ( cmd == 'E' ) { showPage(); }
    /* show EEPROM context */
    if ( cmd == 'F' ) { generateData(); }
    /* load data from EEPROM */
    if ( cmd == 'l' ) { 
      cflag = OFF ;
      loadEEPROM(); 
    }
    if ( cmd == 'L' ) { 
      cflag = ON ;
      loadEEPROM(); 
    }
    /* test transfer */
    if ( cmd == 's' ) { 
      cflag = OFF ;
      saveEEPROM(); 
    }
    if ( cmd == 'S' ) {
      cflag = ON ;
      saveEEPROM();
    }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")                 ; crlf();
  rs_puts("A show whole area")      ; crlf();
  rs_puts("D display buffer")       ; crlf();
  rs_puts("E show page context")    ; crlf();
  rs_puts("F fill value")           ; crlf();
  rs_puts("l load 256 data(lower)") ; crlf();
  rs_puts("L load 256 data(upper)") ; crlf();
  rs_puts("s save 256 data(lower)") ; crlf();
  rs_puts("S save 256 data(upper)") ; crlf();
}

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write 1 byte */
  if ( cflag ) { Wire.beginTransmission(ROM_ADRSX); }
  else         { Wire.beginTransmission(ROM_ADRS ); }
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.write(xx ); /* data */
  Wire.endTransmission();
  /* wait 5ms */
  delay(5);
}

void get_page_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write entry address */
  if ( cflag ) { Wire.beginTransmission(ROM_ADRSX); }
  else         { Wire.beginTransmission(ROM_ADRS ); }
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* get 32 bytes */
  if ( cflag ) { Wire.requestFrom(ROM_ADRSX,32); }
  else         { Wire.requestFrom(ROM_ADRS ,32); }
  /* copy */
  if ( Wire.available() ) {
    for ( adl = 0 ; adl < 32 ; adl++ ) { *(ydat+adl) = Wire.read(); }
  }
  /* show */  
  for ( adl = 0 ; adl < 32 ; adl++ ) {
    adh = *(ydat+adl) ;
    rs_putchar( getHex( (adh >> 4) & 15 ) );
    rs_putchar( getHex( adh & 15 ) );
    rs_putchar(' ');
    if ( (adl % 16) == 15 ) { crlf(); }
  }
}

void loadEEPROM()
{
  byte i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 8 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
    /* store data to buffer */
    for ( j = 0 ; j < 32 ; j++ ) { *(zdat + j + xad) = *(ydat + j) ; }
  }
}

void saveEEPROM()
{
  word ii ;
  rs_puts("Start !");
  crlf();
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    put_eeprom( ii , *(zdat+ii) ) ;
    rs_putchar('.');
    if ( (ii & 15) == 15 ) { crlf(); }
  }
  rs_puts("Complete !");
  crlf();
}

void putPage()
{
  word i ;
  word xad ;
  /* EEPROM contexnt */
  for ( i = 0 ; i < 256 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

void showAll()
{
  byte i ;
  /* loop */
  for ( i = 0 ; i < 2 ; i++ ) {
    if ( i ) { rs_puts("ROM_1"); cflag = ON  ; }
    else     { rs_puts("ROM_0"); cflag = OFF ; }
    crlf();
    putPage();
  }
}

void showBuffer()
{
  byte tmp ;
  word ii ;
  char msg[2] ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    /* get */
    tmp = *(zdat+ii) ;
    /* lower */
    *(msg+1) = getHex( tmp & 15 ); 
    /* upper */
    *(msg+0) = getHex( (tmp >> 4) & 15 );
    /* impress */
    rs_putchar( *(msg+0) );
    rs_putchar( *(msg+1) );
    rs_putchar( ' ' );
    /* new line */
    if ( (ii & 15) == 15 ) { crlf(); }
  }
}

void generateData()
{
  byte xx ;
  /* get data from receive buffer */
  xx = getVal( *(sbuf+1) ) ;
  xx <<= 4 ;
  xx += getVal( *(sbuf+2) ) ;
  /* store */
  for ( word i = 0 ; i < BSIZE ; i++ ) { *(zdat+i) = xx ; }
}

void showPage()
{
  word xx ;
  /* get page number */
  xx = getVal( *(sbuf+1) );
  xx <<= 5 ;
  /* */
  get_page_eeprom( xx );
}

char getHex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }
  
  return result ;
}

byte getVal(char x)
{
  byte result ;
  /* default */
  result = 0 ;
  /* judge */
  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 ;
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 これで、動作することがわかったので、次に4個の
 EEPROMを使うための基板を半田付けしました。



 スケッチは、以下。

#include <Wire.h>

#define OFF 0
#define ON  OFF+1

#define BSIZE 256

#define ROM_ADRS   0x50
#define ROM_ADRS1  0x51
#define ROM_ADRS2  0x52
#define ROM_ADRS3  0x53

#define LED_BIT 5

boolean uflag ;

/* variables */
char sbuf[4] ;
byte sindex ;

byte cmd ;
byte bnum ;
byte ydat[32];
byte zdat[BSIZE] ;

void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
void get_page_eeprom(word xadr);
void loadEEPROM();
void saveEEPROM();
void putPage();
void getBlockNumber();
void showAll();
void showBuffer();
void generateData();
char getHex(byte x);
byte getVal(char x);

void setup()
{
  Serial.begin(9600);
  rs_puts("Hello !");
  crlf();
  show_help();
  /* port value */
  PORTB = 0x00 ;
  PORTC = 0x00 ;
  PORTD = 0x00 ;
  /* port direction */
  DDRB = 0xff ;
  DDRC = 0xf0 ;
  DDRD = 0xfe ;
  /* flags */
  uflag = OFF ;
  /* */
  bnum = 0 ;
  /* enable IIC bus */
  Wire.begin();
}

void loop()
{
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* show all area */
    if ( cmd == 'A' ) { showAll(); }
    /* set block */
    if ( cmd == 'B' ) { getBlockNumber(); }
    /* show block number */
    if ( cmd == 'b' ) { rs_putchar( bnum + '0' ); crlf(); }
    /* show EEPROM context */
    if ( cmd == 'D' ) { showBuffer(); }
    /* show EEPROM context */
    if ( cmd == 'F' ) { generateData(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* test transfer */
    if ( cmd == 'S' ) { saveEEPROM(); }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")             ; crlf();
  rs_puts("A show whole area")  ; crlf();
  rs_puts("B put block number") ; crlf();
  rs_puts("b get block number") ; crlf();
  rs_puts("D display buffer")   ; crlf();
  rs_puts("F fill value")       ; crlf();
  rs_puts("L load 256 data")    ; crlf();
  rs_puts("S save 256 data")    ; crlf();
}

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  /* copy */
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write 1 byte */
  switch ( bnum ) {
    case 1  : Wire.beginTransmission(ROM_ADRS1); break;
    case 2  : Wire.beginTransmission(ROM_ADRS2); break;
    case 3  : Wire.beginTransmission(ROM_ADRS3); break;
    default : Wire.beginTransmission(ROM_ADRS ); break;
  }
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.write(xx ); /* data */
  Wire.endTransmission();
  /* wait 5ms */
  delay(5);
}

void get_page_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0x1f ;
  /* write entry address */
  switch ( bnum ) {
    case 1  : Wire.beginTransmission(ROM_ADRS1); break;
    case 2  : Wire.beginTransmission(ROM_ADRS2); break;
    case 3  : Wire.beginTransmission(ROM_ADRS3); break;
    default : Wire.beginTransmission(ROM_ADRS ); break;
  }
  Wire.write(adh); /* upper address */
  Wire.write(adl); /* lower address */
  Wire.endTransmission();
  /* get 32 bytes */
  switch ( bnum ) {
    case 1  : Wire.requestFrom(ROM_ADRS1,32); break;
    case 2  : Wire.requestFrom(ROM_ADRS2,32); break;
    case 3  : Wire.requestFrom(ROM_ADRS3,32); break;
    default : Wire.requestFrom(ROM_ADRS ,32); break;
  }
  /* copy */
  if ( Wire.available() ) {
    for ( adl = 0 ; adl < 32 ; adl++ ) { *(ydat+adl) = Wire.read(); }
  }
  /* show */  
  for ( adl = 0 ; adl < 32 ; adl++ ) {
    adh = *(ydat+adl) ;
    rs_putchar( getHex( (adh >> 4) & 15 ) );
    rs_putchar( getHex( adh & 15 ) );
    rs_putchar(' ');
    if ( (adl % 16) == 15 ) { crlf(); }
  }
}

void loadEEPROM()
{
  byte i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 8 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
    /* store data to buffer */
    for ( j = 0 ; j < 32 ; j++ ) { *(zdat + j + xad) = *(ydat + j) ; }
  }
}

void saveEEPROM()
{
  word ii ;
  rs_puts("Start !");
  crlf();
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    put_eeprom( ii , *(zdat+ii) ) ;
    rs_putchar('.');
    if ( (ii & 15) == 15 ) { crlf(); }
  }
  rs_puts("Complete !");
  crlf();
}

void putPage()
{
  word i ;
  word xad ;
  /* EEPROM contexnt */
  for ( i = 0 ; i < 256 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

void getBlockNumber()
{
  /* get block number */
  bnum = getVal( *(sbuf+1) ) ;
  /* judge */
  if ( bnum > 3 ) { bnum = 0 ; }
  /* show block number */
  rs_putchar( bnum + '0' );
  /* new line */
  crlf();
}

void showAll()
{
  byte i;
  /* show */
  for ( i = 0 ; i < 4 ; i++ ) {
    /* block number */
    if ( i == 0 ) { rs_puts("ROM_0"); }
    if ( i == 1 ) { rs_puts("ROM_1"); }
    if ( i == 2 ) { rs_puts("ROM_2"); }
    if ( i == 3 ) { rs_puts("ROM_3"); }
    /* new line */
    crlf();
    /* update block number */
    bnum = i ;
    /* show */
    putPage();
  }
  /* default */
  bnum = 0 ;
}

void showBuffer()
{
  byte tmp ;
  word ii ;
  char msg[2] ;
  for ( ii = 0 ; ii < BSIZE ; ii++ ) {
    /* get */
    tmp = *(zdat+ii) ;
    /* lower */
    *(msg+1) = getHex( tmp & 15 ); 
    /* upper */
    *(msg+0) = getHex( (tmp >> 4) & 15 );
    /* impress */
    rs_putchar( *(msg+0) );
    rs_putchar( *(msg+1) );
    rs_putchar( ' ' );
    /* new line */
    if ( (ii & 15) == 15 ) { crlf(); }
  }
}

void generateData()
{
  byte xx ;
  word i  ;
  /* get data from receive buffer */
  xx = getVal( *(sbuf+1) ) ;
  xx <<= 4 ;
  xx += getVal( *(sbuf+2) ) ;
  /* store */
  for ( i = 0 ; i < BSIZE ; i++ ) { *(zdat+i) = xx ; }
}

char getHex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }
  
  return result ;
}

byte getVal(char x)
{
  byte result ;
  /* default */
  result = 0 ;
  /* judge */
  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 ;
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}


目次

inserted by FC2 system