Common Lispの系譜を継ぐuLispをラズパイPico2マイコン上で練習中。前回はI2CバスにSCANをかけ、接続したメモリが接続したつもりのアドレスに「居る」ことを確認できました。今回は実際にメモリにライトしてリードしてみます。リードのところの手順にちょっとテク?いるけれども、どおってことない。ホントか?
※Lispと一緒 投稿順 index はこちら
※実機確認は Raspberry Pi Pico2で行ってます。
※使用させていただいとります uLisp のバージョンは 4.6b (Arm用)です。
24LC64、I2C接続 64kb EEPROM
今回I2Cバスに接続したのは以下のEEPROMです。
MICROCHIP 24LC64 64Kb I2C compatible 2-wire Serial EEPROM
I2Cアドレスは0x50(10進で80)から0x57(10進で87)のうち1か所を指定できるようになっているので、0x50(10進で80)としてあります。Pico2ボードとの回路結線図は前回ご参照くだされ。
64Kビット(8bit x 8K構成)です。I2Cバスなので8ビット単位の出し入れとなり、アドレスは上位5ビット、下位8ビットの合計13ビットを2回にわけて送信です。なおEEPROMであるので、書き込み後、電源を落としても値は保持されます。
シーケンシャルRWなどのモードを使うとまとまった塊で連続したリード、ライトを行えます。今回はランダム・アクセスで1バイトづつ書きこむ/読み出す方法を実験してみたいと思います。
書き込み、読み出し関数の定義
書き込みはWriteを連続すればよいだけなので、SPI使ったWriteとほぼ同様です。I2Cバス上のアドレスを指定、(str 80)の80は先ほど出てきたI2Cバスのアドレス(10進)した後、2回にわけてメモリアドレスを送り、最後にデータ8ビットを送ります。
しかし、読み出しはまずI2Cライトでメモリ・アドレスを書きこんでから、今度は一転I2Cリードを行わないとならない(I2Cリードの頭で2回目のスタートビットが必要)です。SPIのときとはチョイと異なり with-i2cを2回やってます。なおリードのときの(str 80 1)の1はリードで読み込むのは1バイトね、という御印です。メモリ側からはリードの末尾でACKが返ってこないので1バイト読んだら末尾ね、と言っておく必要ありみたいです。
(defun write24LC64 (addr dat) (with-i2c (str 80) (write-byte (logand #xFF (ash addr -8)) str) (write-byte (logand #xFF addr) str) (write-byte (logand #xFF dat) str))) (defun read24LC64 (addr) (with-i2c (str 80) (write-byte (logand #xFF (ash addr -8)) str) (write-byte (logand #xFF addr) str)) (with-i2c (str 80 1) (read-byte str)))
実機実行結果
読み書き出来ているようだね。