电子说
废话
I2C其实肝的我挺难受的,通讯协议这种规范往往可以抠出很多的细节,看了波叔的文章《万变不离其宗之I2C总线要点总结》,很详细。我打赌我还不会I2C,因为涉及到很多技术细节,在实际项目中往往是会被忽略的问题,于是结合自己以前的项目经验,简单再总结一下I2C,由于认知偏差,写完之后,长吁一口气,感觉自己好像懂了。
目录
背景
硬件层
数据传输协议
实际上如何工作?
单个主设备连接多个从机
多个主设备连接多个从机
总结
背景
I2C(Inter-Integrated Circuit),中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,是由飞利浦公司在1980年代初设计的,方便了主板、嵌入式系统或手机与周边设备组件之间的通讯。由于其简单性,它被广泛用于微控制器与传感器阵列,显示器,IoT设备,EEPROM等之间的通信。
I2C最重要的功能包括:
只需要两条总线;
没有严格的波特率要求,例如使用RS232,主设备生成总线时钟;
所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址;
I2C是真正的多主设备总线,可提供仲裁和冲突检测;
传输速度;
标准模式:Standard Mode=100 Kbps
快速模式:Fast Mode=400 Kbps
高速模式:High speed mode=3.4 Mbps
超快速模式:Ultra fast mode=5 Mbps
最大主设备数:无限制;
最大从机数:理论上是127;
以上是I2C的一些重要特点,下面会进一步对I2C进行介绍。
硬件层
I2C协议仅需要一个SDA和SCL引脚。SDA是串行数据线的缩写,而SCL是串行时钟线的缩写。这两条数据线需要接上拉电阻。
设备间的连接如下所示:
使用I2C,可以将多个从机(Slave)连接到单个主设备(Master),并且还可以有多个主设备(Master)控制一个或多个从机(Slave)。
假如希望有多个微控制器(MCU)将数据记录到单个存储卡或将文本显示到单个LCD时,这个功能就非常有用。
I2C总线(SDA,SCL)内部都使用漏极开路驱动器(开漏驱动),因此SDA和SCL 可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个上拉电阻,默认情况下将其保持在高电平;
上拉电阻的值取决于许多因素。德州仪器TI 建议 使用以下公式来计算正确的上拉电阻值:
其中 是逻辑低电压;
是逻辑低电流;
是信号的最大上升时间;
是总线(电线)电容;
具体如下所示:
根据上表,这里不难发现需要在做电阻选择需要满足几个条件;
灌电流 最大值为;
另外I2C总线规范和用户手册还为低电平输出电压设置了最大值为0.4V
所以根据上述公式可以计算,对于5V的电源,每个上拉电阻阻值至少1.53kΩ,而对于3.3V的电源,每个电阻阻值至少967Ω。
如果觉得计算电阻值比较麻烦,也可以使用典型值 4.7kΩ。
上述推导过程可以参考 TI的文档《I2C Bus Pullup Resistor Calculation》 https://www.ti.com/lit/an/slva689/slva689.pdf
最终在调试的时候,当我们测量SDA或SCL信号并且逻辑LOW上的电压高于0.4V时,我们就知道可以知道灌电流太高了;
当然,这并不意味着每当灌电流超过3mA时,设备就会立即停止工作。但是,在操作超出其规格的设备时,应始终小心,因为它可能导致通信故障,缩短其使用寿命甚至甚至永久损坏设备。
数据传输协议
主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输0和1的串行数据。串行数据序列的结构可以分为,开始条件,地址位,读写位,应答位,数据位,停止条件,具体如下所示;
开始条件
当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作;
先将SDA线从高压电平切换到低压电平;
然后将SCL从高电平切换到低电平;
在主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位。
具体如下图所示;
地址位
通常地址位占7位数据,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址;
I2C还支持10位寻址;
读写位
该位指定数据传输的方向;
如果主设备需要将数据发送到从设备,则该位设置为 0;
如果主设备需要往从设备接收数据,则将其设置为 1 。
ACK / NACK
主机每次发送完数据之后会等待从设备的应答信号ACK;
在第9个时钟信号,如果从设备发送应答信号ACK,则SDA会被拉低;
若没有应答信号NACK,则SDA会输出为高电平,这过程会引起主设备发生重启或者停止;
数据块
传输的数据总共有8位,由发送方设置,它需要将数据位传输到接收方。
发送之后会紧跟一个ACK / NACK位,如果接收器成功接收到数据,则设置为0。否则,它保持逻辑“ 1”。
重复发送,直到数据完全传输为止。
停止条件
当主设备决定结束通讯时,需要发送开始信号,需要执行以下动作;
先将SDA线从低电压电平切换到高电压电平;
再将SCL线从高电平拉到低电平;
具体如下图所示;
实际上如何工作?
第一步:起始条件
主设备通过将SDA线从高电平切换到低电平,再将SCL线从高电平切换到低电平,来向每个连接的从机发送启动条件 :
第二步:发送从设备地址
主设备向每个从机发送要与之通信的从机的7位或10位地址,以及相应的读/写位;
第三步:接收应答
每个从设备将主设备发送的地址与其自己的地址进行比较。如果地址匹配,则从设备通过将SDA线拉低一位以表示返回一个ACK位;
如果来自主设备的地址与从机自身的地址不匹配,则从设备将SDA线拉高,表示返回一个NACK位;
第四步:收发数据
主设备发送或接收数据到从设备;
第五步:接收应答
在传输完每个数据帧后,接收设备将另一个ACK位返回给发送方,以确认已成功接收到该帧:
第六步:停止通信
为了停止数据传输,主设备将SCL切换为高电平,然后再将SDA切换为高电平,从而向从机发送停止条件;
单个主设备连接多个从机
I2C总线上的主设备使用7位地址对从设备进行寻址,可以使用128()个从机地址。
请使用4.7K上拉电阻将SDA和SCL线连接到Vcc;
多个主设备连接多个从机
多个主设备可以连接到一个或多个从机;
当两个主设备试图通过SDA线路同时发送或接收数据时,同一系统中的多个主设备就会出现问题。
为了解决这个问题,每个主设备都需要在发送消息之前检测SDA线是低电平还是高电平;
如果SDA线为低电平,则意味着另一个主设备可以控制总线,并且主设备应等待发送消息。
如果SDA线为高电平,则可以安全地发送消息。
要将多个主设备连接到多个从机,请使用下图,其中4.7K上拉电阻将SDA和SCL线连接到Vcc:
总结
本文主要介绍I2C的入门基础知识,从I2C协议的硬件层,协议层进行了简单介绍;作者能力有限,难免存在错误和纰漏,请大佬不吝赐教。
责任编辑:xj
原文标题:I2C基础知识入门
文章出处:【微信公众号:玩转单片机】欢迎添加关注!文章转载请注明出处。
全部0条评论
快来发表一下你的评论吧 !