在 MicroPython 中,通过 I2C 从附加设备读取内存会忽略提供的地址

In MicroPython reading memory from attached device via I2C ignores provided address

我正在尝试将适用于我的 M5 Thermal HAT(使用 MLX90640)(在 M5StickC 上)的 Arduino example project 转换为 MicroPython (1.18)。

尝试通过 I2C 读取数据时发生奇怪的事情。

创建 I2C 对象并扫描附加 HAT 的总线按预期工作:

>>> from machine import Pin, I2C
>>> i2c = I2C(0, sda=Pin(0), scl=Pin(26), freq=800000)
>>> i2c.scan()
[51]

读取 0x8000 处的状态寄存器,如 MLX90680 documentation 中所述,还有 returns 数据,这对我来说似乎是合理的:

>>> list(i2c.readfrom_mem(0x33, 0x8000, 2))
[0, 8]
>>> list(i2c.readfrom_mem(0x33, 0x8000, 2))
[0, 9]

第 3 位表示可用数据,第 0 位似乎切换页面。

但现在魔术开始了。

当我尝试读取 0x800D 处的“控制寄存器”时,如 Adafruit example(以及所有其他示例)所示,它的行为似乎与状态寄存器完全一样(首先进行切换位,这不应该发生在控制寄存器上):

>>> list(i2c.readfrom_mem(0x33, 0x800D, 2))
[0, 9]
>>> list(i2c.readfrom_mem(0x33, 0x800D, 2))
[0, 8]

经过一些试验并尝试使用不同的地址和大小后,我不得不意识到 I2C.readfrom_mem() 提供的地址似乎 完全被忽略了 :

>>> list(i2c.readfrom_mem(0x33, 0x0000, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x1000, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x2400, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x2800, 16))
[0, 8, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]

我尝试关闭所有设备并再次打开,使用不同的 addrsize 值和时钟速度,并尝试将不同的 HAT 连接到棒上(以确保 I2C 原则上工作正常)但所有没有见解。

由于大多数演示如何通过 I2C 使用 MLX90640 传感器的代码示例(例如 this or that)使用对 I2C 的低级访问(而不是 MicroPython readfrom_mem 实现),我还尝试了离散 write/read 方法:

>>> i2c.writeto(0x33, bytes([0x80, 0x0D]))
2
>>> list(i2c.readfrom(0x33, 2))
[0, 9]
>>> i2c.writeto(0x33, bytes([0x0D, 0x80]))  # try swapped byte order
2
>>> list(i2c.readfrom(0x33, 2))
[0, 9]

效果一样。

我做错了什么?因为我可以从 I2C 总线读取数据,所以我想我没有电气性质的问题..(本机 Arduino 示例也完全在同一设备上工作)。

是不是有一些基本的 I2C 知识是我到现在才错过的?

为什么 MicroPython 在此设备上发出的所有 I2C read 操作似乎都忽略了地址,而其他设备却工作得很好?

您似乎缺少 stop 参数。

micropython I2C writeto

试试这个:

i2c.writeto(0x33, bytes([mem_address>>8, mem_address&0xFF]), False)
i2c.readfrom(0x33, 2)

相应地写入你要写的数据:

i2c.writeto(0x33, bytes([mem_address>>8, mem_address&0xFF] + [d,a,t,a]))