目次

IICバスEEPROM処理

 無線サークルの知人から、表面実装のEEPROMを貰いました。

 変換基板に半田付けして、2個使えるようにしています。

 8ピンICソケットを並べて、それらにEEPROM基板を挿入。



 IICバスを操作するには、PC5、PC4を使います。
 PC5、PC4をSCL、SDAとして使います。



 IICバスは4ピンで、IICバスデバイスと接続できるので
 次のケーブルを用意しました。



 ケーブルは、色でどの信号と接続しているのか
 わかるようにしています。

 IICバスデバイスとの接続は、以下。



 IICバスを扱うライブラリは、Wire.hがあります。
 インクルードは、次の記述でOK。

#include <Wire.h>

 IICバスを利用するには、setup()の中に
 開始を宣言するコードを入れます。

  /* enable IIC bus */
  Wire.begin();

 IICバスは、バスに最大8デバイスを接続できます。

 8デバイスを区別するために、各デバイスには
 A0からA2の3ピンを用意して、IICバスから見て
 何番になっているのかを、物理的に固定。

 EEPROMを2個使っているので、番号0、1を
 与えるため、次のように半田付けしています。



 各EEPROMにアクセスするためには、2つの
 パラメータが必要になります。

 ID、アドレスで、EEPROMでは次のように
 指定が必要。



 Control Code がIDで、0x50。
 Chip Select Bitsは、バス上のアドレスで0x0から0x07。

 合体させた0x50、0x51が各々のEEPROMのIICバス上
 のアドレスになります。

 次のようにアドレスが振られます。



 ハードウエアの仕様が決まりました。

 EEPROMにバイトごとにデータをライトする
 バイトごとにデータを読み込むを考えます。

 EEPROMのアクセス方法をタイミングチャートで
 確認しておきます。



 ライトでは、次のシーケンスを利用することで
 指定アドレスに1バイトが格納されています。
  1. START conditionに設定
  2. Control Byte 転送
  3. 上位アドレス転送
  4. 下位アドレス転送
  5. 1バイト転送
  6. STOP conditionに設定
 今回使うEEPROMは、8kバイトになるので  2個使うと、16kバイトまでライト可能。  ライブラリを利用して、1バイトライトする  関数は、次のように定義できます。 void put_eeprom(word xadr,byte xdat) { byte adh ; byte adl ; byte xx ; boolean bflag ; /* copy */ xx = xdat ; /* set block number */ bflag = OFF ; if ( xadr > 0x1fff ) { bflag = ON ; } /* separate address */ adl = xadr & 0xff ; adh = (xadr >> 8) & 0x1f ; /* write 1 byte */ if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); } 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); }  8kバイトごとに、EEPROMデバイスが変わるので  与えられたアドレスから、どのEEPROMデバイスに  なっているのか判定します。  Wire.beginTransmissionで、START condition設定と  Control Byte転送が実行されています。  STOP condition設定は、Wire.endTransmission()を  使ってやればOK。  リードは、次のシーケンスを利用します。
  1. START conditionに設定
  2. Control Byte 転送
  3. 上位アドレス転送
  4. 下位アドレス転送
  5. START conditionに設定
  6. Control Byte 転送
  7. 1バイトをEEPROMから転送
  8. STOP conditionに設定
 リードの場合は、シーケンシャル操作ができると  データシートに書かれています。  タイミングチャートは、以下。  シーケンシャルリードを担当する関数が用意されて  いるので、これを使って1バイトをリードする関数  を定義。 byte get_eeprom(word xadr) { byte adh ; byte adl ; byte result ; boolean bflag ; /* default */ result = 0 ; /* set block number */ bflag = OFF ; if ( xadr > 0x1fff ) { bflag = ON ; } /* separate address */ adl = xadr & 0xff ; adh = (xadr >> 8) & 0x1f ; /* impress address */ if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); } else { Wire.beginTransmission(ROM_ADRS) ; } Wire.write(adh); /* upper address */ Wire.write(adl); /* lower address */ Wire.endTransmission(); /* read 1 byte */ if ( bflag ) { Wire.requestFrom(ROM_ADRS1,1); } else { Wire.requestFrom(ROM_ADRS ,1); } if ( Wire.available() ) { result = Wire.read() ; } return result ; }  1バイトのリード、ライトができるようになったので  ArduinoにEEPROMを2個接続して、端末でアクセスする  スケッチを定義します。  コマンドインタプリタを入れて、使えるコマンドを  次のように決めました。  コマンド'?'は、使えるコマンドのリストを  表示します。  コマンド'A'、'L'は、ほぼ同じ動作をします。  EEPROM内のデータを16進2桁で表示しますが  コマンド'L'は、0xffをスキップ。  コマンド'S'は、システム領域と定めたエリアの  6バイトを16進2桁で表示。  コマンド'D'は、システム領域の6バイトにデータ  を書き込みます。  TeraTermで操作すると、次のようになります。  コマンド'?'の処理  コマンド'S'の処理  コマンド'D'の処理  コマンド'A'の処理   0xffをスキップしないで、表示しています。  コマンド'L'の処理   0xffをスキップして、表示しています。  スケッチの内容は、以下。 /* romtstz.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 ROM_ADRS1 0x51 #define LED_BIT 5 #define SYS_ADRS 0x3ff8 boolean uflag ; boolean cflag ; /* variables */ char sbuf[16] ; 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 put_eeprom(word xadr,byte xdat); byte get_eeprom(word xadr); void loadEEPROM(); char getASC(byte x); byte getVal(char x); void fillEEPROM(); void showSYSYDT(); void dummySet(); void setup() { Serial.begin(115200); rs_puts("Hello !"); crlf(); crlf(); show_help(); /* port value */ PORTB = 0x00 ; PORTC = 0x00 ; PORTD = 0x00 ; /* port direction */ DDRB = 0xff ; DDRC = 0xf0 ; DDRD = 0xfe ; /* flags */ uflag = OFF ; cflag = 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 == 'A' ) { cflag = OFF ; loadEEPROM(); } /* load data from EEPROM */ if ( cmd == 'L' ) { cflag = ON ; loadEEPROM(); } /* fill data EEPROM */ if ( cmd == 'F' ) { fillEEPROM(); } /* show system date time */ if ( cmd == 'S' ) { showSYSYDT(); } /* dummySet */ if ( cmd == 'D' ) { dummySet(); } /* new line */ crlf() ; } } void show_help() { rs_puts("? help") ; crlf(); rs_puts("F fill FF") ; crlf(); rs_puts("A load data") ; crlf(); rs_puts("L load data") ; crlf(); rs_puts("S system status"); crlf(); rs_puts("D dummy set") ; 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 ; boolean bflag ; /* copy */ xx = xdat ; /* set block number */ bflag = OFF ; if ( xadr > 0x1fff ) { bflag = ON ; } /* separate address */ adl = xadr & 0xff ; adh = (xadr >> 8) & 0x1f ; /* write 1 byte */ if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); } 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); } byte get_eeprom(word xadr) { byte adh ; byte adl ; byte result ; boolean bflag ; /* default */ result = 0 ; /* set block number */ bflag = OFF ; if ( xadr > 0x1fff ) { bflag = ON ; } /* separate address */ adl = xadr & 0xff ; adh = (xadr >> 8) & 0x1f ; /* impress address */ if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); } else { Wire.beginTransmission(ROM_ADRS) ; } Wire.write(adh); /* upper address */ Wire.write(adl); /* lower address */ Wire.endTransmission(); /* read 1 byte */ if ( bflag ) { Wire.requestFrom(ROM_ADRS1,1); } else { Wire.requestFrom(ROM_ADRS ,1); } if ( Wire.available() ) { result = Wire.read() ; } return result ; } void loadEEPROM() { long i ; byte tmp ; char msg[2] ; for ( i = 0 ; i < 0x4000 ; i++ ) { tmp = get_eeprom( i ) ; /* separate */ *(msg+0) = getASC( (tmp >> 4) & 15 ) ; *(msg+1) = getASC( tmp & 15 ) ; /* judge */ if ( cflag == ON && tmp == 0xff ) { *(msg+0) = ' ' ; *(msg+1) = ' ' ; } /* show */ if ( *(msg + 0) != ' ' ) { rs_putchar( *(msg+0) ) ; rs_putchar( *(msg+1) ) ; rs_putchar( ' ' ); } /* new ling */ if ( (i & 0xf) == 15 ) { crlf(); } /* delay */ delay(1); } } char getASC(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 ; } void fillEEPROM() { word i ; byte tmp ; tmp = 0xff ; for ( i = 0 ; i < SYS_ADRS ; i++ ) { put_eeprom( i , tmp ) ; rs_putchar('.'); if ( (i % 32) == 31 ) { crlf(); } } } void showSYSYDT() { byte msg[6]; byte i ; byte tmp ; char dh ; char dl ; /* get system date and time */ for ( i = 0 ; i < 6 ; i++ ) { *(msg+i) = get_eeprom( SYS_ADRS + i ) ; } /* show date and time */ for ( i = 0 ; i < 6 ; i++ ) { tmp = *(msg+i); /* separate */ dl = tmp & 15 ; tmp >>= 4 ; dh = tmp & 15 ; /* upper */ rs_putchar( getASC( dh ) ); /* lower */ rs_putchar( getASC( dl ) ); /* space */ rs_putchar( ' ' ); /* */ delay(1); } crlf(); } void dummySet() { word xadr ; byte msg[6]; byte dh ; byte dl ; byte j ; byte i ; /* get information */ j = 1 ; for ( i = 0 ; i < 6 ; i++ ) { /* get */ dh = getVal( *(sbuf+j) ) ; dl = getVal( *(sbuf+j+1) ) ; /* */ *(msg+i) = (dh << 4) + dl ; /* update */ j += 2 ; } /* system area entry */ xadr = SYS_ADRS ; /* year month day weekday hh mm */ put_eeprom( xadr , *(msg+0) ); xadr++ ; put_eeprom( xadr , *(msg+1) ); xadr++ ; put_eeprom( xadr , *(msg+2) ); xadr++ ; put_eeprom( xadr , *(msg+3) ); xadr++ ; put_eeprom( xadr , *(msg+4) ); xadr++ ; put_eeprom( xadr , *(msg+5) ); } /* 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 ; } } }  このスケッチを叩き台にして、次の32kバイトの  EEPROM基板をアクセスするスケッチも、作成して  あります。  32kバイトをアクセスするスケッチは以下。 /* romtstm.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 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 ; /* 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 ; } } 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