一、IIC概述
I2C(Intel Interface Circuit,简称IIC、I2C),是应用广泛的芯片间串行扩展总线。由飞利浦公司开发用于微控制器(MCU)和外围设备(从设备)进行通信的一种总线,属于一主多从(一个主设备(Master),多个从设备(Slave))的总线结构,总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其它设备。
1.1 基本结构
I2C总线总共只有两条信号线,串行时钟线SCL和串行数据线SDA。I2C总线上的各器件的数据线都接到SDA线上,I2C总线上的各器件的时钟线都接到SCL线上。
每个连接到I2C总线上的器件都有一个唯一的地址,扩展器件时受到器件数量的限制,I2C总线的基本结构如图所示:
当I2C总线空闲时,SDA和SCL均为高电平。由于连接到总线上的器件输出级必须是漏极开路或者集电极开路的,因此只要有一个器件任意时刻输出低电平,都将总线上的信号都将总线上的信号变低,即各器件的SDA和SCL都是“线与“的关系。
由于各器件输出端为漏极开路,则SCL和SDA线必须通过上拉电阻接正电源,以保证SDA和SCL在空闲状态被上拉到高电平。
关于是么是漏极开路,如果你已经忘记了数电技术,这里有个简单的介绍:
漏极开路输出需要接一个上拉电阻(上图中的R),可以利用改变上拉电源的电压,改变输出电平。上拉电阻是接在输出引脚和输出电压(上图中的Vcc)之间,可以获得高电平输出:
- 当内部N沟道场效应管关闭的时候,上拉电阻R会把输出拉到高电平,此时场效应管的漏电流将非常的小;
- 当内部N沟道场效应管导通的时候,它会把输出引脚拉到接近GND,此时的电流是根据欧姆定律计算的 (I = Vcc/R);
1.2 优缺点
I2C总线的优点:
-
简单性(I2C只有两条信号线)和有效性(根据SCL线上的时钟线来判断):带有I2C总线的接口的单片机都可直接与具有I2C总线接口的各种扩展器件(如存储器、I/O芯片、A/D、D/A、键盘、显示器、时钟、日历等)连接。由于I2C总线采用纯软件的寻址方法,无须片选线的连接,这样就大大的简化了总线的数量;
- 允许多主器件。任何能够进行发送和接收的设备都可以成为主总线,一个主控能够控制信号的传输和时钟频率,在任何时间点上只能有一个主控。在实际应用中,经常遇到的是以单一单片机为主器件,其他外围接口期间为从器件的情况;
I2C的缺点:
- 在标准的I2C普通模式下,数据的传输速率为100kbit/s,高速模式下可以达到400kbit/s;
-
I2C所接的外围器件的数量并不是无穷多的,总线上的扩展的期间数量是由限制的。总线上的扩展的器件数量并不是由电流负载决定的,而是由电容负载决定的。I2C总线上的每个器件的接口都有一定的等效电容,器件越多(扩展外围器件可以看作是并联在主器件的总线上的),电容值就越大,就会造成信号传输的延迟;
- 总线上允许接的器件数量以器件的电容量不能超过400pF(可以通过其他的方法增加总线的电容量),据此可以算出总线的长度和扩展外围器件的数量;
二、IIC通信协议
I2C总线在传送数据过程中一共有四种类型的信号,分别是起始信号,结束信号、应答信号以及有效数据。
2.1 起始信号
I2C通信的起始信号由主设备发起,SCL保持高电平,SDA由高电平变为低电平;只有在起始信号发送之后,其它数据才有效;
GPIO模拟代码:
void I2C_Start(void) { SDA_OUT(); I2C_SDA =1; delay_us(5); I2C_SCL =1; delay_us(5); I2C_SDA =0; delay_us(5); I2C_SCL =0; }
2.2 终止信号
I2C通信的终止信号由主设备发起,SCL保持高电平,SDA由低电平变为高低电平;随着终止信号的出现,所有外部操作就结束;
GPIO模拟代码:
void I2C_Stop(void) { SDA_OUT(); I2C_SDA =0; delay_us(5); I2C_SCL =1; delay_us(5); I2C_SDA =1; delay_us(5); I2C_SCL =0; }
2.3 应答信号
I2C总线在进行数据传送时,传送的字节数没有限制,但是每个字节长度必须为8位。
数据传送过程中,先传送最高位(MSB),接收端在收到有效数据后向对方相应的信号,发送端每发送一个字节数据(8位),在第9个始终周期释放数据线去接收对方的应答;因此一帧数据共有9位;
- 当SDA位低电平位有效应答(ACK),表示接收端已经接收到数据;
- 当SDA是高电平位无效应答(NAK),表示接收端没有接收成功;
主设备发送完数据需要等待从设备的应答,GPIO模拟:
// 0:接受失败 1:接收成功 u8 I2C_WaitAck(void) //等待来自从机的应答信号 { u16 time; SDA_IN(); I2C_SCL =0; delay_us(5); I2C_SDA =1; delay_us(5); I2C_SCL =1; delay_us(5); while(Read_SDA) { time++; if(time>=2500) { I2C_Stop(); return 0; } } I2C_SCL =0; return 1; }
主设备接收到从设备发送的数据后,需要向从设备发送方发送应答,GPIO模拟:
// ack:0不应答 1:应答 void I2C_Ack(u8 ack) { SDA_OUT(); I2C_SCL =0; delay_us(5); if(ack) I2C_SDA =0; else I2C_SDA =1; I2C_SCL =1; delay_us(5); I2C_SCL =0; delay_us(5); }
2.4 有效数据
I2C总线进行数据传送时,时钟信号SCL为高电平期间,数据线SDA上的数据必须稳定;只有在SCL上的信号为低电平时,SDA上的高电平或低电平状态才允许变化。
因为当SCL是高电平时,数据线SDA的变化被规定为控制命令(也就是前面的起始信号和终止信号)。
主设备向从设备发送发送一个字节数据,GPIO模型模拟:
void I2C_WriteData(u8 byte) { u8 i=0; SDA_OUT(); I2C_SCL =0; for(i=0;i<8;i++) { I2C_SDA =(byte&0x80)>>7; byte <<=1; delay_us(5); I2C_SCL =1; delay_us(5); I2C_SCL =0; delay_us(5); } }
主设备从从设备读取一个字节数据,GPIO模拟:
u8 I2C_ReadData(void) { u8 i=0; u8 data=0; SDA_IN(); I2C_SCL =0; for(i=0;i<8;i++) { I2C_SCL =1; data <<=1; data |=(u8)Read_SDA; delay_us(5); I2C_SCL =0; delay_us(5); } return data; }
三、主从设备通信过程
在前面我们提到过,I2C总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。
3.1 主设备向从设备写入数据
数据格式如下:
流程如下:
- 主设备发送START起始信号;
- 主设备发送从设备地址信息(I2C addr(7bit)和w操作0(1bit)),等待ACK确认信号;
- 从设备发送ACK确认信号;
- 主设备发送数据到从设备,一般发送的每个字节数据后会跟着等待接收来自从设备的响应(ACK);
- 数据发送完毕,主设备发起STOP终止信号;
3.2 主设备从从设备读取数据
数据格式如下:
流程如下:
- 主设备发送START信号;
- 主设备发送从机设备地址信息(I2C addr(7bit)和r操作1(1bit)),等待ACK确认信号;
- 从设备发送ACK确认信号;
- 主设备接收来自从设备的数据,一般接收的每个字节数据后会跟着向从设备发送一个响应(ACK);
- 主设备一般接收到最后一个数据后会发送一个无效响应(NACK),然后主设备发送停止(STOP)信号终止传输;
3.3 主设备向从设备读/写数据
在数据传输过程中,可能需要改变数据传送方向时;起始信号和从机地址都需要重复产生一次;
四、I2C通信的实现
4.1 I2C控制器
就是使用芯片上的I2C外设,也就是硬件I2C,它有相应的I2C驱动电路,有专用的I2C引脚,效率更高,写代码会相对简单,只要调用I2C的控制函数即可,不需要用代码去控制SCL、SDA的各种高低电平变化来实现I2C协议,只需要将I2C协议中的可变部分(如:从设备地址、传输数据等等)通过函数传参给控制器,控制器自动按照I2C协议实现传输,但是如果出现问题,就只能通过示波器看波形找问题。
4.2 GPIO模拟时序
软件模拟I2C比较重要,因为软件模拟的整个流程比较清晰,哪里出来bug,很快能找到问题,模拟一遍会对I2C通信协议更加熟悉。
如果芯片上没有I2C控制器,或者控制接口不够用了,通过使用任意IO口去模拟实现IIC通信协议,手动写代码去控制IO口的电平变化,模拟I2C协议的时序,实现I2C的信号和数据传输。
参考文章:
[1] IIC通信协议,搞懂这篇就够了
标签:SCL,通信协议,总线,SDA,I2C,器件,设备 From: https://www.cnblogs.com/zyly/p/17094178.html