I2C (IIC) 通信协议的原理
综述
I2C通信协议是一种主从式的通信协议,通信双方分为主机和从机,主从机之间通过SCL (Serial Clock Line,串行时钟线) 和 **SDA (Serial Data Line,串行数据线)**两根信号线进行连接,是一种同步式通信协议(由主机的SCL同步双方频率)。主机可以同多个从机进行通信,每个从机有各自的地址进行区分。
信号线 (SCL, SDA)
I2C通信中有两根信号线参与: SCL信号线用于传输从主设备发送出的时钟信号源,实现同步通信。 SDA信号线用于数据的传输,是半双工的,SDA可以将数据由主机传输到从机,也可以由从机传输到主机,但是同一时间只能进行单向的传输,因此是半双工的。 信号线可以通过并联的方式让主机同时与多个从设备建立连接,这种一对多,采用了如SCL,SDA这样的共享信道的协议就是一种总线协议。 PS: 众所周知,这里参与通信的电信号是以高低电平来区分1和0的,而在电路中,I2C中总线实现高低电平的方式是开漏输出模式,也就是:电路输出的是低电平,当需要输出高电平时,通过一个上拉电阻形成高阻态来输出高电平。
主从设备
主设备(Master): 用于发起和终止通讯,并产生用于同步的时钟信号。 从设备(Slave): 用于响应主设备,每个从设备都有属于自己的唯一的7位或者10位的地址。 (小声BB: 为什么从设备不叫Servant() )
通信过程
前面我们说过,I2C协议通过两根信号线实现,SCL输出时钟信号,SDA用于输出数据。 一次通信,都会有以下三个过程:通信开始,传输数据,通信结束 这三个过程在I2C中的实现过程如下:
通信开始
当主机要发送通信开始的信号前,SCL和SDA都处于高电平状态,这样的状态标志着总线空闲可用。 当主机要开始发送通信开始的信号时,SDA会被拉低到低电平,产生一个由高到低的电平的跳变信号,这样的电平信号(SCL处于高电平,SDA由高到低)就是通信开始的标志。 当从机接收到这个信号后,所有的从机就会准备开始接受由主机发来的第一条消息。
第一条消息 (はじめまして)
主机会发送一条包含需要进行通信的从设备的地址和一位读(1)/写(0)指令的消息,从设备接收到消息后将其中的地址与自己的地址进行比对,找到需要通信的从设备,并进入读/写状态。
主机发送消息时的具体原理: 我们再看回典中典之SCL&SDA,在发送出那个“通信开始”的信号之后,SCL就会输出固定频率的高低电平信号,SCL上电平的高和低标志着主机和从机面对数据时的行为:
- 当SCL为低电平时,主机改变SDA上的电平高低来进行数据的写入(一次写入一位)。
- 当SCL为高电平时,从机接收SDA上的电平,根据电瓶高低接收SCL低电平时主机在SDA上写入的一位数据。
应答信号 (ACK/NACK)
当主机发送完8位数据(如果地址是10位的话就是分两次发送)后,主机会停止驱动SDA线,这时候SDA线上的电平由低变高。从设备接收到地址并进行比对确认匹配后,会将此时为高电平的SDA线拉低,表示从设备已接收到消息并完成地址比对,此时正好是SCL上的第9个脉冲(前面主机发送8位数据耗费了8个脉冲),当第9个脉冲结束后,SDA又会被释放到高电平,用于主机的数据写入。
数据传输
在第一次信号发出后,主机进行写(向从机发送数据)和读(从机向主机发送数据)操作。
当主机进行写操作时,我们上面已经介绍过具体的电平情况。 当主机从“写”变为“读”操作时:主机会再次发送那个通信开始前的起始信号,但是会把最后一位从“写”改为“读”,从机响应与上一致。 当从机对主机进行“写”操作时:
- SDA的电平高低由从机控制,SCL依然由主机发出。
- “写”操作中的规则倒转:
- 当SCL为低电平时,从设备改变SDA上的电平高低,准备好要发送的数据位。
- 当SCL为高电平时,从设备必须保持SDA上的电平稳定,此时主机来读取这一位数据。
- 主机接收到数据后,发出应答信号(ACK/NACK)
- 图示
| 操作类型 | SCL (时钟线) 控制方 | SDA (数据线) 控制方 | ACK/NACK (应答) 发送方 |
|---|---|---|---|
| 主机写 | 主机 | 主机 | 从机 (接收方) |
| 主机读 | 主机 | 从机 | 主机 (接收方) |
通信停止
主机在SCL为高电平时,使SDA产生一个由低到高的跳变,标志通信结束。
I2C外设
总述
I2C外设就是能够实现I2C通信的可编程外部电子器件,I2C外设可以完成I2C协议和来自CPU的并行指令之间的转换,并实现外设的相应功能。
上面提到了I2C协议的通信原理,这种协议的实现不是单片机中的CPU要做的事情,相反,是由外设来实现的,也就是说,每个I2C外设的内部电路都能够实现I2C通信,I2C外设就像是模块化编程中的每个类,为主函数(CPU)提供了使用I2C通信的接口。
I2C外设可以被设置为设置为四种模式:
-
主设备模式 (Master Modes) 当MCU作为总线的“发起者”和“控制者”时,I2C外设就工作在主设备模式下。 核心特征是:由它产生SCL时钟信号,并由它发起和停止通信。
-
主发送模式 (Master Transmit): 主设备向从设备发送/写入数据。 SDA控制权: 在数据传输阶段,主设备控制SDA线。 ACK/NACK: 主设备接收来自从设备的应答。 典型应用:
- 向OLED显示屏发送要显示的图像数据。
- 向EEPROM写入要保存的配置信息。
- 向传感器写入配置寄存器(如设置测量精度)。
-
主接收模式 (Master Receive) 主设备从从设备接收/读取数据。 SDA控制权: 在数据传输阶段,从设备控制SDA线。 ACK/NACK: 主设备发送应答给从设备。 典型应用:
- 从温度传感器读取温度值。
- 从EEPROM读取已保存的数据。
- 从陀螺仪传感器读取姿态数据。
-
-
从设备模式 (Slave Modes) 当MCU作为总线上被动的“响应者”时,I2C外设就工作在从设备模式下。 核心特征是:它从不主动产生SCL时钟,而是时刻监听总线,等待自己的地址被主设备呼叫。
-
从接收模式 (Slave Receive) 目标: 从设备从主设备接收/写入的数据。 SDA控制权: 在数据传输阶段,主设备控制SDA线。 ACK/NACK: 从设备发送应答给主设备。 典型应用:
- 你的设备作为一个可配置的模块,接收来自主控板的指令或参数。
- 实现一个多MCU系统,其中一个MCU作为主控,其他作为从机接收命令。
-
从发送模式 (Slave Transmit) 目标: 从设备向主设备发送/读出数据。 SDA控制权: 在数据传输阶段,从设备控制SDA线。 ACK/NACK: 从设备接收来自主设备的应答。 典型应用:
- 你的设备作为一个传感器模块,当主设备请求数据时,将采集到的数据发送出去。
- 在多MCU系统中,向上级主控汇报自己的状态或数据。
-
I2C通信和外设的配置和HAL库见下篇文章