素子:SPIのEEPROM

SPIインターフェースのEEPROMについて纏めました

・使用したEEPROM Microchip社 25AA1024
 容量 1Mビット
 25LC1024の書き込み回数改良版 仕様は同じ

・SPIの特徴
  -クロック、データ入力、データ出力の3線式だがチップセレクトが必要になるので
   3線+SPIに繋げる部品の数 のピンを食ってしまう
  -非常に高速 このEEPROMは20MHzのクロックスピードにも対応できる
   I2Cの速度に満足できないとき採用すると良い
  -通信の仕組みがI2Cに比べとてもシンプル
   そのためSPIインターフェースを実装していないMPUでも自作のルーチンを簡単に書ける
   シンプルすぎるのでプログラムが暴走するとデータを破壊してしまう可能性もあり
   ロジックアナライザーでの解析がI2Cより容易


2009-11-28

SPIインターフェースのEEPROMの情報は非常に少ない。I2Cの例はいくらでも見つかる。SPIは入出力ピンが分かれているためロジックアナライザーで波形を観測するのも容易。I2Cはサンプリング速度が速くないとACKは見えない。何故か秋月電子で1種類も扱っていない。チップセレクトが必要なので接続のために4本MPUの足を使ってしまうのが嫌われた原因だろうか?。チップセレクトのおかげてサブルーチンの造りもちょっとだけ不細工になる。

PICT1067.jpg

価格は$3.14

実験回路図は以下の通り。先ずPIC特有のSPIインターフェースを全く使わずにEEPROMに読み書きしてみます。

spi-eepsch1.PNG
PICのSPIインターフェースを使用しないプログラム
0001  '-------------------------------------------------------------------------------
0002 ' Microchip 25AA1024
0003 '-------------------------------------------------------------------------------
0004 program SPIEEPROM
0005
0006 symbol PORT_OUTPUT = 0
0007 symbol PORT_INPUT = 1
0008
0009 symbol EEPROM_CS_TRIS = TRISB
0010 symbol EEPROM_SO_TRIS = TRISB
0011 symbol EEPROM_SI_TRIS = TRISB
0012 symbol EEPROM_SCK_TRIS = TRISB
0013 symbol EEPROM_CS_PORT = PORTB
0014 symbol EEPROM_SO_PORT = PORTB
0015 symbol EEPROM_SI_PORT = PORTB
0016 symbol EEPROM_SCK_PORT = PORTB
0017 symbol EEPROM_CS_BIT = 5
0018 symbol EEPROM_SI_BIT = 4
0019 symbol EEPROM_SO_BIT = 3
0020 symbol EEPROM_SCK_BIT = 2
0021
0022 '-------------------------------------------------------------------------------
0023 ' SPI write
0024 '-------------------------------------------------------------------------------
0025 sub procedure spi_write_data( dim data as byte )
0026 dim i as byte
0027
0028 for i = 0 to 7
0029 if ((data and 0x80) = 0x80) then
0030 EEPROM_SI_PORT.EEPROM_SI_BIT = 1
0031 else
0032 EEPROM_SI_PORT.EEPROM_SI_BIT = 0
0033 end if
0034 data = data << 1
0035 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 0
0036 Delay_ms(1)
0037 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 1
0038 Delay_ms(1)
0039 next i
0040 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 0
0041 end sub
0042
0043
0044 '-------------------------------------------------------------------------------
0045 ' SPI read
0046 '-------------------------------------------------------------------------------
0047 sub function spi_read_data as byte
0048 dim i as byte
0049
0050 result = 0
0051 for i = 0 to 7
0052 result = result << 1
0053 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 0
0054 Delay_ms(1)
0055 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 1
0056 if EEPROM_SO_PORT.EEPROM_SO_BIT = 1 then
0057 result = result or 0x01
0058 end if
0059 Delay_ms(1)
0060 next i
0061 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 0
0062 end sub
0063
0064
0065 '-------------------------------------------------------------------------------
0066 ' EEPROM WRITE
0067 '-------------------------------------------------------------------------------
0068 sub procedure spi_eeprom_write(
0069 dim addr as longword,
0070 dim data as byte )
0071
0072 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0073
0074 spi_write_data( %00000010 )
0075 Delay_ms(5)
0076 spi_write_data( Higher(addr) )
0077 Delay_ms(5)
0078 spi_write_data( Hi(addr) )
0079 Delay_ms(5)
0080 spi_write_data( Lo(addr) )
0081 Delay_ms(5)
0082 spi_write_data( data )
0083
0084 Delay_ms(1)
0085 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0086 Delay_ms(1)
0087 end sub
0088
0089 '-------------------------------------------------------------------------------
0090 ' EEPROM READ
0091 '-------------------------------------------------------------------------------
0092 sub function spi_eeprom_read( dim addr as longword ) as byte
0093 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0094
0095 spi_write_data( %00000011 )
0096 Delay_ms(5)
0097 spi_write_data( Higher(addr) )
0098 Delay_ms(5)
0099 spi_write_data( Hi(addr) )
0100 Delay_ms(5)
0101 spi_write_data( Lo(addr) )
0102 Delay_ms(5)
0103 result = spi_read_data
0104
0105 Delay_ms(1)
0106 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0107 Delay_ms(1)
0108 end sub
0109
0110
0111 '-------------------------------------------------------------------------------
0112 ' EEPROM WRITE Enable
0113 '-------------------------------------------------------------------------------
0114 sub procedure spi_eeprom_write_enable
0115 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0116
0117 spi_write_data( %00000110 )
0118
0119 Delay_ms(1)
0120 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0121 Delay_ms(1)
0122 end sub
0123
0124
0125 '*******************************************************************************
0126 ' Program main
0127 '*******************************************************************************
0128 main:
0129 dim dat as byte
0130
0131 EEPROM_CS_TRIS.EEPROM_CS_BIT = PORT_OUTPUT
0132 EEPROM_SI_TRIS.EEPROM_SI_BIT = PORT_OUTPUT
0133 EEPROM_SO_TRIS.EEPROM_SO_BIT = PORT_INPUT
0134 EEPROM_SCK_TRIS.EEPROM_SCK_BIT = PORT_OUTPUT
0135
0136 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0137 EEPROM_SCK_PORT.EEPROM_SCK_BIT = 0
0138
0139 Delay_ms(10)
0140 spi_eeprom_write_enable
0141 Delay_ms(5)
0142 spi_eeprom_write( 0x00123456, 0x55 )
0143 Delay_ms(5)
0144 dat = spi_eeprom_read( 0x00123456 )
0145 while true
0146 wend
0147 end.
0148
0149
行番号
解説
36行目 他
Delayが各所に入っていますが全くなくても動きます。これはロジックアナライザーで波形を取ったときに見やすくするための物です。
69行目
アドレスは24ビットですがmikrobasicには24ビットの変数は無いので4バイトのlongwordを使用しています。最高位の1バイトは捨ててます。
76行目
Higher関数はlongwordの上位2バイト目を返します
78行目
Hi関数はlongwordの上位3バイト目を返します
80行目
Lo関数はlongwordの最下位バイトを返します

上のプログラムの波形観測結果

CS:チップセレクト
SCK:クロック これはMPU側が出力しています
SI:MPU(PIC)->EEPROMへの信号です
   データはクロックの立ち上がりでHighかLowかを判断するので
   クロックの立ち下がりで1ビットずつデータを送り込みます
   1バイトのデータは最上位ビットから順に送り出されます。
SO:EEPROM->MPU(PIC)への信号です
   EEPROMはMPUのSCKに同期してデータを出力しています

A:EEPROMに書き込み許可コマンドを送ります。これをやらないと書き込みが出来ません。
B~Fまでがデータの書き込みです
 B:書き込みのコマンド Bin00000010 を送ります
 C~E:アドレスHex123456を指定しています
     1MビットのEEPROMなので実際にはHex123456というアドレスは有りません。
     1FFFFまでです。これ以上大きいアドレスをしていると適当に丸められるようです。
 F:Hex55(bin01010101)を書き込みます
G~Kまでがデータの読み込みです
 G:読み出しのコマンド Bin00000011 を送ります
 H~J:アドレスHex123456を指定しています
 K:MPUが出力するSCKクロックに同期して指定したアドレスのデータがEEPROMから送られてきます

spi-eeprom2.PNG
上記プログラム現物
ファイル ファイルタイプ 添付ファイルの解説
SPIEEPROM_ORG.zip mikroBasic mikroBASIC V7.2ソース&PIC16F877A用HEXファイル

次はPICのSPIインターフェース MSSP を使用した物。

spi-eeprommssp.PNG
PICのSPIインターフェース(MSSP)を使用したプログラム。あえてmikrobasicのSPIライブラリーを使用せずに書いてある。
0001  '-------------------------------------------------------------------------------
0002 ' Microchip 25AA1024 MSSP Version
0003 '-------------------------------------------------------------------------------
0004 program SPIEEPROM
0005
0006 symbol PORT_OUTPUT = 0
0007 symbol PORT_INPUT = 1
0008
0009 symbol EEPROM_CS_TRIS = TRISB
0010 symbol EEPROM_SO_TRIS = TRISC
0011 symbol EEPROM_SI_TRIS = TRISC
0012 symbol EEPROM_SCK_TRIS = TRISC
0013 symbol EEPROM_CS_PORT = PORTB
0014 symbol EEPROM_SO_PORT = PORTC
0015 symbol EEPROM_SI_PORT = PORTC
0016 symbol EEPROM_SCK_PORT = PORTC
0017 symbol EEPROM_CS_BIT = 5
0018 symbol EEPROM_SI_BIT = 5
0019 symbol EEPROM_SO_BIT = 4
0020 symbol EEPROM_SCK_BIT = 3
0021
0022 '-------------------------------------------------------------------------------
0023 ' SPI initializes
0024 '-------------------------------------------------------------------------------
0025 sub procedure Spi_initialize()
0026 SSPSTAT.SMP = 0 ' Input data sampled at middle of data output time
0027 SSPSTAT.CKE = 1
0028 SSPCON2.CKP = 1
0029 SSPCON.SSPEN = 1 ' Enables serial port
0030 SSPCON.SSPM3 = 0 ' SPI Clock FSOC/4
0031 SSPCON.SSPM2 = 0 ' SPI Clock FSOC/4
0032 SSPCON.SSPM1 = 0 ' SPI Clock FSOC/4
0033 SSPCON.SSPM0 = 0 ' SPI Clock FSOC/4
0034 end sub
0035
0036 '-------------------------------------------------------------------------------
0037 ' SPI write
0038 '-------------------------------------------------------------------------------
0039 sub procedure Spi_write_data(dim data as byte )
0040 SSPBUF = data
0041
0042 while PIR1.SSPIF = 0
0043 wend
0044
0045 PIR1.SSPIF = 0
0046 end sub
0047
0048 '-------------------------------------------------------------------------------
0049 ' SPI read
0050 '-------------------------------------------------------------------------------
0051 sub function Spi_read_data as byte
0052 SSPBUF = 0x00 ' dummy write output SCK
0053
0054 while SSPSTAT.BF = 0
0055 wend
0056
0057 PIR1.SSPIF = 0
0058 result = SSPBUF
0059 end sub
0060
0061
0062 '-------------------------------------------------------------------------------
0063 ' EEPROM write
0064 '-------------------------------------------------------------------------------
0065 sub procedure spi_eeprom_write(
0066 dim addr as longword,
0067 dim data as byte )
0068
0069 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0070
0071 Spi_write_data( %00000010 )
0072 Spi_write_data( Higher(addr) )
0073 Spi_write_data( Hi(addr) )
0074 Spi_write_data( Lo(addr) )
0075 Spi_write_data( data )
0076
0077 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0078 end sub
0079
0080
0081 '-------------------------------------------------------------------------------
0082 ' EEPROM read
0083 '-------------------------------------------------------------------------------
0084 sub function spi_eeprom_read( dim addr as longword ) as byte
0085
0086 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0087
0088 Spi_write_data( %00000011 )
0089 Spi_write_data( Higher(addr) )
0090 Spi_write_data( Hi(addr) )
0091 Spi_write_data( Lo(addr) )
0092 result = Spi_read_data
0093
0094 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0095 end sub
0096
0097
0098 '-------------------------------------------------------------------------------
0099 ' EEPROM WRITE Enable
0100 '-------------------------------------------------------------------------------
0101 sub procedure spi_eeprom_write_enable
0102 EEPROM_CS_PORT.EEPROM_CS_BIT = 0
0103 Spi_write_data( %00000110 )
0104 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0105 end sub
0106
0107
0108 '*******************************************************************************
0109 ' Program main
0110 '*******************************************************************************
0111 main:
0112 dim dat as byte
0113
0114 EEPROM_CS_TRIS.EEPROM_CS_BIT = PORT_OUTPUT
0115 EEPROM_SI_TRIS.EEPROM_SI_BIT = PORT_OUTPUT
0116 EEPROM_SO_TRIS.EEPROM_SO_BIT = PORT_INPUT
0117 EEPROM_SCK_TRIS.EEPROM_SCK_BIT = PORT_OUTPUT
0118
0119 EEPROM_CS_PORT.EEPROM_CS_BIT = 1
0120
0121 Spi_initialize
0122
0123 spi_eeprom_write_enable
0124 spi_eeprom_write( 0x0001FFFF, 0x55 )
0125 Delay_ms(4)
0126 dat = spi_eeprom_read( 0x0001FFFF )
0127 while true
0128 wend
0129 end.
0130
0131 '--------- E N D O F P R O G R A M -------------------------------------------
行番号
解説
25行目
SPIの初期化サブルーチン
27、28行目
クロックの立ち上がりでデータを取り込むか、クロックのアイドリングはHighかLowかを決めている。SPIの仕様はゆるいので色々なケースがあり得る。素子のデータシートを見ないとこの設定は出来ない。
30~33行目
SPIのクロックを決めているこれは最高速の設定
39行目
SPIへ1バイト送り出すサブルーチン
42行目
送信完了すると SSPIFが1になる。割り込みを使う事も出来るがEEPROMへの読み書きは何か別の事象に従属して発生するので割り込みを使う必要性は多分低い。
51行目
SPIから1バイト読み込むサブルーチン
52行目
ここはちょっとトリッキー。クロックに同期してデータが送られて来るため書き込みの操作をしている。これによりクロックが送られる。「読む」ために「書く」必要があるのだ。
54行目
受信が完了するとBFが1になる
65行目
EEPROMへの1バイト書き込みサブルーチン。ここでは1バイトだけ書き込んでいるが3バイトのアドレスに続けてデータを連続して送り出せば複数バイト書き込める。詳しくはデータシートに載っているので見て欲しい。
84行目
EEPROMから1バイト読み出し
101行目
EEPROMへ書き込み許可コマンドを送る。SPIの書き込みシーケンスがシンプルすぎて不用意に書き込みが行われたりしないように、このコマンドが必要なのだと思う。書き込み不許可のコマンドもある。
114行目
SPIはTRISの設定が必要。I2Cは入力兼出力なのでTRISの設定が必要無い。
125行目
データシート上は書き込みに必要な時間は6ms。実験の結果4msでOKだった。これより早いと読んでもゼロが返ってくる。1バイト書き込むたびに6ms待たなければいけないという意味ではない。書き込みと読み出しの間に6msが必要なだけ。まとめて100バイト書き込んで6ms待って100バイト読み込むのはOKだ

上のプログラムの波形

PICT1070.jpg

書き込み許可コマンド と 書き込み波形

PICT1071.jpg

4ms待ってからの読み出し波形

おまけ。実験の様子。

PICT1069.jpg

ロジックアナライザーを接続して波形を観測しているところ

PICT1061.jpg

EEPROMはPICkit2でも読み書きが出来る。結線は8ピンのPICとは異なる。PICkit2のREADMEを見ると結線方法が解る。

上記プログラム現物 MSSP版
ファイル ファイルタイプ 添付ファイルの解説
SPIEEPROM_MSSP.zip mikroBasic mikroBASIC V7.2ソース&PIC16F877A用HEXファイル

2013-06-14

arduinoでのサンプル。配線はソースプログラムの先頭を参照

R0017687.jpg

1バイトの書き込みにかかる時間。約13μ秒。但し6msec待たないと正しく読み出せない。

R0017693.jpg
arduinoスケッチサンプル
0001  //---------------------------------------------
0002 // Microchip 25AA1024 sample
0003 //
0004 // EEPROM arduino pin No
0005 // -------- --------------
0006 // 1 CS 10
0007 // 2 SO 12 MISO
0008 // 3 WP 5V
0009 // 4 GND GND
0010 // 5 SI 11 MOSI
0011 // 6 SCK 13 SCK
0012 // 7 HOLD 5V
0013 // 8 VCC 5V
0014 //--------------------------------------------
0015 #define EEPROM_CS 10
0016
0017 #include <SPI.h>
0018
0019 void spi_eeprom_write( byte addrH, byte addrM, byte addrL, byte data )
0020 {
0021 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0022 SPI.transfer( B00000010 ); // eeprom Write Instruction
0023 SPI.transfer( addrH ); // eeprom 24bit address
0024 SPI.transfer( addrM );
0025 SPI.transfer( addrL );
0026 SPI.transfer( data );
0027 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0028 }
0029
0030 byte spi_eeprom_read( byte addrH, byte addrM, byte addrL )
0031 {
0032 byte data;
0033
0034 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0035 SPI.transfer( B00000011 ); // eeprom Read Instruction
0036 SPI.transfer( addrH ); // eeprom 24bit address
0037 SPI.transfer( addrM );
0038 SPI.transfer( addrL );
0039 data = SPI.transfer(0);
0040 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0041
0042 return data;
0043 }
0044
0045 void spi_eeprom_write_enable( void )
0046 {
0047 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0048 SPI.transfer( B00000110 ); // eeprom enable write operation Instruction
0049 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0050 }
0051
0052 void setup()
0053 {
0054 pinMode(EEPROM_CS, OUTPUT);
0055 pinMode(12, INPUT);
0056 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0057 SPI.begin();
0058 Serial.begin(9600);
0059 }
0060
0061 void loop()
0062 {
0063 byte i;
0064 byte j;
0065
0066 for( i= 0 ; i < 10 ; i++ ) {
0067 spi_eeprom_write_enable();
0068 spi_eeprom_write( 0,0,i,i+20);
0069 delay(6);
0070 }
0071 for( i= 0 ; i < 10 ; i++ ) {
0072 j = spi_eeprom_read( 0,0,i);
0073 Serial.println( j, DEC);
0074 }
0075 while(true) {}
0076 }
0077 //--------------------------------- E N D ------------
0078
行番号
解説
39行目
ポイントはここだけ。何か書き込もうとしないと読み出せない

スケッチ実行結果。読み込んだ値はシリアルモニターに出力している

R0017691.jpg
スケッチ現物
ファイル ファイルタイプ 添付ファイルの解説
25AA1024.zip arduino 上のスケッチ現物
EEP25AA1024array.zip arduino 複数バイトまとめて読み書き版。実行結果の画面は以下。上のサンプルとはCSピンの配線が違っているので注意

複数バイトまとめて読み書き版の実行結果

R0017698.jpg

2014-08-10

arduinoスケッチサンプル 25AA256 の例 データは2バイト単位で扱っている
0001  //---------------------------------------------------------------------------------
0002 // Microchip 25AA256 sample
0003 //
0004 // EEPROM arduino pin No
0005 // -------- --------------
0006 // 1 CS Analog 0
0007 // 2 SO digital 12 MISO
0008 // 3 WP 5V
0009 // 4 GND GND
0010 // 5 SI digital 11 MOSI
0011 // 6 SCK digital 13 SCK
0012 // 7 HOLD 5V
0013 // 8 VCC 5V
0014 //------------------- copyleft iizukagiken 2014 all rights reversed ----------------
0015 #define EEPROM_CS A0
0016 #define EEPROM_MAX_ADDR_LENGTH 32768 // (32kbyte=256kbit)
0017 #include <SPI.h>
0018
0019 typedef union {
0020 word word_val;
0021 struct {
0022 byte L;
0023 byte H;
0024 } byte_val;
0025 } type_convert_word_to_byte;
0026
0027 //--------------------------------------------------------------------------------
0028 // 2バイトデータを書き込む
0029 //  引数1はアドレスではなく何ワード目に書き込むかを表すインデックス
0030 //
0031 // word_index: 0,1,2 ....
0032 //--------------------------------------------------------------------------------
0033 void spi_eeprom_write_word( word word_index, word data )
0034 {
0035 type_convert_word_to_byte udata;
0036 type_convert_word_to_byte uaddr;
0037
0038 uaddr.word_val = (word_index << 1);
0039 udata.word_val = data;
0040 spi_eeprom_write_enable();
0041 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0042 SPI.transfer( B00000010 ); // eeprom Write Instruction
0043 SPI.transfer( uaddr.byte_val.H ); // eeprom 16bit address
0044 SPI.transfer( uaddr.byte_val.L );
0045 SPI.transfer( udata.byte_val.L ); // write word data
0046 SPI.transfer( udata.byte_val.H );
0047 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0048 delay(6);
0049 }
0050
0051 //--------------------------------------------------------------------------------
0052 // 引数1のアドレスから1セクタ(64バイト)を引数2のデータで生める
0053 //--------------------------------------------------------------------------------
0054 void spi_eeprom_fill( word sector_number, byte data )
0055 {
0056 type_convert_word_to_byte uaddr;
0057
0058 uaddr.word_val = (sector_number << 6);
0059 spi_eeprom_write_enable();
0060 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0061 SPI.transfer( B00000010 ); // eeprom Write Instruction
0062 SPI.transfer( uaddr.byte_val.H ); // eeprom 16bit address
0063 SPI.transfer( uaddr.byte_val.L );
0064 for( byte i = 0 ; i < 64 ; i++ ) {
0065 SPI.transfer( data );
0066 }
0067 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0068 delay(6);
0069 }
0070
0071 //--------------------------------------------------------------------------------
0072 // 全メモリーを引数2のデータで生める
0073 //--------------------------------------------------------------------------------
0074 void spi_eeprom_fill_all( byte data )
0075 {
0076 for( word sector = 0 ; sector < 512 ; sector++ ) {
0077 spi_eeprom_fill( sector, data );
0078 }
0079 }
0080
0081 //--------------------------------------------------------------------------------
0082 // 指定のアドレスの内容を1バイト読み出す
0083 //--------------------------------------------------------------------------------
0084 byte spi_eeprom_read_byte( word addr )
0085 {
0086 type_convert_word_to_byte uaddr;
0087 byte data;
0088
0089 uaddr.word_val = addr;
0090 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0091 SPI.transfer( B00000011 ); // eeprom Read Instruction
0092 SPI.transfer( uaddr.byte_val.H ); // eeprom 16bit address
0093 SPI.transfer( uaddr.byte_val.L );
0094 data = SPI.transfer(0);
0095 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0096
0097 return data;
0098 }
0099
0100 //--------------------------------------------------------------------------------
0101 // 2バイトデータを読み出す
0102 //  引数はアドレスではなく何ワード目を読み出すかを表すインデックス
0103 //
0104 // word_index: 0,1,2 ....
0105 //--------------------------------------------------------------------------------
0106 word spi_eeprom_read_word( word word_index )
0107 {
0108 type_convert_word_to_byte udata;
0109 word addr;
0110
0111 addr = (word_index << 1);
0112 udata.byte_val.L = spi_eeprom_read_byte( addr );
0113 udata.byte_val.H = spi_eeprom_read_byte( addr + 1 );
0114
0115 return udata.word_val;
0116 }
0117
0118 //--------------------------------------------------------------------------------
0119 // 書き込み許可
0120 //--------------------------------------------------------------------------------
0121 void spi_eeprom_write_enable( void )
0122 {
0123 digitalWrite( EEPROM_CS, LOW ); // eeprom chip select enable
0124 SPI.transfer( B00000110 ); // eeprom enable write operation Instruction
0125 digitalWrite( EEPROM_CS, HIGH ); // eeprom chip select disable
0126 }
0127
0128 //--------------------------------------------------------------------------------
0129 // 指定のインデックス内から引数3と一致する一番小さいインデックスを返す
0130 // 範囲外のデータが返されたら見つからなかったという意味
0131 //--------------------------------------------------------------------------------
0132 word spi_eeprom_find_index( word start_index, word end_index, word fill_data )
0133 {
0134 word offset_index;
0135 word index;
0136 word data;
0137 offset_index = (EEPROM_MAX_ADDR_LENGTH >> 2);
0138
0139 index = offset_index;
0140 while( offset_index > 0 ) { // バイナリサーチアルゴリズム
0141 offset_index >>= 1;
0142 if( index > end_index ) {
0143 index -= offset_index;
0144 } else if( index < start_index ) {
0145 index += offset_index;
0146 } else {
0147 data = spi_eeprom_read_word( index );
0148 if( data == fill_data ) {
0149 index -= offset_index;
0150 } else {
0151 index += offset_index;
0152 }
0153 }
0154 }
0155 if( spi_eeprom_read_word( index ) != fill_data ) {
0156 index++;
0157 }
0158
0159 return index;
0160 }
0161
0162 //--------------------------------------------------------------------------------
0163 // EEPROM初期設定
0164 //--------------------------------------------------------------------------------
0165 void spi_eeprom_init( byte pin_no )
0166 {
0167 pinMode( pin_no, OUTPUT );
0168 digitalWrite( pin_no, HIGH ); // eeprom chip select disable
0169 }
0170
0171 //--------------------------------------------------------------------------------
0172 // arduino setup
0173 //--------------------------------------------------------------------------------
0174 void setup()
0175 {
0176 byte data;
0177 word wdata;
0178 word find_index;
0179
0180 SPI.begin();
0181 spi_eeprom_init( EEPROM_CS );
0182 Serial.begin(115200);
0183
0184 // メモリー内全てを0xFFで埋める これは2~3秒かかる
0185 Serial.println( "fill start" );
0186 spi_eeprom_fill_all( 0xFF );
0187 Serial.println( "fill end" );
0188
0189 // 100ワード目~300ワード目までを2000で埋める
0190 for( word index = 100 ; index <= 300 ; index++ ) {
0191 spi_eeprom_write_word( index, 2000 );
0192 }
0193
0194 // 50ワード目~1000ワード目までの中からデータが書き込まれていない(=値が0xFFFF)先頭インデックスを探す
0195 // 300ワード目まで2000で埋められているので301になる
0196 find_index = spi_eeprom_find_index( 50, 1000, 0xFFFF );
0197 Serial.print( "index=" );
0198 Serial.println( find_index );
0199
0200 while(true) {}
0201 }
0202
0203 //--------------------------------------------------------------------------------
0204 // arduino loop
0205 //--------------------------------------------------------------------------------
0206 void loop()
0207 {
0208 // nothing to do
0209 }
0210 //------------------------------------------------------------- E N D ------------
行番号
解説
解説はコメントを参照。CSピンの配線が回路図と異なっているので注意
スケッチ現物
ファイル ファイルタイプ 添付ファイルの解説
EEP25AA256.zip arduino 上のスケッチ現物