I2C通信协议研究
目录
目录
前言
串口通信通过TX引脚向RX引脚传输以字节为单位的数据流,形成多字节数据包,采用一条发送线、一条接收线的异步全双工协议。基于串口通信协议,如何设计满足特殊要求的通信协议呢?
新的通信协议需满足:单片机与外部模块通过少量线连接,实现读写外部模块寄存器功能,包括指定位置写寄存器与读寄存器;通信为半双工,即同一根通信线负责发送与接收;具备应答机制,发送方每发送完一个字节数据后,接收方需回应;一根通信线可接多个模块,单片机能与任一模块通信且通信时其他模块不干扰;通信协议为同步通信,需时钟线指导读写。
一、I2C通信概述
I2C(Inter IC Bus)是Philips公司开发的通用数据总线,包含两根通信线:SCL(Serial Clock)和SDA(Serial Data),具备同步、半双工、带数据应答的特点,支持总线挂载多设备,包括一主多从与多主多从模式。
1.1 I2C总线简介
I2C总线是Philips公司开发的通用数据总线。作为一种通信协议,I2C与串口通信类似,可实现多个设备间的通信。其应用广泛,众多模块采用I2C协议标准,便于开发者在不同硬件上操作,掌握一种硬件后可轻松学习其他硬件。
1.2 I2C通信线功能
I2C通信线包括SCL(Serial Clock)和SDA(Serial Data)。SCL即串行时钟线,满足前言中同步时序的需求,降低硬件依赖且稳定性高于异步时序;SDA即串行数据线,一根线兼具发送和接收功能,满足大公司提出的半双工需求,最大化利用资源。使用I2C通信的器件均配备SCL和SDA引脚。
1.3 同步半双工通信特性
I2C协议是同步、半双工且带数据应答的协议,满足需求2。这种通信特性使得I2C在数据传输过程中具有明确的时序控制和数据确认机制,保证了数据传输的可靠性和稳定性。
1.4 一主多从架构
I2C支持总线挂载多设备,满足设计要求3,并且支持一主多从和多主多从两种模型。一主多从模型中,单片机作为主机主导I2C总线运行,所有外部模块为从机,从机只有被主机点名后才能控制I2C总线,防止冲突。这类似于教室里老师主导课程,学生只有被点名后才能发言。绝大多数I2C应用场景采用一主多从形式,一个单片机挂载一个或多个模块作为从机。I2C还支持多主多从模型,总线上的任何一个模块都可以主动成为主机,但同一时间只能有一个人说话,发生总线冲突时,I2C协议会进行仲裁,仲裁胜利的一方取得总线控制权。多主机情况下,还需进行时钟同步,本文主要展示一主多从模型的使用。
二、硬件电路设计
I2C硬件规定包括电路连接和端口输入输出模式等内容。所有I2C设备的SCL连在一起,SDA连在一起;设备的SCL和SDA均要配置成开漏输出模式;SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右。
2.1 I2C电路模型构建
典型I2C电路模型为一主多从模型。左边CPU即单片机作为总线主机,拥有对SCL线的完全控制权,空闲状态下可主动发起对SDA的控制,仅在从机发送数据和应答时转交SDA控制权给从机。图中下方的四个模块是从机,可为姿态传感器、OLED、存储器、时钟模块等。从机的权利较小,对于SCL时钟线只能被动读取,不允许控制;对于SDA数据线,只有在主机发送读取从机命令或从机应答时,才能短暂取得SDA控制权。
2.2 I2C接线规范
I2C接线要求是所有设备的SCL连在一起,SDA连在一起。主机的SCL线和SDA线分别连接所有从机的SCL和SDA,这种接线方式确保了I2C总线的正常通信。
2.3 I2C上拉电阻功能
若忽略图中右上方的两个电阻,规定每个设备SCL和SDA的输入输出模式会存在问题。SCL线规定主机为推挽输出,从机为浮空输入或上拉输入,数据流向为主机发送、从机接收。但SDA线作为半双工协议,主机和从机的SDA需在输入和输出间切换,若总线时序协调不好,易导致两个引脚同时处于输出状态,若一个输出高电平、一个输出低电平,就会造成电源短路,这是要极力避免的。
为避免电源短路问题,I2C设计禁止所有设备输出强上拉的高电平,采用外置弱上拉电阻加开漏输出的电路结构。设备的SCL和SDA均配置成开漏输出模式,SCL和SDA各添加一个上拉电阻,阻值一般为4.7K欧左右。这种设计杜绝了电源短路现象,避免了引脚模式的频繁切换,还利用“线与”现象实现多主机模式下的时钟同步和总线仲裁。
三、I2C时序基本单元解析
接下来是软件部分,即I2C时序设计。首先学习I2C规定的一些时序基本单元。
3.1 起始与终止条件
3.1.1 起始条件特点
起始条件是指SCL高电平期间,SDA从高电平切换到低电平。在I2C总线空闲状态时,SCL和SDA都处于高电平状态,由外挂的上拉电阻拉高。当主机需要进行数据收发时,产生起始条件,即保持SCL高电平,拉低SDA产生下降沿。从机捕获到SCL高电平、SDA下降沿信号后会复位,等待主机召唤。之后主机再拉低SCL,一方面占用总线,另一方面方便基本单元拼接,保证每个时序单元的SCL以低电平开始、低电平结束,使单元拼接起来SCL能连续得上。
3.1.2 终止条件特点
终止条件是SCL高电平期间,SDA从低电平切换到高电平。SCL先放手回弹到高电平,SDA再放手回弹到高电平,产生上升沿触发终止条件。终止条件之后,SCL和SDA回归到最初的平静状态。起始条件和终止条件类似串口时序里的起始位和停止位,一个完整的数据帧以起始条件开始,终止条件结束,且起始和终止都由主机产生,从机不允许产生。
3.2 发送字节流程
在起始条件之后,紧跟着是发送一个字节的时序单元。发送一个字节时,SCL低电平期间,主机依次将数据放到SDA线上,高位先行。然后主机释放SCL,从机在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化。依次循环上述过程8次,即可发送一个字节。发送过程中,主机在SCL低电平时根据要发送的数据位控制SDA的电平,高电平期间从机读取SDA数据。主机在SCL下降沿之后尽快把数据放在SDA上,从机在SCL上升沿读取数据。整个过程在SCL的同步下进行,发送8位数据即完成一个字节的发送。需要注意的是,I2C是高位先行,与串口时序的低位先行不同。此外,由于I2C有时钟线同步,即使主机发送过程中进中断,传输也会在中断结束后继续进行,不会出问题,这是同步时序的优势。
3.3 接收字节流程
接收一个字节的流程是SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后主机释放SCL,主机在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据位变化。依次循环上述过程8次,即可接收一个字节。主机在接收之前需释放SDA,因为总线是线与的特征,任何一个设备拉低电平,总线就是低电平。接收时,从机取得SDA控制权,根据要发送的数据位控制SDA电平,主机在SCL高电平期间读取数据。SCL全程由主机控制,SDA主机在接收前释放,交由从机控制。从机的数据变换贴着SCL下降沿进行,主机可在SCL高电平的任意时刻读取。
3.4 应答机制详解
应答机制分为发送应答和接收应答,它们的时序分别和发送一个字节、接收一个字节的其中一位相同,可理解为发送一位和接收一位用来做应答。
3.4.1 接收应答流程
接收应答是主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答。主机在接收之前需释放SDA。在调用发送一个字节之后,紧跟着调用接收应答的时序,用来判断从机有没有收到刚才给它的数据。如果从机收到,在应答位时主机释放SDA,从机拉低SDA,主机在SCL高电平期间读取应答位,若应答位为0,说明从机收到。这个过程类似于主机发送完数据后询问是否收到,从机通过拉低SDA回应。
3.4.2 发送应答流程
发送应答是主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。在接收一个字节之后,主机给从机发送应答位,目的是告诉从机是否继续发送。如果从机得到主机应答,会继续发送;若没得到应答,从机认为主机不想要数据了,就会释放SDA,交出控制权,防止干扰主机后续操作。
四、I2C时序综合分析
I2C的完整时序主要有指定地址写、当前地址读和指定地址读这三种。
4.1 I2C设备从机地址设定
在I2C一主多从模型中,主机通过从机地址访问总线上的设备。主机在起始条件之后发送一个字节,包含从机地址和读写位。所有从机将收到的字节与自己的地址比较,若相同则响应主机的读写操作。从机地址在I2C协议标准里有7位地址和10位地址,本文介绍7位地址模型。每个I2C设备出厂时有7位地址,不同型号芯片地址不同,相同型号芯片地址相同,但可通过地址中的可变部分改变地址。例如MPU6050地址的最后一位可由AD0引脚确定,AT24C02芯片地址的最后三位可由A0、A1、A2引脚确定。这样即使相同型号芯片挂载在同一条总线上,也可保证每个设备地址不同。
4.2 指定地址写时序
指定地址写时序的任务是对指定设备,在指定地址下写入指定数据。时序开始时,主机在SCL高电平期间拉低SDA产生起始条件。之后发送一个字节,包含从机地址和读写位,读写位为0表示写入操作。从机收到后应答。接着主机发送第二个字节,指定寄存器地址或指令控制字等。再发送要写入的数据字节,从机应答。最后产生停止条件。例如,对从机地址为1101000的设备,在其内部0x19地址的寄存器中写入0xAA数据。
4.3 当前地址读时序
当前地址读时序的任务是对指定设备,在当前地址指针指示的地址下读取从机数据。时序开始时产生起始条件,主机发送一个字节,包含从机地址和读写位,读写位为1表示读取操作。从机应答后,主机释放SDA,从机在SCL低电平期间写入SDA,主机在SCL高电平期间读取数据。由于主机在寻址时读写标志位给1后,下一个字节就转为读的时序,所以主机来不及指定读哪个寄存器,从机返回当前指针指向的寄存器的值。从机中寄存器被分配到线性区域,有指针变量指示寄存器,指针上电默认指向0地址,每写入或读出一个字节后指针自动自增一次。例如,刚调用指定地址写的时序在0x19位置写入0xAA后,指针移动到0x1A位置,再调用当前地址读时序,返回的就是0x1A地址下的值。
4.4 指定地址读时序
指定地址读时序的任务是对指定设备,在指定地址下读取从机数据。时序开始时产生起始条件,发送一个字节进行寻址,读写标志位为0表示写操作。从机应答后,发送第二个字节指定地址。然后产生重复起始条件,重新寻址且读写标志位为1表示读操作。主机接收一个字节,即指定地址下的数据。例如,对从机地址为1101000的设备,先指定地址0x19,再读取0x19地址下的数据。指定地址读时序也可通过先写入地址再停止,之后再起始读当前位置来实现,但I2C协议官方规定的复合格式是一整数据帧,即先起始、再重复起始、再停止。
总结
本文详细介绍了I2C通信协议,包括其基本概念、硬件电路设计、时序基本单元以及完整的时序分析。I2C作为一种广泛应用的通信协议,以其简单的硬件连接和高效的通信机制,在众多领域发挥着重要作用。通过对I2C协议的深入研究,我们可以更好地理解和应用这一协议,为相关领域的研发和实践提供有力支持。