

ラズパイからEEPROM(M95M04-DR)をSPIで接続しています。  
Pythonを使用して、EEPROMの読み書きを行おうとしていますが、  
メモリデータの取り出し以前に、レジスタの読み込み、設定も行えません。  
初めての工作で理由がわからず苦戦しています。  
構文誤り、考え方の誤り、修正方法等あれば教えてください。

[code]

    import spidev
    import time
    
    READ = 0x03 # 0000 0011 read
    RDSR = 0x05 # 0000 0101 read status register
    WRSR = 0x01 # 0000 0001 write status register
    
    spi = spidev.SpiDev()
    spi.open(0,0)
    spi.max_speed_hz = 10000000
    spi.mode = 3
    
    #write register
    spi.xfer2([WREN]
    time.sleep(0.1)
    spi.xfer2([WRSR,0x0A])　#とりあえず何かを設定できるか確認
    
    #read register
    res = spi.xfer2([RDSR, RDSR])[1]
    print("res:" + str(res)) 　# 1byte(SRWD/ 0 / 0 / 0 / BP1 / BP0 / WEL / WIP) を想定
    time.sleep(0.1)
    
    #read
    data= spi.xfer2([READ, 0x00200, 0x00])
    print("data" + str(data))
    
[/code]

[code]

    res:255  (たまに 253 となる。なぜ…？)  
    data:[255,255,255] (たまに[255,255,127] となる。なぜ…？)　
    
[/code]


CC BY-SA 4.0
2022-07-27T06:02:04.700
90231
2022-07-27T17:39:37.470
2022-07-27T07:16:17.377
3060
53708
question
python python3 raspberry-pi
RaspberryPi CM4 にて、Pythonを使用し、SPI通信で外部のEEPROMにアクセスしますが、値の読み書きができません。


SPI の通信について誤解があるようです。 `xfer2` の挙動と合わせて理解すると吉。

SPI は

  * マイコンが `CS#=L` にする
  * マイコンが `MOSI` からコマンドを出力する 
    * この間もマイコンは `MISO` を読んでいるが、信号の状態が無意味なので結果を無視する義務がある
  * チップが `MISO` に返事が返す 
    * この間もマイコンは `MOSI` を出力しなければならない
    * チップ側はこの間の `MOSI` を無視する義務がある
  * マイコンが `CS#=H` にして１物理トランザクションの終了

というハードウエアプロトコルです。んで `xfer2` はこの一連の処理を一括で行うものです。

`Read Status` 05h コマンドは上記のごとく

  * `MOSI` に 05h を送る（がマイコンはこの間も `MISO` を読む義務がある）
  * `MISO` に値が 8bit で帰ってくる（がこの間もマイコンは `MOSI` に出力する義務がある）

ので、都合１６ビットの転送を行い、マイコンとしては前半が 05h の送信、後半が status の受信となるわけです。

`xfer2()` は引数としてバイト値のリストを受け取り、結果としてバイト値のリストを返す仕様となっているので

[code]

    result = spi.xfer2([5,何でもよいゴミ値])
    
[/code]

とすることで

  * 都合 16bit の転送が行われる
  * `MOSI` の前半に 05h 後半に何でもよいゴミ値が出力される 
    * チップ側は 05h を受け取った時点で `Read status` と解釈し、ゴミ値は無視する
  * `MISO` の前半 8bit が `result[0]` に、後半 8bit が `result[1]` に得られる
  * すでに書いた通り、マイコンソフトのほうは 
    * `result[0]` は無視しなきゃならない
    * `result[1]` が `Read status` の返事のはず

という動作になります。


CC BY-SA 4.0
2022-07-27T07:08:05.287
90233
2022-07-27T07:08:05.287
8589
90231
answer


お忙しい所、ご回答いただきありがとうございます。  
xfer2の仕組みについて少し理解が深まりました。  
お礼申し上げます。

頂いた内容を元に、ソースを少し変更してみましたが、  
レジスタ設定値を取得した値は 255 のまま変わらずでした。  
マスター側、スレーブ側、または双方で何か別の問題があるのかもしれません。  
引き続き学習を進めたいと思います。。

[code]

    #read register
    res = spi.xfer2([RDSR, 0x00])
    print("res:" + str(res[1]))
    res:255
    
[/code]


CC BY-SA 4.0
2022-07-27T09:54:13.563
90236
2022-07-27T17:39:37.470
2022-07-27T17:39:37.470
51596
53708
90231
answer