Pythonのsmbus2ライブラリで24LC512の読み書きができました。 smbusじゃなくてsmbus2なのがミソです。
ハマりポイント
smbusにある関数では24LCxxxの通信フォーマットと合わないのです。
write系の関数とread系の関数は完全に分離されていて、それぞれStart ConditionとStop Conditionで閉じているっぽいです。 24LCxxxのデータシートをみると、EEPROMからデータを読み込む際、アドレス上位バイト、アドレス下位バイトをマスターから送信後、Repeated Startを発行してからEEPROMからデータが送られてきます。 この動作に対応する関数がsmbusにはありません。
図 : データシートより
解決策
smbusをsmbus2に変更し、i2c_rdwr関数を使用しました。 これ↓はページ書き込み/読み込みを実行するサンプルです。
m24LCxxx.py
from smbus2 import SMBus, i2c_msg
ADDR = 0x50 # A0, A1, A2 -> Low
PAGE_SIZE = 128
xxx = 512 # 24LCxxx
def read_n_bytes(bus, address, n):
# EEPROMからnバイト読み込み
w = i2c_msg.write(ADDR, [address>>8, address&0x00ff]) # [アドレス上位, アドレス下位]
r = i2c_msg.read(ADDR, n)
bus.i2c_rdwr(w, r) # 実行
return list(r)
def write_page(bus, page, data):
# EEPROMにページ書き込み
assert len(data) <= PAGE_SIZE
address = page*PAGE_SIZE
w = i2c_msg.write(ADDR, [address>>8, address&0x00ff, *data])
bus.i2c_rdwr(w)
return
if __name__ == "__main__":
i2c = SMBus(1)
i2c.pec = 1
#write_page(i2c, 0, [0xff]*PAGE_SIZE) # ページ0を0xffで満たす
for i in range(xxx//8*1024//16): # i : 記憶領域全体を16バイトごとに区切った時の先頭アドレス
line = read_n_bytes(i2c, i*16, 16) # 16バイト読み込み
# 16バイトずつ改行して表示
for n in line:
print("{:02X} ".format(n), end="")
print()
i2c.close()
解説
i2c_msg.read / i2c_msg.writeで処理を登録して、bus.i2c_rdwrで一気に実行する感じだと思います(たぶん)。