最近参加了TI公司赞助的电子大赛,学到了很多的东西,想着写出来分享一下,于是也就有了这篇博文。
首先来谈谈IIC(Inter-Integrated Circuit, 又叫I2C, I²C)协议,它是一个单主机多从机的半双工通信协议,所有设备通过两根信号线进行连接,一根是SDA(Serial Data Line, 串行数据线),另一根是SCL(Serial Clock Line, 串行时钟线),这两根线缆需要通过电阻被上拉至电源电压。并且系统之间需要进行共地。这也表明IIC总线仅需要三根线缆就可以进行设备间的通信。下图可以表示IIC设备之间的连接方式。
IIC总线的优点显而易见,它可以将许多设备穿在极少的线缆上,并对它们进行高效的管理和使用。单个IIC模块可以工作在两种不同的模式上,一个是主机模式,它可以产生时钟信号并且主动与其它从机通信,另一个是从机模式,它便是等待主机发来的地址,当与自己的地址想匹配后便在回复ACK之后继续进行数据接收或发送。
IIC中最基本的问题就是发送和接收数据的过程。IIC总线要求在数据传输的过程中,每当SCL为高电平时,SDA上电平必须保持不变,当SCL为低电平时,SDA上的电平可以发生改变。但是有两种情况例外,一种是开始信号,它由在SCL为高电平的时候SDA产生下降沿来发送,另一种是结束信号,它由在SCL为高电平时候SDA产生上升沿来发送。
首先IIC在发送数据前要先发送开始信号,这个时候在时钟线(SCL)为高电平时,数据线(SDA)发生了从高电平到低电平的跳变。在紧接着的下一个时钟线为高的时候即为第一位数据,从1-8八个数据依次发送完毕后的紧接着的一个时钟周期为从机的确认位,如果这时数据线被从机拉低表明从机已接收到数据。这时主机便可继续依次发送下八位数据,直到发送结束。
IIC协议在进行数据传输的时候需要在第一帧数据中发送设备的地址,设备的地址一般可以从手册上查到。将其上移一位,形成高七位的七位设备地址,最低位填入0表示写入从机数据,填入1表示读取从机数据。但是IIC协议当中读取操作往往比写入操作更为困难,因为当IIC需要从从机读取数据的时候,往往需要先以写入模式写入一些操作命令,再对从机返回值进行分析和调试。
IIC总线在通信协议中基本可以分为以下几个步骤:
1.写数据:通过IIC发送:开始->地址+写->写入命令->写入数据->结束。
2.读数据:通过IIC接收:开始->地址+写->读取命令->开始->地址+读->设备返回数据->结束。
因为读数据的时候需要先行写入读取命令才可以正确的读出数据,所以通过IIC读数据多了一点工序。
在附上的IIC函数库当中,仅有两个函数,一个是IIC_Write,另一个是IIC_Read,通过配置好头文件中的Config,便可正常使用。函数声明如下:
void IIC_Write(unsigned char const dev_add,unsigned char const *write_cmd,unsigned char const cmd_size,unsigned char const *data,unsigned char const data_size); void IIC_Read(unsigned char const dev_add,unsigned char const *read_cmd,unsigned char const cmd_size,unsigned char *data,unsigned char const data_size);
在IIC_Write函数中,输入依次为IIC设备地址,IIC写入命令数组,IIC写入命令长度,IIC写入数据数组,IIC写入数据长度。两个数组均用const指针传入,并且用户应该保证指针后长度范围内的所有位应该有意义。在IIC_Read函数中,输入依次为IIC设备地址,IIC读取命令数组,IIC读取命令长度,IIC读取数据存储地址,IIC读取数据长度。通过IIC发送至主机的数据将由IIC_Read捕捉并获取。当两个函数中任意一个数组需要输入空数组的时候,则仅需要将参数的位置上输入EMPTY,并将其长度置为0即可。
附件:
IIC –IIC库源码。
*注:图片均来自维基百科。