Yuhang Zheng

第二十九节、i2c总线

N 人看过

本节用于介绍i2c总线

一、I2C简介

I2C是很常见的一种总线协议,I2C是NXP公司设计的,I2C使用两条线在主控制器和从机之间进行数据通信。一条是SCL(串行时钟线),另外一条是SDA(串行数据线),因为I2C这两条数据线是开漏输出的,所以需要接上拉电阻,总线空闲的时候SCL和SDA处于高电平。I2C总线标准模式下速度可以达到100Kb/S,快速模式下可以达到400Kb/S。

如果大家之前玩过51单片机,肯定对模拟I2C时序这个操作并不陌生,但是在Linux上,还需要我们继续来模拟I2C的时序吗,答案是不需要的,cpu会自带I2C控制器,有了这个I2C控制器之后,我们就不用在来取模拟时序了,我们只需要关系怎么把数据写到寄存器和怎么从寄存器读数据即可,具体的时序都是由I2C控制器来帮我们自动完成。

Linux把I2C控制器抽象成了一个i2c_adapter,我们只要来分配这个i2c_adapter,就可以得到一个l2C控制器。

我们可以先来体验一下,在Linux上操作l2C是多么的容易,我们可以先来看一下我们的系统里面都有哪些l2C的节点,这里以终结者的开发板为例。如下所示:

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

Linux有一个非常重要的概念叫一切皆文件,那么我们能不能在应用层通过open这些节点来操作l2C来跟外设I2C通信的芯片进行一个数据交流呢?当然是可以的,我们来一起看一下,这里我们以操作时钟芯片RX8010为例。

那我们怎么在应用层操作l2C呢?应用层操作l2C是以数据包进行交流的,所有我们在应用层就要进行封包的操作。

数据包对应的结构体是i2c_rdwr_ioctl_data

文件位置路径:include/uapi/linux/i2c-dev.h

/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
        struct i2c_msg __user *msgs;    /* 我们要发送的数据包的指针 */
        __u32 nmsgs;                    /* 我们要发送的数据包的个数 */
};

然后是i2c_msg结构体的定义

文件位置路径:include/uapi/linux/i2c.h

struct i2c_msg {
        __u16 addr;             /* 从设备的地址 */
        __u16 flags;            /* 读写标志位,如果是1,则为读,反之为0,则为写 */
#define I2C_M_RD                0x0001  /* read data, from slave to master */
                                        /* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN               0x0010  /* this is a ten bit chip address */
#define I2C_M_RECV_LEN          0x0400  /* length will be first received byte */
#define I2C_M_NO_RD_ACK         0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK        0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR      0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART           0x4000  /* if I2C_FUNC_NOSTART */
#define I2C_M_STOP              0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
        __u16 len;              /* 为buf的大小,单位是字节,当flags为1是,buf就是我们要接收的数据,当flags为0时,就是我们要发送的数据。 */
        __u8 *buf;              /* pointer to msg data */
};