为什么read的时候要使用两个i2c_msg,而读只需要一个?
这与时序图有关
一 、指定地址读的时序图
设备地址为0x50的eeprom,要读取它里面存储地址为0x10的两个字节为例
1.设置内部地址
第一个i2c_msg是一个写操作,用于设置EEPROM内部地址指针,指向你要读取的地址0x10。这个消息会包含设备地址(0x50)和要写入的内部地址(0x10)。
2.读取数据
第二个i2c_msg是一个读操作,用于从EEPROM中读取数据。此时,EEPROM已经知道了要读取的地址(因为刚才设置了内部地址指针),所以这个消息会包含设备地址(0x50)和用于存储读取数据的缓冲区。
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
int read_eeprom(struct i2c_client *client, u8 addr, u8 *data, size_t len) {
int ret;
struct i2c_msg msgs[2];
u8 buf[1];
// 第一个消息:设置内部地址指针
buf[0] = addr;
msgs[0].addr = client->addr;
msgs[0].flags = 0; // 写操作
msgs[0].len = 1;
msgs[0].buf = buf;
// 第二个消息:读取数据
msgs[1].addr = client->addr;
msgs[1].flags = I2C_M_RD; // 读操作
msgs[1].len = len;
msgs[1].buf = data;
// 发送I2C消息
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0) {
pr_err("I2C transfer failed: %d\n", ret);
return ret;
}
return 0;
}
二、指定地址写的时序图
写入数据到EEPROM只需要一个i2c_msg的原因是,在一个写操作中,可以同时发送内部地址和数据。这与读取数据的过程有所不同,读取操作通常需要分两步进行。
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
int write_eeprom(struct i2c_client *client, u8 addr, const u8 *data, size_t len) {
int ret;
u8 buf[256]; // 假设最多写256字节,实际大小视情况而定
// 构造要发送的数据,先是内部地址,然后是数据
buf[0] = addr;
memcpy(&buf[1], data, len);
// 构造I2C消息
struct i2c_msg msg = {
.addr = client->addr,
.flags = 0, // 写操作
.len = len + 1, // 数据长度(地址+数据)
.buf = buf
};
// 发送I2C消息
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret < 0) {
pr_err("I2C transfer failed: %d\n", ret);
return ret;
}
return 0;
}