I2C 通信
1. I2C子系统
在 Linux 操作系统中,I2C 子系统是一个关键的驱动框架,用于管理和控制通过 I2C 总线连接的各种外部设备,有关 I2C 子系统的更多详细信息可以在 <Linux内核源码>/Documentation/i2c 目录中找到。I2C 子系统的关键组成部分:
- sysfs 接口:I2C 子系统通过 sysfs 文件系统提供用户空间接口,以便用户可以访问和配置与 I2C 设备相关的信息。其中
/sys/bus/i2c/devices目录用于管理和配置 I2C 设备的属性和状态信息。用户可以通过读写 sysfs 文件来获取设备信息或控制设备。 - 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测试
查看 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: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --读取指定设备的全部寄存器的值
i2cdump -f -y 1 0x68读取指定 IIC 设备的某个寄存器的值,如下读取地址为
0x3d器件中的0x01寄存器值i2cget -f -y 1 0x68 0x01
3. I2C通讯(Python 程序)
完整代码:
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()运行程序:
root@luckfox:/home/luckfox# python3 i2c_test.py
Data read from device 0x3d: 0x41
4. I2C通讯(C 程序)
完整代码:
#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, ®_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;
}交叉编译运行程序,搭建交叉编译环境请参考《程序编译》或《GPIO》部分。
arm-none-linux-gnueabihf-gcc i2c_test.c -o i2c_test
5. 设备树简介
设备文件路径位于
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>;
};
};
};