STEVAL-DRONE01上の加速度センサはマイコンとSPI 3-Wireモードで接続されていてMicroPython上で利用可能な標準のSPIドライバでは制御できない*1。
泥臭いが、ビットバンギングでIOポートを上げ下げしてSPI 3-Wire相当のバスを作って加速度センサのレジスタを読んでみた。
結果、以下の通りで動いてそうな感じ。
>>> reg_dump() 00: 00 00 00 00 00 00 00 00 12 00 00 00 00 00 00 6a 10: 00 00 08 00 00 00 00 00 e0 00 00 00 00 00 00 c2 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30: 00 00 00 00 00 00 00 00 00 00 00 10 00 00 bb a8 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50: 00 00 00 00 84 00 00 00 00 00 00 00 00 00 00 00 60: 00 00 00 00 00 bb 00 00 00 00 00 00 00 00 00 00 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80: 00 00 00 00 00 00 00 00 12 00 00 00 00 00 00 6a 90: 00 00 08 00 00 00 00 00 e0 00 00 00 00 00 00 c2 a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b0: 00 00 00 00 00 00 00 00 00 00 00 10 00 00 bb a8 c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0: 00 00 00 00 84 00 00 00 00 00 00 00 00 00 00 00 e0: 00 00 00 00 00 bb 00 00 00 00 00 00 00 00 00 00 f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
あたりまえだが、、ダンプさせるともっさり動いている。
SPI 3-Wireモードによる制御サンプルは以下
#-----------------------------------------
from pyb import Pin
# def for SPI
SPI_READ_BIT = 0x80
CTRL3_C = 0x12
CTRL6_C = 0x15
SIM_3WIRE = 0x08
lsm6d_cs = None
s2_clk = None
s2_sda = None
def reg_dump():
for addr in range(0xff+1):
data = spi_read_reg(addr)
if (addr % 16) == 0:
print(f"\n{addr:02x}: ", end="")
print(f"{data:02x} ", end="")
print("")
def spi_init():
global lsm6d_cs, s2_clk, s2_sda
lsm6d_cs = Pin(Pin.cpu.A8, mode=Pin.OUT)
s2_clk = Pin(Pin.cpu.B13, mode=Pin.OUT)
s2_sda = Pin(Pin.cpu.B15, mode=Pin.OUT)
def spi_write_reg(addr,data):
global lsm6d_cs, s2_clk, s2_sda
s2_sda = Pin(Pin.cpu.B15, mode=Pin.OUT)
lsm6d_cs.high()
spi_out(addr, no_ctrl_cs = True)
spi_out(data, no_ctrl_cs = True)
lsm6d_cs.low()
def spi_read_reg(addr):
global lsm6d_cs, s2_clk, s2_sda
s2_sda = Pin(Pin.cpu.B15, mode=Pin.OUT)
lsm6d_cs.high()
spi_out(addr | SPI_READ_BIT, no_ctrl_cs = True)
s2_sda = Pin(Pin.cpu.B15, mode=Pin.IN)
data = spi_in(no_ctrl_cs = True)
#print(f"{data:02x}")
lsm6d_cs.low()
return data
def spi_out(data,no_ctrl_cs = False):
global lsm6d_cs, s2_clk, s2_sda
# setup SPI bus
if not no_ctrl_cs:
lsm6d_cs.high()
s2_clk.high()
s2_sda.high()
lsm6d_cs.low()
mask = 0x80
for i in range(8):
s2_clk.low()
#print("C_L ",end="")
if data & mask:
s2_sda.high()
#print("D_H ",end="")
else:
s2_sda.low()
#print("D_L ",end="")
s2_clk.high()
#print("C_H")
mask >>= 1
if not no_ctrl_cs:
lsm6d_cs.high()
def spi_in(no_ctrl_cs = False):
global lsm6d_cs, s2_clk, s2_sda
# setup SPI bus
if not no_ctrl_cs:
lsm6d_cs.high()
s2_clk.high()
lsm6d_cs.low()
data = 0
for i in range(8):
data <<= 1
s2_clk.low()
#print("C_L ",end="")
s2_clk.high()
#print("C_H ",end="")
if s2_sda.value() == 1:
#print("D_H")
data |=1
else:
pass
#print("D_L")
if not no_ctrl_cs:
lsm6d_cs.high()
return data
#----------------------------------------------
spi_init()
# set 3-wire mode
addr = CTRL3_C
data = SIM_3WIRE
spi_write_reg(addr,data)
data = spi_read_reg(addr)
print(f"{data:02x}")
reg_dump()
■追記
あらためて読み直すと、、以下のCS操作は逆ではなかろうか。
def spi_write_reg(addr,data):
global lsm6d_cs, s2_clk, s2_sda
s2_sda = Pin(Pin.cpu.B15, mode=Pin.OUT)
lsm6d_cs.high() # not cs.high but cs.low ??
spi_out(addr, no_ctrl_cs = True)
spi_out(data, no_ctrl_cs = True)
lsm6d_cs.low() # not cs.low but cs.high ??