目次

EEPROMハンドリング

 EEPROMをアクセスするスケッチは、新規に開発しました。

 8kバイトのEEPROMを扱うスケッチは、以下。

/*
  romtstx.ino

  PORTB
    PB5 (output) LED
    PB4 (output) --
    PB3 (output) --
    PB2 (output) --
    PB1 (output) --
    PB0 (output) --
 
  PORTC
    PC5 (output) SCL
    PC4 (output) SDA
    PC3 (output) --
    PC2 (output) --
    PC1 (output) --
    PC0 (output) --

*/
#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];

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

void setup()
{
  Serial.begin(115200);
  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(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* fill data EEPROM */
    if ( cmd == 'F' ) { fillEEPROM(); }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")      ; crlf();
  rs_puts("F fill FF")   ; crlf();
  rs_puts("L load 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 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(); }
  }
  /* wait */
  delay(100);
}

void loadEEPROM()
{
  word i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 256 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

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);
}

void fillEEPROM()
{
  word i ;
  for ( i = 0 ; i < 8000 ; i++ ) {
    put_eeprom( i , 0xff ) ;
    rs_putchar('.');
    if ( (i % 32) == 31 ) { 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 ;
    }
  }
}

 使う機能は、EEPROMの8kバイトをすべてリードするか
 8kバイトに16進数で'FF'をライトするかに限定。

 Arduinoスケッチは、データの入出力だけを担当し
 変換やグラフ描画は、OSを持ったPCでと考えました。

 データリードでは、32バイトのバッファを用意して
 一気に32バイトを読み込んでから表示。
 このページリードで、読込時間を短縮しています。

 ページリードを担当する関数は、次のように定義。

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(); }
  }
  /* wait */
  delay(100);
}

 32バイトを1ページとするので、8kバイトは
 8192/32=256となり、256回ページリードすれば
 全部のバイトをリードできます。

 全部のバイトをリードし、表示する関数は以下。

void loadEEPROM()
{
  word i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 256 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

 TeraTermを利用して、8kバイト分のデータを
 リードすると、次のようになります。



 データをすべて吸い上げたなら、次回利用のため
 16進数で'FF'を書き込むコマンドで初期化できる
 ようにしています。

 'FF'で初期化する関数は、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);
}

void fillEEPROM()
{
  word i ;
  for ( i = 0 ; i < 8000 ; i++ ) {
    put_eeprom( i , 0xff ) ;
    rs_putchar('.');
    if ( (i % 32) == 31 ) { crlf(); }
  }
}

 8kバイトのEEPROMでは、2分ごとの計測で
 35時間まで温度を取得できます。

 5日ほどの温度変化を見たいので、EEPROMの
 容量を64kバイトに増やしました。

 使ったEEPROMは、以下。



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

/*
  romtsty.ino

  PORTB
    PB5 (output) LED
    PB4 (output) --
    PB3 (output) --
    PB2 (output) --
    PB1 (output) --
    PB0 (output) --
 
  PORTC
    PC5 (output) SCL
    PC4 (output) SDA
    PC3 (output) --
    PC2 (output) --
    PC1 (output) --
    PC0 (output) --

*/
#include <Wire.h>

#define OFF 0
#define ON  OFF+1

#define ROM_ADRS  0x50

#define LED_BIT 5

boolean uflag ;

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

byte cmd ;
byte ydat[32];

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

void setup()
{
  Serial.begin(115200);
  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(); }
    /* load data from EEPROM */
    if ( cmd == 'L' ) { loadEEPROM(); }
    /* fill data EEPROM */
    if ( cmd == 'F' ) { fillEEPROM(); }
    /* new line */
    crlf() ;
  }
}

void show_help()
{
  rs_puts("? help")     ; crlf();
  rs_puts("F fill FF")  ; crlf();
  rs_puts("L load 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 get_page_eeprom(word xadr)
{
  byte adh ;
  byte adl ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0xff ;
  /* 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(); }
  }
  /* wait */
  delay(100);
}

void loadEEPROM()
{
  word i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 2048 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

void put_eeprom(word xadr,byte xdat)
{
  byte adh ;
  byte adl ;
  byte xx ;
  xx = xdat ;
  /* separate address */
  adl = xadr & 0xff ;
  adh = (xadr >> 8) & 0xff ;
  /* 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 fillEEPROM()
{
  long i ;
  byte tmp ;
  tmp = 0xff ;
  for ( i = 0 ; i < 0xffff ; i++ ) {
    put_eeprom( i , tmp ) ;
    rs_putchar('.');
    if ( (i % 32) == 31 ) { 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 ;
    }
  }
}

 ページリードは、そのままにしたいので
 ページリードを扱う関数だけを最大容量
 を扱えるように変更しています。

 ページリードのため、変更した関数の内容は以下。

void loadEEPROM()
{
  word i ;
  byte j ;
  word xad ;
  for ( i = 0 ; i < 2048 ; i++ ) {
    xad = (i << 5) ;
    get_page_eeprom( xad ) ;
  }
}

 'FF'で初期化する関数も、変更しています。

void fillEEPROM()
{
  long i ;
  byte tmp ;
  tmp = 0xff ;
  for ( i = 0 ; i < 0xffff ; i++ ) {
    put_eeprom( i , tmp ) ;
    rs_putchar('.');
    if ( (i % 32) == 31 ) { crlf(); }
  }
}

 2つのスケッチは、PC内に保存しているので
 場面に応じて、Arduinoにダウンロードして
 使えます。


目次

inserted by FC2 system