ラズパイとmbedでi2c通信してみました。
ラズパイはI2C Slaveにはなれないようなので、マスターになっています。
mbedがスレーブで受信割り込みで自動で値を受け取るようにしました。
レジスタ指定で、4バイトの送受信が可能です。
使用したものはRaspberry Pi 2 model Bと、mbedLPC1768です。
はいコードです。
ラズパイ側
import smbus addr = 0x1D class I2CMaster(): def __init__(self): self.i2c = smbus.SMBus(1) def writeSomeData(self, addr, reg, data, size): DATA = [size, 1] tmp = [(data>>i*8)&0xFF for i in range(size)] self.i2c.write_i2c_block_data(addr, reg, DATA) self.i2c.write_i2c_block_data(addr, tmp[0], tmp[1::]) def getSlaveRegistarData(self, addr, reg, size): DATA = [size, 2] self.i2c.write_i2c_block_data(addr, reg, DATA) val = self.i2c.read_byte_data(addr, 1) return val def getSlaveData(self, addr, reg, size): val = 0 for i in range(size): val |= self.getSlaveRegistarData(addr, reg*4+i, 1) << i*8 return val i2c = I2CMaster() #レジスタ0に12345(4バイト送信) i2c.writeSomeData(addr, 0, 12345, 4) #レジスタ0の値4バイトを受信 data = i2c.getSlaveData(addr, 0, 4) print(data) #レジスタ1に6543(4バイト送信) i2c.writeSomeData(addr, 1, 6543, 4) #レジスタ1の値4バイトを受信 data = i2c.getSlaveData(addr, 1, 4) print(data)
mbedはライブラリをあげときました。cppファイル中のサンプルコードで動きます。
まあそんな解説することもないです。
mbedの方のレジスタ登録は
union U{ int8_t _Registar[0x40]; int32_t Registar[0x10]; }; union U u = { 0 }; i2cslave slave(p28, p27, u._Registar);
としておいて、4バイトの方のレジスタを使用するといいです。
基本的にラズパイ側で使用する関数は、
writeSomeData(self, addr, reg, data, size)
getSlaveData(self, addr, reg, size)
だけです。
mbedとラズパイではI2Cアドレスの表記の仕方が下位1bitを書くか書かないかで異なるので、そこはmbedの方で修正するようにしてます。
こんな感じ
#define ADDR 0x1D #define _ADDR ADDR<<1 //on raspi
あとは、スレーブからマスターにデータ送信するときの
case WriteRequired: I2CSlave::read(DATA, 1); //捨て受信 int8_t tmp = *(Registar+reg); I2CSlave::write(tmp); I2CSlave::write(tmp); I2CSlave::write(tmp);
あたりがこだわりポイントですかね。。。
I2CSlave::write(tmp);
を2つとかにすると動かないんですよ。
これmbedとラズパイの遅延時間とかの問題だと思うんですけど、waitを入れてもやはり動かなくて、
やけくそでI2CSlave::write(tmp);を連打してみたら動いたみたいな感じです。
すごく気持ち悪いので直したらすぐ修正しときます。