从零开始的stm32旅途--I2C通信协议(1)

最近复习了I2C通信协议,撰写这篇博客,一是为复习巩固,二是分享自己的一些感悟,如果能够帮助一些朋友那就再好不过了

I2C的基本概念

在之前的学习当中,我们已了解到串口通信是一种点对点,一对一的通信方式,而这样导致的后果就是每多一台设备与单片机进行串口通信,就需要多占用一对引脚,多占用一个USART外设;例如:我们常用的stm32F10c8t6就只有3个USART外设,它最多同时与3台设备进行通信,如果想要更多的设备进行通信,就可以考虑使用I2C通信———I2C是嵌入式环境下,多设备通信中性价比之选。
I2C通信,意译过来就是芯片集成电路之间的通信。
注意:I2C通信时芯片之间的相互通信,通信双方按照各自的程序,基于I2C通信协议完成通信。不要把I2C通信理解为谁控制谁,双方都是芯片,都有烧录好的程序,双方都基于同样的通信协议,只要在双发约定好的时间,做约定好的事情,通信就完成了。对于我们而言,单片机由我们控制,单片机的I2C的通信程序也是由程序员完成的,而与单片机通信的设备,它有烧录好的I2C通信程序,我们不需要关系它的程序的具体实现,只要能完成通信即可。

I2C是一种总线式的通信方式,它的硬件电路设计是一种总线式的设计,而且I2C的总线设计很标准,是典型的总线式通信方式。

通信的总体式电路设计,使得通信中的设备,可以把自身引脚都挂在总线上,这种总线式设计,使得通信的电路设计更加简单,降低了走线复杂度。而且对单片机而言,即便与它进行通信的设备很多,也只需要占用少量的引脚即可,不需要像串口通信一样,每多一台设备,就要占两个引脚(当然引脚占用少了,外设也就占用的少了)在多设备的通信环境中,总线的设计使得接线变得更加简单,减少了引脚和外设的资源的占用,使得这种设计方式成为通信方式的主流
以下就是I2C通信的总线设计电路
image

I2C通信是单工,半双工还是全双工?

I2C通信和串口通信一样,都是串行通信,通信过程中,都是在数据线上一个BIT一个BIT的传输,发送端拉高数据线,就是发送1,发送端拉低数据线,就是发送0。串口通信有两条独立的数据线,所以它是全双工的,而I2C只有一条数据线,即SDA总线,在I2C通信当中,谁控制了SDA总线,谁就有能力发送数据,所以I2C不是单工,而是双工,但是由于只有一条SDA总线,所以它是半双工的。
SDA总线:serial data,串行数据线,谁来控制这条总线就意味着谁发数据,I2C通信只有这一条数据线。
SCL总线:serial clock,串行时钟线,I2C通信的整个流程都由时钟信号来控制,总线上的设备都共享同一个时钟信号。

I2C通信是一种“主从模式”设计的通信协议。

实际上多设备通信中,大多都是主从模式,在通信协议中,始终掌握着整个通信的流程的,及控制SCL线的称为主机,所以在学习中我们都已单片机作为主机,其他设备作为从机,理论来说,I2C总线上的设备都可以作为主机,但使用I2C通信,大概率不会使用切换这种语法,过于复杂,多数情况下我们都不切换主机进行使用。主机可以主动发送数据给从机,从机接受数据,这称之为“I2C的写”,从机在主机的要求下发送数据给主机,这称之为“I2C的读”,从机不能主动发送数据给主机。即在I2C通信中,任何通信操作都能必须由主机发起。

I2C通信是多设备通信方式,我们如何在多设备找到我们需求的哪一个设备,从而进行通信?

I2C总线上的从机,都有着唯一标识,称之为“从机地址。slave address”,任何I2C通信,都是由主机发起的,主机发起一次I2C通信,总是从发送寻址地址开始,主机通过SDA总线发送寻址字节,寻找目标地址,这个总是I2C通信中首个发送发送的字节,SDA总线的控制器,在通信一开始,是在主机中,由主机发起寻址,主机发送数据。
寻址地址(8位):7位从机地址+1位读写标志位。
7位从机地址,是由生产厂商在生产设备时一次性烧录设置的。某台从机设备,它的从机地址总是固定的(或者或是大多数位,少数位可选)
从机地址有7位,理论上来说,有2^7=128种可能性,即最大支持的设备为128个设备,但是I2C通信在实际使用中,往往会预保留一些从机地址,实现一些特殊用途。最典型的一个例子,就是0这个从机地址,它是I2C通信的广播地址,用于主机一次性发送数据给总线上的所有设备,所以排除掉一些用作特殊用途的从机地址,I2C通信最多可支持100+的设备,在同一总线上进行通信。
1位的读写标志位:
一次I2C通信,我们不仅要找到从机地址,还需要告诉从机设备,我们这一次通信需要读还是写,所以这1位读写标志位就和从机地址组合在一起,构成寻址地址,通过SDA总线发送。
读标志位:1
写标志位:0
比如0.96存OLED显示屏,支持I2C通信,它从机地址是:0111 100,如果单片机要与它通信,并且要求OLED发送数据给主机(读),那么寻址地址就是:0111 1000,转换成16进制就是0X78。一定要记住通信的第一个字节就是寻址地址!SDA总线一开始都是被主机所控制。

I2C通信的总线设计,为什么这么设计?

image
依旧是这张图片,我们前面提到了总线控制权,SDA总线谁控制就是谁发送数据,SCL时钟线始终被主机所控制,那么到底什么是控制权,控制权又是如何切换的?
在解决这些问题之前,我们先谈一谈一个重要的约定:在I2C通信中,输出模式都是开漏模式,只能输出高阻态或者是低电平。为什么会这样,我们先按下布表。
逻辑线与(重点!),它是I2C通信总线设计的核心概念,I2C总线之所以这么设计,目的是为了实现逻辑线与。
与是逻辑运输符,参与&运算的变量,必须全部都是1,结果才是1,只要任意变量是0,结果就是0.

逻辑线与:

指的是两条总线(SDA和SCL),总线的最终电平状态,靠所有接入总线的引脚电平来决定:
1.只要接入总线的所有引脚,都设置为1(高组态),然后依靠上拉电阻的上拉作用,总线表现为高电平,这个过程就是1(高阻态)&1&1&1...&1 = 1(高电平,上拉电阻得到)
2.只要任意的总线的任意引脚,设置为0(低电平),总线就会表现为低电平,这个过程就是1(高阻态)&1&1&0...&1 = 0(低电平)
I2C总线的电平状态表现,和逻辑运算符与计算结果是一样的,所以称这种总线设计为逻辑线与。

I2C总线控制权,到底什么是控制权?

控制权就是可以随时拉高或者是拉低这条总线,没有控制权的设备,必须把自身对应引脚设置为1(高阻态),有总线控制权的设备,就可以将自身对应的引脚设置1,即拉高总线,拉低亦是如此。
所以,有没有控制权,核心在于,这台设备能不能把自身对应引脚设置为0,可以设置为0,就说明这台设备有控制权。
当然,主机完全控制SCL总线,从机的所有SCL引脚必须全部设置为1,且不能切换,而SDA总线的控制权既可以切换控制权,但是在I2C通信的一开始,SDA总线先由主机控制。

I2C通信流程

即学习I2C通信的时序结构,时序过程,时序图
image
I2C通信规定:SCL和SDA总线,两条总线都是高电平,才表示通信的空闲状态,任意总线的拉低,都不属于空闲状态。
推论:一开始通信肯定都处于空闲状态,这就意味着接入总线的设备,在一开始的初始状态都是高阻态,所有在软I2C模拟时候,务必初始化引脚时候设置为高阻态。

I2C通信时同步通信,是受时钟信号控制,那么时钟信号是如何控制I2C通信流程呢?

image
这个就是时钟信号,周期性变化的方波,一个时钟周期,是由一个低电平和一个高电平组成的。I2C通信规定:一个时钟周期的高电平时间内属于工作时间,一个时钟周期的低电平时间内属于休息时间/准备时间。
注意:在通信过程中,所有的重要的通信结点都是发生在工作时间,也就是高电平时期。
举一个简单的例子,下图是简化部分的时序图,描述的是,I2C发送数据过程中两条总线的电平状态,该时序图仅考虑数据的发送,其他因素都不开率:
image
这张时序图,就简单描述了通过SDA中的两个Bit,很显然,发送的数据是1,0。

I2C通信过程中的数据发送与接收

发送端,在低电平的休息时间内,也叫准备时间,由数据端准备要发送的数据,所以由电平变化的情况,如果数据端要发送1,就要拉高SDA总线。要发送0,就要拉低SDA总线,所以休息时间,对于数据的发送端而言,其实是准备时间,用于准备下一个高电平工作时间内需要发送的数据。接收端在休息时间内,是真正意义上的休息,什么都不用做。I2C通信,1个时钟周期发送1个bit的数据,所以I2C通信,影响它通信速率的最主要因素就是时钟信号的频率时钟频率越高,I2C通信越快,否则通信速率越慢。

I2C通信是多设备总线式同步串行通信当中,典型的低速通信协议。

为什么呢?因为I2C总线依靠上拉电阻拉高电平,但这个过程很缓慢,需要一个固定的不短的时间如果I2C通信过快,使得上拉电阻来不及拉高总线电平,就会导致通信失败,所以I2C通信,它的速度基本上串口通信半斤八两,都是典型的低速通信协议。当然,上面讲的是I2C比较慢的核心因素,当然还有一些其它的影响因素,后面再讲。

总结:

I2C总线由SDA(数据线)与SCL(时钟线)组成,所有主从设备共享这两条线,形成“多设备挂载"的总线结构。
通信中所有设备的SDA和SCL引脚,都需要设置为开漏输出模式。
两条总线的电平状态,受所有设备引脚“逻辑线与”的共同决定一一任一拉低(0)即为低电平,全部释放(1)才为高电平。
SCL总线由主机(单片机)独占控制,用于产生时钟信号,严格控制通信时序。
SDA总线控制权,在通信时根据发送端角色动态切换,主机写(主机发送)时主机控制SDA总线,主机读(从机发送)时从机控制SDA总线。
所谓总线控制权,指的是某一设备具有对总线电平的主动控制能力,即其对应引脚可以在0和1(低电平与高阻态)之间切换,而其他设备必须将对应引脚置为高阻态(输出1),以释放总线控制权。
I2C通信把两条总线都为高电平状态,设置为通信的空闲状态。任一总线被拉低,表示通信已开始,或通信正在进行中。
I2C 是同步通信协议,所有设备共享主机生成的时钟信号。9每个时钟周期(高电平+低电平)被划分为:
a.休息时间(SCL 低电平):为工作时间做准备,发送端控制拉高SDA总线(准备发1),也可以控制拉低SDA总线(准备发0)
b.工作时间(SCL 高电平):控制通信的关键节点。比如通信的开始与结束,数据发送与接收采集等重要节点,都必须在工作时间内发生。
如果是发送接收数据,SDA总线必须在整个工作时间内,保持电平状态不变。

posted @ 2026-06-17 14:32  无秋33  阅读(25)  评论(0)    收藏  举报