ラズパイと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()
i2c.writeSomeData(addr, 0, 12345, 4)
data = i2c.getSlaveData(addr, 0, 4)
print(data)
i2c.writeSomeData(addr, 1, 6543, 4)
data = i2c.getSlaveData(addr, 1, 4)
print(data)
mbedはライブラリをあげときました。cppファイル中のサンプルコードで動きます。
os.mbed.com
まあそんな解説することもないです。
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
あとは、スレーブからマスターにデータ送信するときの
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);を連打してみたら動いたみたいな感じです。
すごく気持ち悪いので直したらすぐ修正しときます。