【问题标题】:I2C-dev: Change write and read parametersI2C-dev:更改写入和读取参数
【发布时间】:2016-08-27 03:55:24
【问题描述】:

我目前正在研究 Raspberry Pi 3 和 PsoC 4 之间的 I2C。我正在使用 I2C-dev 库来处理 I2C 通信。至此I2C总线启动并运行,读写功能已经正确实现。但是,我想让函数指针成为读取和写入函数,因此 to 函数使用相同类型的参数(至少看起来像)我有以下称为 I

的主要代码

2Ctest-tools.cpp

#include <unistd.h>             //Needed for I2C port
#include <fcntl.h>              //Needed for I2C port
#include <sys/ioctl.h>          //Needed for I2C port
#include <linux/i2c-dev.h>      //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"


int main() {


        int addr = 0x49;
        int cmd = 2; //Write
        int length = 5;
        int file_i2c = 0;
        I2C myI2C;



        unsigned char buffer[5];

        buffer[0] = 0x01;
        buffer[1] = 0x02;
        buffer[2] = 0x20;
        buffer[3] = 0x00;
        buffer[4] = 0x17;

        i2c_init(&myI2C, cmd, addr, &file_i2c);
        i2c_exe(&myI2C, file_i2c, buffer, length);

    return 0;
}

如代码所示,我使用了一个名为 myI2C 的结构对象,该对象在 i2c_init、i2c_exe 两个函数中传递。 functions.cpp的源代码如下:

#include <unistd.h>             //Needed for I2C port
#include <fcntl.h>              //Needed for I2C port
#include <sys/ioctl.h>          //Needed for I2C port
#include <linux/i2c-dev.h>      //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"

int i2c_init(I2C *cthis, int cmd, int addr, int *ptrFile_i2c ) {
    char *filename = (char*)"/dev/i2c-1";
    if ((*ptrFile_i2c = open(filename, O_RDWR)) < 0)
    {
        //ERROR HANDLING: you can check errno to see what went wrong
        printf("Failed to open the i2c bus");
        return 0;
    }

    if (ioctl(*ptrFile_i2c, I2C_SLAVE, addr) < 0)
    {
        printf("Failed to acquire bus access and/or talk to slave.\n");
        //ERROR HANDLING; you can check errno to see what went wrong
        return 0;
    }

    switch(cmd) {
        case 1: 
            //cthis->WR = write;
            break;
        case 2:
            cthis->WR = read;
            break;
    }
    return 0;
}

int i2c_exe(I2C *cthis, int file_i2c, unsigned char *buffer, size_t length) {

    cthis->WR(file_i2c, buffer, length);
    return 0;
}

所以这里要注意的重要一点是,在函数 i2c_init 中,我打开了 varialbe cmd,它指示函数指针是指向写入函数还是读取函数。现在出现了失败部分。函数指针在其自己的名为 i2c.h 的 .h 文件中声明,如下所示:

struct I2C {
    ssize_t (*WR)(int, const void   *, size_t);
};

如您所见,函数指针必须指向带有参数(int、const void*、size_t)的函数,当函数指向写入函数但指向读取函数时,这就像一个魅力获取和错误,错误说:

functions.cpp:在函数‘int i2c_init(I2C*, int, int, int*)’中: functions.cpp:30:14: 错误: 'ssize_t ()(int, void, size_t) {aka int ()(int, void, unsigned int) 的无效转换)}' to 'ssize_t ()(int, const void, size_t) {aka int ()(int, const void, unsigned int)}' [-fpermissive] cthis->WR = 读取;

我研究了错误并得出结论,这是因为读写函数不知何故不采用相同的参数,这很奇怪,因为我在其中传递了相同的参数(int i2s_file,int buffer,int length)所以如果我将函数指针更改为

ssize_t (*WR)(int, void *, size_t);

该函数适用于读取,但不适用于写入。所以我的问题是:我可以通过更改 i2c-dev 库以某种方式更改写入或读取函数以采用相同的参数,或者我可以做些什么来解决这个问题?

这是 i2c-dev 库的链接,我完全放弃理解 http://textuploader.com/5yioi

多谢了

【问题讨论】:

    标签: c++ c raspberry-pi i2c


    【解决方案1】:

    您可以将函数显式转换为正确的类型:

    typedef ssize_t (*I2CCMD)(int, void *, size_t);
    
    cthis->WR = (I2CCMD)write;
    
    cthis->WR = (I2CCMD)read;
    

    这应该可以消除错误。

    【讨论】:

    • 是的,由于函数指针类型不兼容,它消除了错误并调用了未定义的行为。不过,它很可能会在实践中发挥作用。
    • @EmilMøllerRinggaard 重要的是您要意识到此代码依赖于指定不当的行为。您需要在 cmets 中记录。否则您的程序可能无法移植。
    【解决方案2】:

    显然read 函数不能接受指向const 的指针,因为与write 函数不同,它必须修改该参数。

    所以你不能用函数指针来切换功能,因为函数指针是不同的类型。

    最好的解决方法似乎是将“cmd”参数移动到i2c_exe 函数,或者创建一个包含cmd 的私有变量(在struct I2C 中是理想的)。然后在 i2c_exe 中调用 read 或 write。

    更糟糕的解决方案是将结构更改为联合,例如:

    union I2C {
        ssize_t (*WR)(int, const void   *, size_t);
        ssize_t (*read)(int, void*, size_t);
    };
    

    然后在读取的情况下,使用读取成员分配给结构。但请注意,这是一种“肮脏的黑客行为”,理论上它是一种指定不当的行为。在实践中,它很可能适用于任何给定的系统。 (const 正确性不太可能影响调用约定。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多