LoginSignup
0
0

Raspberry Pi で I²C EEPROM (24LCxxx) の読み書き

Posted at

Pythonのsmbus2ライブラリで24LC512の読み書きができました。 smbusじゃなくてsmbus2なのがミソです。

ハマりポイント

 smbusにある関数では24LCxxxの通信フォーマットと合わないのです。
 write系の関数とread系の関数は完全に分離されていて、それぞれStart ConditionとStop Conditionで閉じているっぽいです。 24LCxxxのデータシートをみると、EEPROMからデータを読み込む際、アドレス上位バイト、アドレス下位バイトをマスターから送信後、Repeated Startを発行してからEEPROMからデータが送られてきます。 この動作に対応する関数がsmbusにはありません。
スクリーンショット 2023-08-15 111341.png
図 : データシートより

解決策

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で一気に実行する感じだと思います(たぶん)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0