i2ctransfer

i2ctransfer

i2ctransfer 是一个在 Linux 系统上通过 I2C 总线与设备通信的工具,它通常用于执行低级的 I2C 数据传输。这个命令允许用户通过 I2C 总线进行读取和写入操作。它是 i2c-tools 包的一部分,通常用于调试和与 I2C 设备进行交互。


提示: i2c 通信失败可以参考《rk3568 I2C》


前期准备

  1. Linux 安装 i2c-tools
    如果你的Linux系统上还没有安装 i2c-tools,可以通过以下命令进行安装:
sudo apt-get install i2c-tools

buildroot 默认集成 i2c工具包,无需额外配置。

  1. Android 添加 i2ctransfer 工具
    从 官方下载 i2c-tools
    i2c-tools
    将代码放在Android项目源代码的external目录下,解包后得到 i2c-tools-4.4 文件夹。
    方便进行编译,编写 Android.mk,内容如下:
LOCAL_PATH:= $(call my-dir)

################### i2c-tools #########################
include $(CLEAR_VARS)

LOCAL_MODULE := i2c-tools

LOCAL_SRC_FILES := \
    tools/i2cbusses.c \
    tools/util.c \
    lib/smbus.c

LOCAL_C_INCLUDES += \
    $(LOCAL_PATH) \
    $(LOCAL_PATH)/include

#LOCAL_CFLAGS := -g -Wall -Werror -Wno-unused-parameter
include $(BUILD_STATIC_LIBRARY)

################### i2ctransfer #######################
include $(CLEAR_VARS)

LOCAL_MODULE:=i2ctransfer

LOCAL_SRC_FILES:= \
    tools/i2ctransfer.c

LOCAL_C_INCLUDES += \
    $(LOCAL_PATH) \
    $(LOCAL_PATH)/include

LOCAL_SHARED_LIBRARIES:= \
    libc
LOCAL_STATIC_LIBRARIES := \
    i2c-tools

LOCAL_CPPFLAGS += -DANDROID

include $(BUILD_EXECUTABLE)

提示:源码中包含 i2cdetect、i2cget、i2cdump、i2cset等工具,切勿添加到编译配置文件,以免与原有冲突。

配置环境变量,编译 i2ctransfer

source build/envsetup.sh
lunch rk3568_s-userdebug
# 编译 i2ctransfer
mmm external/i2c-tools-4.4 -j8
.......
[100% 1/1] initializing build system ...
device/rockchip/common/prebuild.mk:2: warning: Generating manifest snapshot at out/commit_id.xml...
device/rockchip/common/prebuild.mk:3: warning: You can disable this by removing this and setting BOARD_RECORD_COMMIT_ID := false in BoardConfig.mk
Saved manifest to out/commit_id.xml
[100% 28/28] Install: out/target/product/rk3568_s/system/bin/i2ctransfer

将生成 i2ctransfer 拷贝到系统,到此 i2ctransfer 工具准备完成。

1. i2ctransfer 简述

i2ctransfer 是一个在 Linux 系统上通过 I2C 总线与设备通信的工具,它通常用于执行低级的 I2C 数据传输。这个命令允许用户通过 I2C 总线进行读取和写入操作。它是 i2c-tools 包的一部分,通常用于调试和与 I2C 设备进行交互。

1.1 i2ctransfer 命令基础介绍

i2ctransfer 命令的基本结构:

i2ctransfer -f -y <bus> <read/write>N@<address> [<data>...]

参数详解:

  • -f--force:强制执行该操作,即使有一些警告或潜在的错误存在。
  • -y:跳过对总线访问的确认,通常用于自动化脚本,防止每次都询问确认。
  • <bus>:指定 I2C 总线的编号。在大多数系统上,I2C 总线设备路径通常为 /dev/i2c-X,其中 X 是总线编号。总线编号通常可以通过 ls /dev/i2c-* 命令来确认。
  • <read/write>:指定是进行读操作(rN,N 是要写入的字节数)还是写操作(wN,N 是要读取的字节数)。读操作会从设备读取数据,写操作则向设备发送数据。
  • <address>:指定 I2C 设备的地址,这是设备的 7 位地址(0xXX)。设备地址通常可以从文档或数据表中找到。
  • <data>:在写操作中,列出要发送到设备的数据字节;在读操作中,指定要读取的字节数。

额外选项:

  • -r <retries>:指定重试次数,表示在遇到通信失败时自动重试指定次数。
  • -t <timeout>:指定每次操作的超时时间(以毫秒为单位)。

2. i2ctransfer 示例

简单讲解 i2ctransfer 在不同场景下使用方法。

2.1 芯片 7位i2c地址 8位寄存器地址 8位数据读写操作

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x18, 写入数据 0xa7
i2ctransfer -f -y 3 w2@0x1a 0x18 0xa7

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x18:表示寄存器地址 0x18。
0xa7:表示要写入的值。

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x18, 读取一字节
i2ctransfer -f -y 3 w1@0x1a 0x18 r1

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x18:表示寄存器地址 0x18。
r1:表示要读取字节数量。

2.2 芯片 7位i2c地址 16位寄存器地址 8位数据 读写操作

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x3018, 写入数据 0xa7
i2ctransfer -f -y 3 w3@0x1a 0x30 0x18 0xa7

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
0xa7:表示要写入的值。

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x3018, 读取一字节
i2ctransfer -f -y 3 w2@0x1a 0x30 0x18 r1

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
r1:表示要读取字节数量。

2.3 芯片 7位i2c地址 16位寄存器地址 16位数据 读写操作

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x3018, 写入数据 0xa7
i2ctransfer -f -y 3 w4@0x1a 0x30 0x18 0xa7 0xb0

-y 3:选择 I2C 总线 3,并跳过确认提示。
w4@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
0xa7 0xb0:表示写入寄存器的值 0xa7b0,这里分为两个字节分别发送。0xa7 是高字节,0xb0 是低字节。

i2c总线 3, 芯片地址 0x1a, 寄存器地址 0x3018, 读取一字节
i2ctransfer -f -y 3 w2@0x1a 0x30 0x18 r1

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a:表示写操作,设备地址为 0x1a,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
r2:表示要读取字节数量。

2.4 芯片 13位i2c地址 16位寄存器地址 8位数据 读写操作

i2c总线 3, 芯片地址 0x1a20, 寄存器地址 0x3018, 写入数据 0xa7
i2ctransfer -f -y 3 w3@0x1a20 0x30 0x18 0xa7

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a20:表示写操作,设备地址为 0x1a20,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
0xa7:表示要的值。

i2c总线 3, 芯片地址 0x1a20, 寄存器地址 0x3018, 读取一字节
i2ctransfer -f -y 3 w2@0x1a20 0x30 0x18 r1

-y 3:选择 I2C 总线 3,并跳过确认提示。
w2@0x1a20:表示写操作,设备地址为 0x1a20,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
r1:表示要读取字节数量。

2.5 芯片 13位i2c地址 16位寄存器地址 16位数据 读写操作

i2c总线 3, 芯片地址 0x1a20, 寄存器地址 0x3018, 写入数据 0xa7
i2ctransfer -f -y 3 w4@0x1a20 0x30 0x18 0xa7

-y 3:选择 I2C 总线 3,并跳过确认提示。
w4@0x1a20:表示写操作,设备地址为 0x1a20,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
0xa7 0xb0:表示写入寄存器的值 0xa7b0,这里分为两个字节分别发送。0xa7 是高字节,0xb0 是低字节。

i2c总线 3, 芯片地址 0x1a20, 寄存器地址 0x3018, 读取2字节
i2ctransfer -f -y 3 w2@0x1a20 0x30 0x18 r2

-y 3:选择 I2C 总线 3,并跳过确认提示。
w4@0x1a20:表示写操作,设备地址为 0x1a20,后面跟随两个字节的操作。
0x30 0x18:表示寄存器地址 0x3018,这里分为两个字节分别发送。0x30 是高字节,0x18 是低字节。
r2:表示要读取字节数量。

3. i2ctransfer 帮助说明

Usage: i2ctransfer [-f] [-y] [-v] [-V] [-a] I2CBUS DESC [DATA] [DESC [DATA]]...
  I2CBUS is an integer or an I2C bus name
  DESC describes the transfer in the form: {r|w}LENGTH[@address]
    1) read/write-flag 2) LENGTH (range 0-63535, or '?')
    3) I2C address (use last one if omitted)
  DATA are LENGTH bytes for a write message. They can be shortened by a suffix:
    = (keep value constant until LENGTH)
    + (increase value by 1 until LENGTH)
    - (decrease value by 1 until LENGTH)
    p (use pseudo random generator until LENGTH with value as seed)

Example (bus 0, read 8 byte at offset 0x64 from EEPROM at 0x50):
  # i2ctransfer 0 w1@0x50 0x64 r8
Example (same EEPROM, at offset 0x42 write 0xff 0xfe ... 0xf0):
  # i2ctransfer 0 w17@0x50 0x42 0xff

结语

不枉博主详细讲解,欢迎订阅博主–炭烤毛蛋

`i2c_transfer`是Linux内核提供的函数,用于在I2C总线上进行数据传输。该函数可以同时处理多个I2C消息,包括读取和写入操作。 函数原型如下: ```c int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); ``` 参数说明: - `adap`:指向要进行传输的I2C适配器(总线)的指针。 - `msgs`:指向I2C消息数组的指针,每个消息包含了要传输的数据、设备地址和标志位等信息。 - `num`:要传输的消息数量。 返回值为传输的消息数量,如果返回值小于`num`,则表示传输过程中发生了错误。 下面是一个简单的示例代码,演示如何使用`i2c_transfer`函数进行I2C数据传输: ```c #include <linux/i2c.h> #include <linux/i2c-dev.h> #include <fcntl.h> #include <unistd.h> int main() { int fd = open("/dev/i2c-0", O_RDWR); if (fd < 0) { perror("Failed to open I2C bus"); return 1; } struct i2c_msg msgs[2]; unsigned char buf[2]; int ret; // 设置从设备地址 msgs[0].addr = 0x50; msgs[0].flags = 0; msgs[0].buf = buf; msgs[0].len = 1; // 读取数据 buf[0] = 0x00; msgs[1].addr = 0x50; msgs[1].flags = I2C_M_RD; msgs[1].buf = buf; msgs[1].len = 4; ret = i2c_transfer(fd, msgs, 2); if (ret < 0) { perror("Failed to transfer data"); close(fd); return 1; } // 处理读取的数据 // ... close(fd); return 0; } ``` 上述示例代码中,首先打开I2C总线设备文件`/dev/i2c-0`,然后使用`i2c_msg`结构创建一个I2C消息数组。在示例中,我们设置了两个消息:第一个消息用于写入要读取的寄存器地址,第二个消息用于读取4个字节的数据。最后,我们使用`i2c_transfer`函数进行数据传输,返回值表示成功传输的消息数量。 需要注意的是,上述代码适用于在用户空间中进行I2C数据传输,如果需要在内核驱动中使用`i2c_transfer`函数,可以参考内核源代码中相关的I2C驱动实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值