UART、SPI、IIC通信总线原理

1.UART原理

串口是典型的异步串行通信方式,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。其中,232电平可传输20米左右,485和422信号可传输1200米。

UART、SPI、IIC通信总线原理

如上图所示,进行数据传输时,TxD用于数据的发送,RxD用于数据的接受。

数据帧格式:

UART、SPI、IIC通信总线原理

其中:

起始位(start):1bit,为低电平,表示数据的开始;

数据位(Data):8bits,由低位开始传输,即D0为最低位

奇偶检验位(Parity):1bit,可设为奇校验或者偶校验,可省略

停止位(Stop):1~2bits,高电平,表示数据的结束

数据传输中可能出现的错误:

1.数据帧错误:若一段时间后仍收不到期待的停止位,则发生数据帧错误

2.奇偶校验错误

3.溢出错误:若接收方相关缓存的数据还没来的及读取,就被新数据覆盖,则发生溢出错误

4.间断错误:RxD数据线失去第一个停止位后,若连续保持低电平10位以上,则发生间断错误

2.SPI原理

 SPI是串行外设接口(Serial Peripheral Interface)的缩写。是 Motorola 公司推出的一种同步串行接口技术,是一种高速的,全双工,同步的通信总线。

它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是:

(1)MOSI – 主设备数据输出,从设备数据输入;

(2)MISO – 主设备数据输入,从设备数据输出;

(3)SCLK – 时钟信号,由主设备产生;

(4)CS/SS – 其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。需要注意的是,在具体的应用中,当一条SPI总线上连接有多个设备时,SPI本身的CS有可能被其他的GPIO脚代替,即每个设备的CS脚被连接到处理器端不同的GPIO,通过操作不同的GPIO口来控制具体的需要操作的SPI设备,减少各个SPI设备间的干扰。

UART、SPI、IIC通信总线原理

如上图所示,SPI中的核心组件为SSPSR移位寄存器,SSPBUF为数据缓冲区,控制器输出(接受)同步时钟信号和片选信号。

 SPI是串行通讯协议,也就是说数据是一位一位从MSB或者LSB开始传输的,这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,MISO、MOSI则基于此脉冲完成数据传输。 SPI支持4-32bits的串行数据传输,支持MSB和LSB,每次数据传输时当从设备的大小端发生变化时需要重新设置SPI Master的大小端。

UART、SPI、IIC通信总线原理

工作时序:

在SPI操作中,最重要的两项设置就是时钟极性(CPOL或UCCKPL)和时钟相位(CPHA或UCCKPH)。时钟极性设置时钟空闲时的电平,时钟相位设置读取数据和发送数据的时钟沿。

主机和从机的发送数据是同时完成的,两者的接收数据也是同时完成的。所以为了保证主从机正确通信,应使得它们的SPI具有相同的时钟极性和时钟相位。

CPOL极性

SPI的CPOL,表示当SCLK空闲idle的时候,其电平的值是低电平0还是高电平1:

CPOL=0,时钟空闲idle时候的电平是低电平,所以当SCLK有效的时候,就是高电平,就是所谓的active-high;

CPOL=1,时钟空闲idle时候的电平是高电平,所以当SCLK有效的时候,就是低电平,就是所谓的active-low;

CPHA相位

相位,对应着数据采样是在第几个边沿(edge),是第一个边沿还是第二个边沿,0对应着第一个边沿,1对应着第二个边沿。

CPOL=0:

对于CPHA=0,idle时候的是低电平,第一个边沿就是从低变到高,所以是上升沿;

对于CPHA=1,idle时候的是低电平,第二个边沿就是从高变到低,所以是下降沿;

CPOL=1:

对于CPHA=0,idle时候的是高电平,第一个边沿就是从高变到低,所以是下降沿;

对于CPHA=1,idle时候的是高电平,第二个边沿就是从低变到高,所以是上升沿;

如图所示,当CPHA和CPOL都为0时:

UART、SPI、IIC通信总线原理

SCK的第一个时钟周期,在时钟的前沿采样数据(上升沿,第一个时钟沿),在时钟的后沿输出数据(下降沿,第二个时钟沿)。

首先来看主器件,主器件的输出口(MOSI)输出的数据bit1,在时钟的前沿被从器件采样,那主器件是在何时刻输出 bit1 的呢?bit1 的输出时刻实际上在 SCK 信号有效以前,比 SCK 的上升沿还要早半个时钟周期。bit1 的输出时刻与 SSEL 信号没有关系。

再来看从器件,主器件的输入口(MISO)同样是在时钟的前沿采样从器件输出的 bit1 的,那从器件又是在何时刻输出 bit1 的呢?从器件是在SSEL信号有效后,立即输出 bit1,尽管此时SCK信号还没有起效。

3.IIC原理

简介:

I2C(Inter-integrated Circuit)总线支持设备之间的短距离通信,用于处理器和一些外围设备之间的接口,它只需要两根信号线来完成信息交换。I2C最早是飞利浦在1982年开发设计并用于自己的芯片上,一开始只允许100kHz、7-bit标准地址。1992年,I2C的第一个公共规范发行,增加了400kHz的快速模式以及10-bit扩展地址。在I2C的基础上,1995年Intel提出了“System Management Bus” (SMBus),用于低速设备通信,SMBus 把时钟频率限制在10kHz~100kHz,但I2C可以支持0kHz~5MHz的设备:普通模式(100kHz即100kbps)、快速模式(400kHz)、快速模式+(1MHz)、高速模式(3.4MHz)和超高速模式(5MHz)。

和SPI不同的是,I2C可以支持mul-master系统,允许有多个master并且每个master都可以与所有的slaves通信(master之间不可通过I2C通信,并且每个master只能轮流使用I2C总线)。master是指启动数据传输的设备并在总线上生成时钟信号以驱动该传输,而被寻址的设备都作为slaves。 

I2C总线只有两根双向信号线。其中一根是数据线SDA,另一根是时钟线SCL。由于仅有一根数据线,故通信是半双工的。

每个接到I2C总线上的器件都有唯一的地址。发送数据到总线上的称为发送器,从总线上接收数据的器件称为接收器。

UART、SPI、IIC通信总线原理

I2C协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。起始和结束信号总是由主设备产生

总线在空闲状态时,SCL和SDA都保持着高电平;

起始条件:当SCL为高电平而SDA由高到低的跳变;在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;

停止条件:当SCL为高而SDA由低到高的跳变。而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。注意,在正常传输数据过程中,当SCL处于高电平时,SDA上的值不应该变化,防止意外产生一个停止条件。

UART、SPI、IIC通信总线原理

在了解起始条件和停止条件后,我们再来看看在这个过程中数据的传输是如何进行的。前面我们已经提到过,数据传输以字节为单位。主设备在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位,此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。数据传输的过程如图所示:

UART、SPI、IIC通信总线原理

在前面我们还提到过,I2C总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。如图所示:

UART、SPI、IIC通信总线原理

I2C总线的字节格式

发送到SDA线上的每个字节必须是8位,每次传输可以发送的字节数量不受限制,每个字节后必须跟一个ACK应答位,数据从最高有效位(MSB)开始传输。如果从机要完成一些其他功能后(如一个内部中断服务程序)才能接收或发送下一个完整的字节,可以使时钟线SCL保持低电平迫使主机进入等待(wait)状态。当从机准备好新的字节数据传输时,释放时钟线SCL,数据传输便继续进行。

应答信号

  I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

重复开始条件(repeated start condition): 
有时master需要在一次通信中进行多次消息交换(例如与不同的slave传输消息,或切换读写操作),并且期间不希望被其他master干扰,这时可以使用“重复开始条件” —— 在一次通信中,master可以产生多次start condition,来完成多次消息交换,最后再产生一个stop condition结束整个通信过程。由于期间没有stop condition,因此master一直占用总线,其他master无法切入。 

为了产生一个重复的开始条件,SDA在SCL低电平时拉高,然后SCL拉高。接着master就可以产生一个开始条件继续新的消息传输(按照正常的7-bit/10-bit地址传输时序)。重复开始条件的传输时序如下图所示: 

UART、SPI、IIC通信总线原理

时钟同步和仲裁

如果两个master都想在同一条空闲总线上传输,此时必须能够使用某种机制来选择将总线控制权交给哪个master,这是通过时钟同步和仲裁来完成的,而*让出控制权的master则需要等待总线空闲后再继续传输。在单一master的系统上无需实现时钟同步和仲裁。

时钟同步

时钟同步是通过I2C接口和SCL之间的线“与”(wired-AND)来完成的,即如果有多个master同时产生时钟,那么只有所有master都发送高电平时,SCL上才表现为高电平,否则SCL都表现为低电平。

总线仲裁

总线仲裁和时钟同步类似,当所有master在SDA上都写1时,SDA的数据才是1,只要有一个master写0,那此时SDA上的数据就是0。一个master每发送一个bit数据,在SCL处于高电平时,就检查看SDA的电平是否和发送的数据一致,如果不一致,这个master便知道自己输掉仲裁,然后停止向SDA写数据。也就是说,如果master一直检查到总线上数据和自己发送的数据一致,则继续传输,这样在仲裁过程中就保证了赢得仲裁的master不会丢失数据。 
输掉仲裁的master在检测到自己输了之后也不再产生时钟脉冲,并且要在总线空闲时才能重新传输。 
仲裁的过程可能要经过多个bit的发送和检查,实际上两个master如果发送的时序和数据完全一样,则两个master都能正常完成整个的数据传输。

因此,一般的i2c时序可以表示为:

UART、SPI、IIC通信总线原理