i2c指令使用 + 仿照开源i2ctransfer实现的自己的i2ctransfer

1. 列出目前有哪些i2c controller

i2cdetect -l

image

2.查看某个特定i2c controller下面下挂的设备

i2cdetect -y 0

其中0表示想要查看i2c controller的标号,可以改成命令i2cdetect -l 中列出所有的数字

image

3.通过i2c指令读取camera的温度

i2ctransfer -y 0 w2@0x36 0x4D 0x60 r2@0x36

image

其中0x36表示slave address

0x4d60表示摄像头温度的寄存器,由于我们要读取两个值,所以写的是r2, 这样我们就可以读取出0x4D60, 0x4D61两个连续的值。

可以这样理解 w2@0x36 0x4D 0x60,设置了 start point是0x4d60,然后往下读两个,即0x4D60 + 0x4D61两个位置的寄存器,加起来总共两个byte,一个整数部分,一个小数部分

转换成人类可读的温度的方法如下

0x4e52因为小于0xc000
HEX2DEC(0x4e)-50+HEX2DEC(0x52)/256=28.3203125
大于0xc000的值为零下,公式中的-50改为-142

上面的结果中 0x4e是寄存器0x4D60的值,0x52是寄存器0x4D61的值

image

 4.通过研究开源i2ctransfer的代码,自己实现的代码如下,这样其他上层app就可以用函数的形式 向底层发出i2c命令。

以等效于命令“i2ctransfer -y 0 w2@0x36 0x4D 0x60 r2@0x36” 来讲解如何调用下面的函数

slave_address: 0x36
reg_part1:0x4D
reg_part2:0x60
result, result_len: 2,用来存放返回的2个byte的数据

所以上层代码调用的示例代码如下

unsigned char *return_array[2];

zhongshan_i2c_transfer(0x36, 0x4D, 0x60, return_array, 2);

#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include <fcntl.h>

int zhongshan_i2c_transfer(unsigned char slave_address, unsigned char reg_part1, unsigned char reg_part2, unsigned char *result, int result_len) {
    struct i2c_msg msgs[2];
    unsigned char *buf;
    struct i2c_rdwr_ioctl_data rdwr;
    int file, nmsgs_sent;

    file = open("/dev/i2c-0", O_RDWR);
    if (file < 0)
        printf("can not open /dev/i2c-0.");

    //construct write message.
    msgs[0].addr = slave_address;
    msgs[0].flags = 0;
    msgs[0].len = 2;
    buf = (unsigned char *)malloc(msgs[0].len);
    if (!buf)
        printf("Error: No memory for buffer\n");
    memset(buf, 0, msgs[0].len);
    msgs[0].buf = buf;
    msgs[0].buf[0] = reg_part1;
    msgs[0].buf[1] = reg_part2;

    //construct read message.
    msgs[1].addr = slave_address;
    msgs[1].flags = I2C_M_RD;   // #define I2C_M_RD        0x0001
    msgs[1].len = result_len;
    buf = (unsigned char *)malloc(msgs[1].len);
    if (!buf)
        printf("Error: No memory for buffer\n");
    memset(buf, 0, msgs[1].len);
    msgs[1].buf = buf;

    rdwr.msgs = msgs;
    rdwr.nmsgs = 2;
    nmsgs_sent = ioctl(file, I2C_RDWR, &rdwr);
    if (nmsgs_sent < 0) {
        printf("Error: Sending messages failed\n");
        return 1;
    } else if (nmsgs_sent < rdwr.nmsgs) {
        printf("Error: only %d/%d messages were sent\n", nmsgs_sent, rdwr.nmsgs);
        return 1;
    }
    
    result[0] = msgs[1].buf[0];
    if (result_len > 1)
        result[1] = msgs[1].buf[1];

    close(file);

    for (int i = 0; i < 2; i++)
        free(msgs[i].buf);

    return 0;
}

 

posted @ 2025-08-08 13:19  midhillzhou  阅读(55)  评论(0)    收藏  举报