前回はSTM32F401CCU6にMicroPythonを載せ簡易動作させましたが、今回は同じボードを2枚用意して片方をMasterにもう一方をSlaveにしてI2C通信を行ってみました。
なお結線ですが、SCLがB6, SDAがB7、どちらも5vトレラントのピンなので、2kΩで5vにプルアップしています。
まず、マスターからスレーブにデータを転送する例です。
スレーブ側
まずスレーブ側です。
今回は以上です。それでは、Happy coding!
なお結線ですが、SCLがB6, SDAがB7、どちらも5vトレラントのピンなので、2kΩで5vにプルアップしています。
まず、マスターからスレーブにデータを転送する例です。
スレーブ側
from pyb import I2C SLAVE_ADDR = 0x40 BAUD = 100000 i2c_slave = I2C(1, I2C.SLAVE, addr=SLAVE_ADDR, baudrate=BAUD)この状態ではslaveはscanにも反応しないので以下のようにして待ち受けさせます。
while True:
try:
data = i2c_slave.recv(4)
except OSError as exc:
if exc.args[0] == 5:
# 5 == EIO ( bus scan )
print("I2C bus scan detected")
elif exc.args[0] == 110:
# 110 == ETIMEOUT
pass
else:
print(exc)
except KeyboardInterrupt:
break
else:
print("RECV: %r" % data)
続いてマスター側です。
from pyb import I2C
SLAVE_ADDR = 0x40
BAUD = 100000
i2c_master = I2C(1, I2C.MASTER, baudrate=BAUD)
i2c_master.scan()
for i in range(63):
i2c_master.send("%04i" % i, addr=SLAVE_ADDR)
pyb.delay(100)
成功するとスレーブ側が以下のようになります。
I2C bus scan detected RECV: b'0000' RECV: b'0001' RECV: b'0002' (中略) RECV: b'0060' RECV: b'0061' RECV: b'0062'次にスレーブからマスターへ送信する例です。
まずスレーブ側です。
import pyb # for adc
from pyb import I2C
SLAVE_ADDR = 0x40
BAUD = 100000
SENDTIMEOUT = 250
RECVTIMEOUT = 250
i2c_slave = I2C(1, I2C.SLAVE, addr=SLAVE_ADDR, baudrate=BAUD, dma=False)
RESOLUTION=12
def send_cpu_temp():
adc = pyb.ADCAll(RESOLUTION)
cpu_temparature = adc.read_core_temp()
i2c_slave.send(str(cpu_temparature), timeout=SENDTIMEOUT)
def send_vbat():
adc = pyb.ADCAll(RESOLUTION)
core_vbat = adc.read_core_vbat()
i2c_slave.send(str(core_vbat), timeout=SENDTIMEOUT)
def send_vref():
adc = pyb.ADCAll(RESOLUTION)
core_vref = adc.read_vref()
i2c_slave.send(str(core_vref), timeout=SENDTIMEOUT)
while True:
try:
data = i2c_slave.recv(2, timeout=RECVTIMEOUT)
except OSError as exc1:
if exc1.args[0] == 5:
# 5 == EIO ( bus scan )
print("I2C bus scan detected")
elif exc1.args[0] == 110:
# 110 == ETIMEOUT
pass
else:
print(exc1)
except KeyboardInterrupt:
break
else:
if data[0] == 0xFF and data[1] == 0x01:
try:
print("RECV: %r" % data)
send_cpu_temp()
except OSError as exc2:
if exc2.args[0] not in (5, 110):
break
except KeyboardInterrupt:
break
else:
pass
if data[0] == 0xFF and data[1] == 0x02:
try:
print("RECV: %r" % data)
send_vbat()
except OSError as exc2:
if exc2.args[0] not in (5, 110):
break
except KeyboardInterrupt:
break
else:
pass
if data[0] == 0xFF and data[1] == 0x03:
try:
print("RECV: %r" % data)
send_vref()
except OSError as exc2:
if exc2.args[0] not in (5, 110):
break
except KeyboardInterrupt:
break
else:
pass
マスター側です。
from pyb import I2C
SLAVE_ADDR = 0x40
BAUD = 100000
RES_INT=10
MES_INT=10000
TIMEOUT_RETRY = 5000
DATA_LEN=6
i2c_master = I2C(1, I2C.MASTER, baudrate=BAUD, dma=False)
def print_slave_sensor(param1, param2, unit_label):
buf = bytearray(2)
buf[0] = param1
buf[1] = param2
i2c_master.send(buf, addr=SLAVE_ADDR)
pyb.delay(RES_INT)
data = bytearray(DATA_LEN)
res = i2c_master.recv(data, addr=SLAVE_ADDR)
print("%s: %s" % (unit_label, res.decode()))
while True:
try:
print_slave_sensor(0xFF, 0x01, "Temp")
print_slave_sensor(0xFF, 0x02, "Vbat")
print_slave_sensor(0xFF, 0x03, "Vref")
pyb.delay(MES_INT - RES_INT*3)
except OSError as exc1:
if exc1.args[0] == 110:
print("ETIMEOUT: Could not read data.")
print("Waiting for %d ms." % TIMEOUT_RETRY)
pyb.delay(TIMEOUT_RETRY)
except KeyboardInterrupt:
break
else:
pass
正常に動作すると、マスター側は以下のようになります。
Temp: 28.518 Vbat: 1.6229 Vref: 3.2912初めはslave側のtimeoutを秒単位で大きく取っていてマスター側でtimeoutエラーが発生したのですが、slave側のtimeoutを250にするとマスター側でのtimeoutエラーが発生しなくなりました。パラメータの指定はまだ詰める必要はありそうですがとりあえず動いてはいるようなので、良しとしています。
今回は以上です。それでは、Happy coding!
コメント
コメントを投稿