跳到主要内容

I2C 通信

1. I2C子系统

在 Linux 操作系统中,I2C 子系统是一个关键的驱动框架,用于管理和控制通过 I2C 总线连接的各种外部设备,有关 I2C 子系统的更多详细信息可以在 <Linux内核源码>/Documentation/i2c 目录中找到。I2C 子系统的关键组成部分:

  1. sysfs 接口:I2C 子系统通过 sysfs 文件系统提供用户空间接口,以便用户可以访问和配置与 I2C 设备相关的信息。其中 /sys/bus/i2c/devices 目录用于管理和配置 I2C 设备的属性和状态信息。用户可以通过读写 sysfs 文件来获取设备信息或控制设备。
  2. I2C 设备节点:在 /dev 目录下,通常会创建类似 /dev/i2c-3 的字符设备节点,这些节点允许用户在用户空间与特定的 I2C 设备或 I2C 适配器进行通信。通过这些节点,用户可以发送和接收数据,以实现对 I2C 设备的操作。

2. I2C测试(Shell)

2.1 引脚分布

  • Luckfox Lyra Ultra/Ultra W 引脚图:

2.2 查看设备

/sys/bus/i2c/devices 目录中,每个 I2C 设备都有自己的文件夹。这些文件夹的名称通常包含 i2c 和设备编号,例如 `/sys/bus/i2c/devices/i2c-1 表示 I2C 总线编号为 1 的设备。如果您想查看系统存在的 I2C 总线,可以使用如下命令:

root@luckfox:~# ls /dev/i2c*
/dev/i2c-2 /dev/i2c-1

2.3 I2C测试

  1. 查看 i2c-0 接口上的设备。

    i2cdetect -a -y 1

    root@luckfox:/home/luckfox# i2cdetect -a -y 1
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- 3d -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  2. 读取指定设备的全部寄存器的值

    i2cdump  -f -y 1 0x68
  3. 读取指定 IIC 设备的某个寄存器的值,如下读取地址为0x3d器件中的0x01寄存器值

    i2cget -f -y 1 0x68 0x01

3. I2C通讯(Python 程序)

  1. 完整代码:

    import smbus
    import time

    # I2C 总线 (根据你的设备实际情况选择 0 或 1)
    I2C_BUS = 1

    # 从设备地址
    I2C_ADDR = 0x3d

    # 寄存器地址(根据你需要的从设备寄存器)
    REG_ADDR = 0x00 # 例如,读取第一个寄存器的数据

    def i2c_read():
    # 创建 SMBus 实例
    bus = smbus.SMBus(I2C_BUS)

    try:
    # 读取从设备的寄存器值
    data = bus.read_byte_data(I2C_ADDR, REG_ADDR)
    print(f"Data read from device 0x{I2C_ADDR:02x}: 0x{data:02x}")
    except Exception as e:
    print(f"Error reading from device: {e}")
    finally:
    bus.close()

    if __name__ == "__main__":
    i2c_read()
  2. 运行程序:

    root@luckfox:/home/luckfox# python3 i2c_test.py 
    Data read from device 0x3d: 0x41

4. I2C通讯(C 程序)

  1. 完整代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <linux/i2c-dev.h>
    #include <stdint.h>


    #define I2C_BUS "/dev/i2c-1" // I2C 总线 (根据你的设备选择 i2c-0 或 i2c-1)
    #define I2C_ADDR 0x3d // 从设备地址

    int i2c_read(int file, uint8_t reg_addr) {
    uint8_t buf[1] = {0};

    // 写入寄存器地址
    if (write(file, &reg_addr, 1) != 1) {
    perror("Failed to write register address");
    return -1;
    }

    // 读取从设备数据
    if (read(file, buf, 1) != 1) {
    perror("Failed to read from device");
    return -1;
    }

    printf("Data read from device 0x%02x: 0x%02x\n", I2C_ADDR, buf[0]);
    return buf[0];
    }

    int main() {
    int file;

    // 打开 I2C 总线
    if ((file = open(I2C_BUS, O_RDWR)) < 0) {
    perror("Failed to open I2C bus");
    return 1;
    }

    // 设置从设备地址
    if (ioctl(file, I2C_SLAVE, I2C_ADDR) < 0) {
    perror("Failed to set I2C address");
    close(file);
    return 1;
    }

    // 读取寄存器 0x00 的数据
    i2c_read(file, 0x00);

    // 关闭 I2C 设备
    close(file);

    return 0;
    }
  2. 交叉编译运行程序,搭建交叉编译环境请参考《程序编译》或《GPIO》部分。

    arm-none-linux-gnueabihf-gcc i2c_test.c  -o i2c_test

5. 设备树简介

  1. 设备文件路径位于kernel-6.1/arch/arm/boot/dts/rk3506g-luckfox-lyra.dts,开启i2c1的代码片段如下:

    &i2c1 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&rm_io10_i2c1_scl &rm_io11_i2c1_sda>;
    };

    &pinctrl {
    rm_io10 {
    rm_io10_i2c1_scl: rm-io10-i2c1-scl {
    rockchip,pins =
    <0 RK_PB2 32 &pcfg_pull_up>;
    };
    };

    rm_io11 {
    rm_io11_i2c1_sda: rm-io11-i2c1-sda {
    rockchip,pins =
    <0 RK_PB3 33 &pcfg_pull_up>;
    };
    };
    };