如何通过I2C发送数组?

2 投票
3 回答
8604 浏览
提问于 2025-04-18 19:55

我这几天一直在尝试通过I2C发送一个Python数组。

data = [x,x,x,x] # `x` is a number from 0 to 127.
bus.write_i2c_block_data(i2c_address, 0, data)

bus.write_i2c_block_data(addr, cmd, array) 

在上面的函数中:addr 是 Arduino 的 I2C 地址;cmd - 我不太确定这是什么;array - 是一个包含整数的 Python 数组。
这能实现吗?实际上这个 cmd 是什么呢?


顺便提一下,这是我在 Arduino 代码中接收数组并将其放入 byteArray 的部分:

void receiveData(int numByte){
    int i = 0;
    while(wire.available()){
        if(i < 4){
            byteArray[i] = wire.read();
            i++;
        }
     }
  }

我遇到了这个错误:
bus.write_i2c_block_data(i2c_adress, 0, decodedArray) IOError: [Errno 5] Input/output error.
我试过这个:bus.write_byte(i2c_address, value),它可以工作,但只适用于从 0 到 127 的 value,而我需要传递的不仅仅是一个值,而是一个完整的数组。

3 个回答

0

cmd是你想要写入数据的偏移量。

所以它就像这样:

bus.write_byte(i2c_address, offset, byte)

但是如果你想写入一个字节数组,那么你需要写入块数据,这样你的代码就会像这样:

bus.write_i2c_block_data(i2c_address, offset, [array_of_bytes])
3

这个函数是个好函数。

不过你需要注意一些要点:

  • bus.write_i2c_block_data(addr, cmd, []) 会把 cmd 的值和列表里的值一起发送到 I2C 总线上。

所以

bus.write_i2c_block_data(0x20, 42, [12, 23, 34, 45])

实际上发送给设备的不是 4 个字节,而是 5 个字节。

我不知道 Arduino 上的 wire 库是怎么工作的,但设备只读取 4 个字节,它不会对最后一个字节发送确认信号(ACK),这就导致发送方检测到输出错误。

  • I2C 设备地址有两种约定。I2C 总线有 7 位用于设备地址,还有一位用来表示是读取还是写入。另一种(错误的)约定是用 8 位来表示地址,并说你有一个用于读取的地址和一个用于写入的地址。smbus 包使用的是正确的约定(7 位)。

举个例子:在 7 位约定下,0x23 变成写入时的 0x46,读取时的 0x47。

0

我花了一些时间,但终于搞定了。

在Arduino那边:

int count = 0;
...

...
void receiveData(int numByte){

    while(Wire.available()){
      if(count < 4){
        byteArray[count] = Wire.read();
        count++;
      }
      else{
        count = 0;
        byteArray[count] = Wire.read();
      }
    }
}  

在树莓派那边:

def writeData(arrayValue):

    for i in arrayValue:
        bus.write_byte(i2c_address, i)

就这样。

撰写回答