ラズベリーパイをROMライターにしてみた(Reader編)

以前買い置きしていたI2CのROM 24C512 が手元にあり、これを使おうと思ったのだけど、データを書き込むのがめんどくさい。そのためにAruduinoとかPICとかで書き込んでも良いのだけど、PCで作ったデータファイルをROMに書き込むとなると、PCでデータ作って、書き込み用のプログラム作って、シリアルでArduinoに送り、Arduino側でシリアルとI2Cのプログラム作って・・・って、あー、もう、めんどくせー! となるので、なんか、良い方法はないかいな? と、考えてたら、
おー!ラズパイがあった!
ラズパイだと、I2Cもいけるし、ファイルも簡単に読み書きできる!
と、いうわけで、ラズベリーパイで24C512 を読み書きするための、ROM Reader/Writer を試してみた。
f:id:manpukukoji:20171027100652j:plain
と、言っても、ハードウェアは、ブレッドボードにROMを置いて、ラズパイとジャンパー線4本でつなぐだけ。
I2Cのプルアップも、なぜか、必要なかった。・・・ラズパイ側でプルアップされているのかな???
あとは、Pythonでチョコチョコッと・・・。
使ったラズパイは、RasPi3で、OSはRaspbian with Pixcelってやつ。 比較的新しい方だと思う。I2Cのバスも”1”になってました。

古いやつだと、I2Cを使うのに、i2c-tools とか、smbus とかのPythonのライブラリをインストールする必要があったようだけど、僕の場合、何もしなくてもすでに入っていたみたい。ラズパイの設定でインターフェースのタブでI2Cを有効にしておけば、それだけで問題なく使えました。
このあたりは、検索するといろいろ詳しく説明されたサイト(I2C表示器が多いけど同じです。)があるので、省略するとして、こちらでは、いきなりROMをつないで読むところからです。
例えば、このあたりのサイトで、丁寧に説明されています。
Raspberry Pi で I2C を使用する準備 – 或る阿呆の記


ROMは、ATMELの24C512 です。ですので、他のROMで同じようにいくわけではないと思います。秋月電子通商のサイトで見ると、300円(http://akizukidenshi.com/catalog/g/gI-00561/)だけど、同様の24LC512って言うのもある。こちらは、価格もほぼ半額(http://akizukidenshi.com/catalog/g/gI-02524/)だし、同じように使えるのではないかと思うのだけど、現物を持っていないので、試しておらず、わからないので、あしからず・・・。
ラズパイとの接続は、以下のようにつないだ。

RaspberryPi        24C512
Pin 01  3V    ---   Pin 8
Pin 03  SDA   ---   Pin 5
Pin 05  SCL   ---   Pin 6
Pin 09  GND   ---   Pin 4

f:id:manpukukoji:20171027074550p:plain

Frizingの図は、電源部分、勘違いしやすいので、V+とGND、間違わないように十分注意してね。 ・・・自己責任でよろしく!
上記以外のROMのピンはそのまま(float)ですが、デバイスアドレスを指定するような場合には、アドレスに応じてプルアップすると良いようです。7ピンは、ライトプロテクトなので、書き込みする場合には、そのままか、GNDに落とします。
接続できたら、ラズパイで確認します。

$ i2cdetect -y 1

と、やると、特にアドレスピンを設定していなければ、50 と表示されるはずです。
表示されなければ、ROMが認識されていないかもしれません。
あとは、以下のPythonプログラムを走らせるとROMが読めると思います。
プログラム中の"bus=smbus.SMBus(1)" のところ、もし、バスが0の場合には、添え字を"(0)"にしてくださいね。
ポイントは、24C512は、アドレスが、2バイトなので、smbusのライブラリでは、本来の使い方では、1バイトしか書けないみたいで、"write_i2c_block_data でデータ部分の最初のデータに2バイト目のアドレスを書くことによって、2バイト分のアドレスを指定しているみたいです。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import smbus
import sys

bus = smbus.SMBus(1)
addr = 0
adr1=0
adr2=0
startaddr = 0
endaddr = 0

def read_ROM():
    l1=[]
    print('%4s : %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X ' %('Adr',0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) )
    print('-'*54)
    for i in range(startaddr/256,endaddr/256+1):       
        for j in range(16):
            for k in range(16):
                bus.write_i2c_block_data(addr,i,[16*j+k])
                l1.append(bus.read_byte(addr))
        
            print('%4X : %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ' %(256*i+16*j,l1[0],l1[1],l1[2],l1[3],l1[4],l1[5],l1[6],l1[7],l1[8],l1[9],l1[10],l1[11],l1[12],l1[13],l1[14],l1[15]) )

            l1=[]

if __name__ == '__main__':
    args = sys.argv
    if len(args) < 4 :
        print('usage: python {} <Device Address(HEX)> <Start Address(HEX)> <End Address(HEX)>'.format(__file__))
        exit(0)
    addr = int(args[1],16)
    startaddr = int(args[2],16)
    endaddr = int(args[3],16)
    
    read_ROM()

使い方は、
このスクリプトのファイル名に続いて、デバイスアドレス(50) 読み込みの開始アドレス 読み込み終了アドレス となります。
例えば、"i2cromread.py" という名前で保存し、デバイスは、0x50、読み込み開始アドレスは、0x200、終了アドレス0x21F とすると、以下のようになります。 ただし、表示は、256バイトごとのブロックで表示されるので、要らない部分も表示されるかと思いますが、そこんとこ、よろしく・・・。

$ python i2cromread.py 50 200 21F

f:id:manpukukoji:20171027090206p:plain
と、言うわけで、Writer編は、次回に・・・。