c++ - 树莓派 I2C

标签 c++ linux arduino raspberry-pi i2c

我有多个使用 I2C 来回对话的 arduino。主机写两个字节,然后读回 1 个字节的响应。一切都很好,万岁。但现在我一直在努力将我的主人换成 Raspberry Pi。我编写的代码没有问题,但每 200 次读/写中有 1 次,它偶尔会返回错误的读数,这将严重影响系统的可靠性。我附上我的代码以防万一有人看到我做错了什么或者其他人之前遇到过类似的问题。

树莓派 C++ 代码:

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "../HaMiD_Lib/StopWatch.h"

using namespace std;

int file_i2c;
int length;
uint8_t buffer[2] = {0};

int timingLoopFreq = 500;       
int timingLoopMicroSeconds = 1000000 / timingLoopFreq;      //500 us
StopWatch loopTime(timingLoopMicroSeconds);                 // My own stopwatch livrary
uint8_t addr = 0x11;

using namespace std;

int main(void)
{
         //-------------- OPEN THE I2C BUS--------------------------
        char *filename = (char*)"/dev/i2c-1";
        if((file_i2c = open(filename, O_RDWR))< 0 ){
                //ERROR HANDLING: you can check errno to see what went wrong;
                cout << "Failed to open the i2c bus" << endl;
                return 0;
        }

        while(1){
                if (loopTime.check()) {
                        loopTime.reset();

                        if (ioctl(file_i2c, I2C_SLAVE, addr) < 0){
                                cout << "Failed to acquire bus access and/or talk to slave" << endl;
                                //ERROR HANDLING: you can check errno to see what went wrong;
                        }

                        // ------------- WRITE BYTES -------------
                        buffer[0] = 4;
                        buffer[1] = 0;
                        length = 2;                 //<<<<< Number of bytes to write
                        if (write(file_i2c, buffer, length) != length){                    // write() returns the number of bytes actually written, if it doesn't match then an error occurred (e.g. no response from the device)
                        // ERROR HANDLING: i2c transaction failed
                                cout << "Failed to write to the i2c bus " << endl;
                        } else {
                                    // ------------ READ BYTES -------
                                    length = 1;
                                    if (read(file_i2c, buffer, length) != length){              // read() returns the number of bytes actually read, if it doesn't match then an error occurred (e.g. no response from the device)
                                        //ERROR HANDLING: i2c transaction failed
                                        cout <<"Failed to read from the i2c bus" << endl;
                                    } else {
                                            cout << "Data read:" << buffer[0] << endl;
                                }
                        }
                }
        }
        cout << "exiting" << endl;
        return 0;
}

Arduino I2C 片段:

//I2C functions
void receiveEvent(int byteCount) {
    while (Wire.available()) {
        I2C_cmd_1st = Wire.read(); // 1 byte (maximum 256 commands)
        I2C_cmd_2nd = Wire.read(); // 1 byte (maximum 256 commands)
    }
}

void slavesRespond() {
    byte returnValue = 0;

    switch (I2C_cmd_1st) {
    case status_cmd:   // 40
        returnValue = module;
        if (module == DONE) {
            module = STOP;                  //reset the machine
        }
        break;
    case test_cmd:
        returnValue = ID;
        break;
    }
    Wire.write(returnValue);          // return response to last command
}

这里是 cout 输出的一小部分。读取的数据应始终返回 2 但有时(100 分之一)它无法从 i2c 总线读取或写入,有时(500 分之一)它返回错误值(在下面的示例中它应该返回 2 但有时返回 3是偶然的,也可能是 97 等)。

Data read:2
Data read:3    //This is wrong!
Data read:2
Failed to read from the i2c bus
Failed to read from the i2c bus
Data read:3    //This is wrong!
Data read:2

如有任何帮助,我们将不胜感激。有没有其他人看到过与 RPi 和 Arduino 类似的东西?接线非常简单,因为 RPi 是主机。

最佳答案

您是否尝试过在接收事件中只读取实际可用的我的数据。代码考虑到 receiveEvent 中的 byteCount 可以被 2 整除。

关于c++ - 树莓派 I2C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37086583/

相关文章:

c++ - 将字符串字面量的地址映射到字符串字面量,通过解析ELF C++程序

c++ - OPENGL:使用 VBO 的方形类

c++ - 使用自定义 TCL 解释器获取 "free(): invalid pointer"

c - 使用管道,从父进程读取 2 个数字,子进程计算它们的总和并将结果提供给父进程进行打印

c++ - PTRACE_TRACEME 的范围是多少?

ios - 使用蓝牙从 Arduino 获取数据到 iPhone

c++ - Arduino 矩阵数学?

android - 通过蓝牙在 Arduino 和 Android 之间传输串行数据

c++ - 使用 CLANG 内联汇编创建 C++ 预自增操作

regex - 使用 linux shell 对数据进行排序