Raspi I2C 与 Arduino 的通信问题与 wiringPi

Raspi I2C communication with Arduino issues with wiringPi

我在使用 wiringPiwiringPiI2CWriteReg16() 函数时遇到意外结果,我不确定这是由于使用不当还是其他原因造成的。这是函数的声明:

extern int wiringPiI2CWriteReg16 (int fd, int reg, int data);

wiringPiI2C.c 文件中有 notes 声明它类似于 Linux 的 SMBus 代码,如果有帮助的话。

在我的 Arduino(一个 Uno R3 和一个 Trinket Pro)上,我正在 运行 制作这个简化的草图:

#include <Wire.h>

#define SLAVE_ADDR 0x04

void receive_data (int num_bytes){
  Serial.print("bytes in: ");
  Serial.println(num_bytes);

  while(Wire.available()){
    int data = Wire.read(); // tried char, uint8_t etc
    Serial.println(data);
  }
  Serial.print("\n");
}

void setup() {
  Serial.begin(9600);
  Wire.begin(SLAVE_ADDR);
  Wire.onReceive(receive_data);
}

void loop() {
  delay(500);
}

我认为 Wire.read() 会在字节边界处分解事物,但在我的情况下不会发生这种情况。也许这是我的问题……误会。

尽管如此,我有这个 C 代码(需要 wiringPi v2.36+ 安装):

// word.c

#include <wiringPiI2C.h>

void main (){
    int fd = wiringPiI2CSetup(0x04);
    wiringPiI2CWriteReg16(fd, 0x00, 255);
    wiringPiI2CWriteReg16(fd, 0x01, 256);
}

这样编译:

gcc -o word word.c -lwiringPi

当 运行、./word 时,我在 Arduino 的串行输出上收到以下内容:

bytes in: 3
0
255
0

bytes in: 3
1
0
1

在第一次调用 wiringPiI2CWriteReg16() 时,我希望输出中的第一个字节为零 (0x00),因为这是我请求的寄存器地址。第二个字节(255)也是正确的。第三个字节 (0) 据我所知毫无意义(因为我只发送一个字节作为数据)。

然而,在对该函数的第二次调用中,我确实得到了寄存器的正确输出(第一个字节为 0x01 == 1),但第二个字节为零,并且第三个字节似乎是正确的余数(255 == 一个字节,+ 1)。问题是,第二个字节是 0.

如果我传入 511 或就此而言,任何数字作为调用中的数据,都会发生完全相同的效果。

我的问题是我是否遗漏了一些明显的东西(我对 C 和 Arduino 比较陌生),and/or 如果我能得到一些关于如何更彻底地解决这个问题的指示。

我发现问题出在我的 Arduino 代码中。在 Raspi 官方论坛上,Gordon 告诉我字节是分开读入的,LSB 在前。在我所有的搜索过程中,我都没有遇到过,而且真的不太明白发生了什么。将我的 Arduino 草图中的 I2C 读取循环代码更改为:

while(Wire.available()){
    Wire.read(); // throw away register byte

    int16_t data = Wire.read(); // LSB
    data += Wire.read() << 8;   // MSB

    Serial.print("data: ");
    Serial.println(data);
}

...一切正常。实际上,这至少是一种在 Arduino 上通过 I2C 读取两个字节值并将字节放回一起的方法。