Arduinoで遊ぼう - シリアルSRAMを使ってメモリを拡張する
Posted by arms22 on 2011年02月01日

(写真 スイッチサイエンス - シリアルSRAMモジュール 23K256)
8bitマイコンのSRAM(以下メモリ)は数100バイト~数Kバイトと非常に少なく、Arduino UNOに搭載されているATmega328だと2Kバイト、MEGAに搭載されているATmega2560で8Kバイトだ。ちょっとしたアプリケーションならこれで十分だけど、インターネットからのストリーミングデータを扱ったり、大量のデータを使って何か計算したり、ディレイやリバーブを作ったりしたい場合ぜんぜん足りない。そんな時はメモリチップを外付けしてメモリを拡張しよう!
23K256はMicrochip社のシリアルメモリチップだ。32Kバイトのメモリ空間にシリアルインターフェース(SPI)経由でアクセスできる。一般的な32Kバイトのメモリは15本のアドレスラインと8本のデータラインを繋ぐ必要があるが、23K256はたった4本の信号(MISO/MOSI/SCK/CS)を繋ぐだけで良い。またEEPROMのようなライトサイクルを必要としないので高速に読み書きでき、スタンバイ時の電流は4uAと非常に少なく、電池でバックアップすれば数週間~数ヶ月はデータを保持できる。
23K256の主な特徴
動作電圧:2.7V~3.6V
メモリサイズ:256Kbit(32K x 8 bit)
インターフェース:SPI
速度:最大20MHz
23K256の動作電圧は2.7V~3.6Vで、5V動作のArduino UNOには直接接続できない。5Vトレラント機能を持つバッファICか抵抗分圧による電圧変換が必要になるだろう。今回、Arduino UNOでも使いやすいようにバッファICを搭載したシリアルSRAMモジュールを作った。少量だがスイッチサイエンスで発売している。
スイッチサイエンス - シリアルSRAMモジュール 23K256
http://www.switch-science.com/products/detail.php?product_id=516
3.3V動作のArduino ProやPro Miniで使う場合はマイクロファンでDIPパッケージの23K256を入手すると良い。
マイクロファン - 23K256-DIP8
http://www.microfan.jp/shop/77_104.html
Arduinoに接続する
1 CS <-- 10番(Arduino)シリアルSRAMモジュールのピン割り当ては23K256と同じ。HOLD端子は使わないので10K~100K抵抗でプルアップしておく。繰り返すが23K256の動作電圧は2.7V~3.6Vだ。間違っても5Vを印加しないように!
2 SO --> 12番(Arduino)
3 未接続
4 Vss <-- GND(Arduino)
5 SI <-- 11番(Arduino)
6 SCK <-- 13番(Arduino)
7 HOLD <-- 100kΩ抵抗でプルアップ
8 Vcc <-- 3.3V(Arduino)
SPISRAMライブラリ
Arduino用にSPI SRAMライブラリを作成した。バイトアクセス、シーケンシャルアクセスに対応。次のURLからライブラリをダウンロードして、Arduinoのライブラリフォルダ(MacOSXの場合"~/Documents/Arduino/libraries"、Windowsの場合"My Documents/Arduino/libraries")にコピーする。
SPI SRAM 23k256 librariy for Arduino
http://code.google.com/p/arms22/downloads/detail?name=SPISRAM-001.zip
サンプルスケッチ
SPI SRAMライブラリはSPIライブラリを使うので、SPIライブラリもインクルードする。メモリの読み込みはread関数、書き込みはwrite関数で行う。若干遅くなるがCの配列のようなアクセスも行える。
#include <SPI.h>
#include <SPISRAM.h>
/*
SRAM Arduino
1 CS 10(CS)
2 SO 12(MISO)
3 - -
4 Vss GND
5 SI 11(MOSI)
6 SCK 13(SCK)
7 HOLD <-- 100k ohm -- 3.3V
8 Vcc 3.3V
*/
SPISRAM myRAM(10); // CS pin
char buffer[128];
void setup()
{
Serial.begin(9600);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
Serial.println("Byte write...");
myRAM.write(0,'H');
myRAM.write(1,'e');
myRAM.write(2,'l');
myRAM.write(3,'l');
myRAM.write(4,'o');
myRAM.write(5,'-');
Serial.println("Byte read...");
Serial.println(myRAM.read(0));
Serial.println(myRAM.read(1));
Serial.println(myRAM.read(2));
Serial.println(myRAM.read(3));
Serial.println(myRAM.read(4));
Serial.println(myRAM.read(5));
Serial.println("\nByte write...");
myRAM.write(0x7FFC,'W');
myRAM.write(0x7FFD,'o');
myRAM.write(0x7FFE,'r');
myRAM.write(0x7FFF,'l');
myRAM.write(0x8000,'d');
myRAM.write(0x8001,'!');
myRAM.write(0x8002,'!');
Serial.println("Byte read...");
Serial.println(myRAM.read(0x7FFC));
Serial.println(myRAM.read(0x7FFD));
Serial.println(myRAM.read(0x7FFE));
Serial.println(myRAM.read(0x7FFF));
Serial.println(myRAM.read(0x8000));
Serial.println(myRAM.read(0x8001));
Serial.println(myRAM.read(0x8002));
Serial.println("\nseq write...");
int addr = 0x7F00;
myRAM.write(addr, (byte*)"Hello world!!", sizeof("Hello world!!"));
Serial.println("seq read...");
myRAM.read(addr, (byte*)buffer, sizeof(buffer));
Serial.println( buffer );
Serial.println("\nByte read at operator[]...");
myRAM[100] = 'H';
myRAM[101] = 'e';
myRAM[102] = 'l';
myRAM[103] = 'l';
myRAM[104] = 'o';
Serial.println( myRAM[100] );
Serial.println( myRAM[101] );
Serial.println( myRAM[102] );
Serial.println( myRAM[103] );
Serial.println( myRAM[104] );
Serial.println("\nRandom read/write...");
for(int i=0;i<100;i++){
int addr = random() & 0x7fff;
byte val = i;
Serial.print( addr, HEX );
Serial.print( " " );
Serial.print( val, HEX );
myRAM[addr] = val;
Serial.print( " " );
Serial.println( myRAM[addr], HEX );
}
}
void loop()
{
}
CQ出版 (2011-01-25)