一.I2C总线
I2C(内置集成电路)总线是由Philips开发的两线式串行总线,支持多主控模式,任何能够进行发送和接收的设备都可以成为主设备。
I2C是philips提出的外设总线。I2C只有两条线,一条串行数据线SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线。因此,I2C总线被非常广泛地应用在EEPROM,实时钟,小型LCD等设备与CPU的接口中。
总线空闲时,上拉电阻使SDA和SCL线都保持高电平。I2C设备上的串行数据线SDA接口电路是双向的,输出电路用于向总线上发送数据,输入电路用于接收总线上的数据。同样的,串行时钟线SCL也是双向的,作为控制总线数据传送的主机要通过SCL输出电路发送时钟信号,并检测总线上SCL上的电平以决定什么时候发送下一个时钟脉冲电平;作为接收主机命令的从设备需按总线上SCL的信号发送或接收SDA上的信号,它也可以向SCL线发送低电平信号以延长总线时钟信号周期。
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
在开始信号之后i2c主设备便会开始发送数据,在发送数据期间,SCL为高时SDA必须保持稳定无变化,因为SCL为高时会采样数据。若此时SDA变化,可能导致误发结束信号而产生终止。也就是说SCL高,SDA保持稳定,则数据有效,SDA的改变只能发生在SCL的低电平期间。当然接收器每接收一个字节数据都会产生一个ACK回应信号,表示已经收到数据。
开始位和停止位都由I2C主设备产生。在选择从设备时,如果从设备是采用7位地址,则主设备在发起传输过程前,需先发送1字节的地址信息,前7位为设备地址,最后一位为读写标志。之后,每次传输的数据也是一个字节,从MSB位开始传输。每个字节传输完后,在SCL的第9个上升沿到来之前,接收方应该发出一个ACK位。SCL上的时钟脉冲由I2C主控方发出,在第8个时钟周期之后,主控方应该释放SDA,I2C总线的时序如下:
二、Linux下的I2C驱动体系结构
在linux系统中,I2C驱动由以下三部分组成:
1.I2C核心:
提供了I2C总线驱动和I2C设备驱动的注册和注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
增加/删除i2c_adapter
int i2c_add_adapter(struct i2c_adapter *adapter)
int i2c_del_adapter(struct i2c_adapter *adap)
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
void i2c_del_driver(struct i2c_driver *driver)
i2c_client依附/脱离
int i2c_attach_client(struct i2c_client *client)
int i2c_detach_client(struct i2c_client *client)
I2C传输,发送和接收
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
2.I2C总线驱动:
I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以集成在CPU内部。I2C总线驱动主要包括i2c_adapter数据结构和i2c_algorithm数据结构以及控制i2c适配器产生通信信号的函数。经由I2C总线驱动的代码,可以以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。
一个总线驱动用于支持一条特定的I2C总线的读写。一个总线驱动通常需要两个模块,struct i2c_adapter和struct i2c_algorithm来描述
I2C_adapter:构造一个对I2C core层接口的数据结构,并通过接口函数向I2C core注册一个控制器adapter。
i2c_algorithm:主要实现对I2C总线访问通信的具体算法。
3.I2C设备驱动:
I2C设备驱动是对I2C硬件体系结构中设备端的实现,I2C设备挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。I2C设备驱动主要包括数据结构i2c_driver和i2c_client,这需要具体设备来实现其中的成员函数。
i2c_driver结构对应一套具体的驱动方法,例如:probe、remove、suspend等,需要自己申明。i2c_client数据结构由内核根据具体的设备注册信息自动生成,设备驱动根据硬件具体情况填充。具体使用下面介绍。
I2C 设备驱动具体实现放在在/drivers/i2c目录下chips文件夹。
i2c-dev.c:提供了用户层对I2C设备的访问,包括open,read,write,ioctl,release等常规文件操作,我们可以通过open函数打开 I2C的设备文件,通过ioctl函数设定要访问从设备的地址,然后可以通过 read和write或者ioctl函数完成对I2C设备的读写操作。
I2C_client:对应于真实的物理设