I2C子系统

I2C协议

I2C协议运用已经非常广泛,直接看图,一图胜前言。

d991ae199fd76aac20e5d4d0abbe51ec.png

I2C设备驱动数据处理

Linux内核代码:drivers\i2c\i2c-core.c

数据处理函数: i2c_transfer

/**

* i2c_transfer - execute a single or combined I2C message

* @adap: Handle to I2C bus

* @msgs: One or more messages to execute before STOP is issued to

*terminate the operation; each message begins with a START.

* @num: Number of messages to be executed.

*

* Returns negative errno, else the number of messages executed.

*

* Note that there is no requirement that each message be sent to

* the same slave address, although that is the most common model.

*/

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

使用i2c_transfer函数发送数据之前要先构建好i2c_msg 。

i2c_msg 结构体定义在文件 include/uapi/linux/i2c.h

struct i2c_msg {

__u16 addr;/* slave address*/

__u16 flags;

#define I2C_M_RD0x0001/* read data, from slave to master */

/* I2C_M_RD is guaranteed to be 0x0001! */

#define I2C_M_TEN0x0010/* this is a ten bit chip address */

#define I2C_M_RECV_LEN0x0400/* length will be first received byte */

#define I2C_M_NO_RD_ACK0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_IGNORE_NAK0x1000/* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_REV_DIR_ADDR0x2000/* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_NOSTART0x4000/* if I2C_FUNC_NOSTART */

#define I2C_M_STOP0x8000/* if I2C_FUNC_PROTOCOL_MANGLING */

__u16 len;/* msg length*/

__u8 *buf;/* pointer to msg data*/

};

以读取 I2C 设备寄存器数据为例:

(参考正点原子)

int ret;

struct i2c_msg msg[2];

/* msg[0],第一条写消息,发送要读取的寄存器地址 */

msg[0].addr = addr; /* I2C 设备地址 */

msg[0].flags = 0; /* 标记为发送数据 */

msg[0].buf = ® /* 读取的首地址 */

msg[0].len = 1; /* reg 长度 */

/* msg[1],第二条读消息,读取寄存器数据 */

msg[1].addr = addr; /* I2C 设备地址 */

msg[1].flags = I2C_M_RD; /* 标记为读取数据 */

msg[1].buf = val; /* 读取数据缓冲区 */

msg[1].len = len; /* 要读取的数据长度 */

ret = i2c_transfer(adapter, msg, 2);

向 I2C 设备寄存器写入数据:

(参考正点原子)

int ret;

u8 b[256];

struct i2c_msg msg;

struct i2c_client *client = (struct i2c_client *)

dev->private_data;

b[0] = reg; /* 寄存器首地址 */

memcpy(&b[1],buf,len); /* 将要发送的数据拷贝到数组 b 里面 */

msg.addr = addr; /* I2C 设备地址 */

msg.flags = 0; /* 标记为写数据 */

msg.buf = b; /* 要发送的数据缓冲区 */

msg.len = len + 1; /* 实际数据长度 + 寄存器地址长度*/

ret = i2c_transfer(client->adapter, &msg, 1);

Linux内核对i2c_transfer进一步封装,形成两个API函数分别用于I2C数据的接收和发送操作 。代码位于:drivers\i2c\i2c-core.c

i2c_master_recv

/**

* i2c_master_recv - issue a single I2C message in master receive mode

* @client: Handle to slave device

* @buf: Where to store data read from slave

* @count: How many bytes to read, must be less than 64k since msg.len is u16

*

* Returns negative errno, or else the number of bytes read.

*/

int i2c_master_recv(const struct i2c_client *client, char *buf, int count)

i2c_master_send

/**

* i2c_master_send - issue a single I2C message in master transmit mode

* @client: Handle to slave device

* @buf: Data that will be written to the slave

* @count: How many bytes to write, must be less than 64k since msg.len is u16

*

* Returns negative errno, or else the number of bytes written.

*/

int i2c_master_send(const struct i2c_client *client, const char *buf, int count)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐