首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用c语言设置I2C的读写

用c语言设置I2C的读写
EN

Stack Overflow用户
提问于 2018-10-25 02:33:21
回答 2查看 8.4K关注 0票数 0

首先,我在这方面是新手,但我正在学习,真的想让它工作起来。我买了一台树莓机和一台bno055博世加速计。它附带了一个bno055.c、bno055.h和一个bno055_support.c文件。在学习了编程和c语言并学习/尝试之后,我似乎需要以某种方式定义如何进行I2C读写。需要对其进行设置,以便您可以定义读取/写入的字节数。您可以在下面找到两个预定义的函数:

代码语言:javascript
复制
/*  \Brief: The API is used as I2C bus write
 *  \Return : Status of the I2C write
 *  \param dev_addr : The device address of the sensor
 *  \param reg_addr : Address of the first register,
 *   will data is going to be written
 *  \param reg_data : It is a value hold in the array,
 *      will be used for write the value into the register
 *  \param cnt : The no of byte of data to be write
 */
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
    s32 BNO055_iERROR = BNO055_INIT_VALUE;
    u8 array[I2C_BUFFER_LEN];
    u8 stringpos = BNO055_INIT_VALUE;

    array[BNO055_INIT_VALUE] = reg_addr;
    for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
        array[stringpos + BNO055_I2C_BUS_WRITE_ARRAY_INDEX] =
            *(reg_data + stringpos);
    }
    /*
    * Please take the below APIs as your reference for
    * write the data using I2C communication
    * "BNO055_iERROR = I2C_WRITE_STRING(DEV_ADDR, ARRAY, CNT+1)"
    * add your I2C write APIs here
    * BNO055_iERROR is an return value of I2C read API
    * Please select your valid return value
    * In the driver BNO055_SUCCESS defined as 0
    * and FAILURE defined as -1
    * Note :
    * This is a full duplex operation,
    * The first read data is discarded, for that extra write operation
    * have to be initiated. For that cnt+1 operation done
    * in the I2C write string function
    * For more information please refer data sheet SPI communication:
    */
    return (s8)BNO055_iERROR;
}

 /* \Brief: The API is used as I2C bus read
 *  \Return : Status of the I2C read
 *  \param dev_addr : The device address of the sensor
 *  \param reg_addr : Address of the first register,
 *  will data is going to be read
 *  \param reg_data : This data read from the sensor,
 *   which is hold in an array
 *  \param cnt : The no of byte of data to be read
 */
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
    s32 BNO055_iERROR = BNO055_INIT_VALUE;
    u8 array[I2C_BUFFER_LEN] = {BNO055_INIT_VALUE};
    u8 stringpos = BNO055_INIT_VALUE;

    array[BNO055_INIT_VALUE] = reg_addr;

    /* Please take the below API as your reference
     * for read the data using I2C communication
     * add your I2C read API here.
     * "BNO055_iERROR = I2C_WRITE_READ_STRING(DEV_ADDR,
     * ARRAY, ARRAY, 1, CNT)"
     * BNO055_iERROR is an return value of SPI write API
     * Please select your valid return value
     * In the driver BNO055_SUCCESS defined as 0
     * and FAILURE defined as -1
     */
    for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
        *(reg_data + stringpos) = array[stringpos];
    return (s8)BNO055_iERROR;
}

我的问题是,有没有人可以指导我通过这个挑战?我正在学习,https://www.kernel.org/doc/Documentation/i2c/dev-interface,但现在被困在这里了。为阅读/回复提前Thx。

EN

回答 2

Stack Overflow用户

发布于 2018-10-25 03:59:35

我最近为MMA8451 i2c加速度计写了一个library similar to what you're describing

本质上,Linux中的i2c控制器会被分配一个设备节点(例如/dev/i2c-1)。您将以文件like this形式打开此设备节点

代码语言:javascript
复制
int file = open(path, O_RDWR); //path = /dev/i2c-1

一旦有了文件句柄,就可以使用ioctl's读写i2c寄存器。i2c内核模块支持I2C_RDWR ioctl,它允许您与i2c寄存器交互。

要读取寄存器,您需要执行something like this

代码语言:javascript
复制
int mma8451_get_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char *val) {
    unsigned char inbuf, outbuf;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];

    outbuf = reg;
    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = &outbuf;

    messages[1].addr  = addr;
    messages[1].flags = I2C_M_RD;
    messages[1].len   = sizeof(inbuf);
    messages[1].buf   = &inbuf;

    packets.msgs      = messages;
    packets.nmsgs     = 2;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        return 0;
    }
    *val = inbuf;

    return 1;
}

要写入寄存器,您需要执行something like this

代码语言:javascript
复制
int mma8451_set_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char value) {
    unsigned char outbuf[2];
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[1];

    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = outbuf;

    outbuf[0] = reg;
    outbuf[1] = value;

    packets.msgs  = messages;
    packets.nmsgs = 1;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        return 0;
    }

    return 1;
}

编辑:I2C_RDWR ioctl采用i2c_rdwr_ioctl_data结构作为参数。我是described like this

另一个常见的数据结构是struct i2c_rdwr_ioctl_data

这是在I2C_RDWR ioctl调用中使用的结构

struct i2c_rdwr_ioctl_data { struct i2c_msg __user *msgs; /* pointers to i2c_msgs */ __u32 nmsgs; /* number of i2c_msgs */ };

(在linux/i2c-dev.h中定义)这个结构指向要处理的i2c_msg数组,并定义数组中的i2c_msg数量。

用法:如果程序要写入一个字节(例如-索引字节),然后读取一个字节,则需要两个结构i2c_msg数据结构。一个用于写入,另一个用于读取。这两个数据结构应该声明为两个i2c_msg数据结构的数组。它们将按照它们在数组中出现的顺序进行处理。

i2c_rdwr_ioctl_data结构包含一个指向i2c_msg结构数组的指针。这些结构包含您想要发送或接收的实际消息。例如,我的加速计为了读取一个寄存器,我首先需要将我想要读取的寄存器写入设备,然后我就可以读取它(这就是为什么在我的read函数中有两个i2c_msg)。

您需要参考data sheet for your BNO055来准确地找出哪些寄存器做了什么。

至于你的例子,它看起来来自bno055_support.c。看起来这只是你打算实现的一组存根。它看起来基本上是一个真实界面的模拟。所以重要的是接口,而不是实际的代码(所以不用担心cnt)。重要的部分如下:

代码语言:javascript
复制
s8 I2C_routine(void)
{
    bno055.bus_write = BNO055_I2C_bus_write;
    bno055.bus_read = BNO055_I2C_bus_read;
    bno055.delay_msec = BNO055_delay_msek;
    bno055.dev_addr = BNO055_I2C_ADDR1;

    return BNO055_INIT_VALUE;
}

这会将设备结构上的函数指针设置为将要定义的写入函数,并设置设备的地址和延迟。在此基础上,您需要实现与此接口匹配的函数:

代码语言:javascript
复制
#define BNO055_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
    bus_write(dev_addr, reg_addr, reg_data, wr_len)


#define BNO055_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len)\
    bus_read(dev_addr, reg_addr, reg_data, r_len)

我上面给你的函数应该是非常接近的。祝好运!

票数 2
EN

Stack Overflow用户

发布于 2020-07-14 14:13:33

例如

代码语言:javascript
复制
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
    u8 array[I2C_BUFFER_LEN] = { BNO055_INIT_VALUE };
    array[BNO055_INIT_VALUE] = reg_addr;
    
    if (write(file, array, 1) != 1) {
        return -1;
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    s8 res = read(file, reg_data, cnt);

    if (res > 0) return 0;
    else return -1;

}
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
    char buf[1 + cnt];
    buf[0] = reg_addr;
    memcpy(&buf[1], reg_data, cnt);

    if (write(file, buf, cnt+1) != cnt+1) {
        return -1;
    }
    return 0;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52975817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档