I2C

IICvs SPI

现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求制定了这两种标准通信协议。

IIC 开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互联方式。电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped I/O)的方式来互联微控制器和外围设备的。要实现内存映射,设备必须并联入微控制器的数据线和地址线,这种方式在连接多个外设时需大量线路和额外地址解码芯片,很不方便并且成本高。

为了节省微控制器的引脚和和额外的逻辑芯片,使印刷电路板更简单,成本更低,位于荷兰的Philips实验室开发了 ‘Inter-Integrated Circuit’,IIC 或 IIC ,一种只使用二根线接连所有外围芯片的总线协议。最初的标准定义总线速度为100kbps。经历几次修订,主要是1995年的400kbps,1998的3.4Mbps。

有迹象表明,SPI总线首次推出是在1979年,Motorola公司将SPI总线集成在他们第一支改自68000微处理器的微控制器芯片上。SPI总线是微控制器四线的外部总线(相对于内部总线)。与IIC不同,SPI没有明文标准,只是一种事实标准,对通信操作的实现只作一般的抽象描述,芯片厂商与驱动开发者通过data sheets和application notes沟通实现上的细节。

SPI

对于有经验的数字电子工程师来说,用SPI互联两支数字设备是相当直观的。SPI是种四根信号线协议(如图):

关于I2C和SPI总线协议

§ SCLK: Serial Clock (output from master);

§ MOSI; SIMO: Master Output, Slave Input(output from master);

§ MISO; SOMI: Master Input, Slave Output(output from slave);

§ SS: Slave Select (active low, outputfrom master).

SPI是[单主设备( single-master )]通信协议,这意味着总线中的只有一支中心设备能发起通信。当SPI主设备想读/写[从设备]时,它首先拉低[从设备]对应的SS线(SS是低电平有效),接着开始发送工作脉冲到时钟线上,在相应的脉冲时间上,[主设备]把信号发到MOSI实现“写”,同时可对MISO采样而实现“读”,如下图:

关于I2C和SPI总线协议

SPI有四种操作模式——模式0、模式1、模式2和模式3,它们的区别是定义了在时钟脉冲的哪条边沿转换(toggles)输出信号,哪条边沿采样输入信号,还有时钟脉冲的稳定电平值(就是时钟信号无效时是高还是低)。每种模式由一对参数刻画,它们称为时钟极(clock polarity)CPOL与时钟期(clock phase)CPHA。

关于I2C和SPI总线协议

[主从设备]必须使用相同的工作参数——SCLK、CPOL 和 CPHA,才能正常工作。如果有多个[从设备],并且它们使用了不同的工作参数,那么[主设备]必须在读写不同[从设备]间重新配置这些参数。以上SPI总线协议的主要内容。SPI不规定最大传输速率,没有地址方案;SPI也没规定通信应答机制,没有规定流控制规则。事实上,SPI[主设备]甚至并不知道指定的[从设备]是否存在。这些通信控制都得通过SPI协议以外自行实现。例如,要用SPI连接一支[命令-响应控制型]解码芯片,则必须在SPI的基础上实现更高级的通信协议。SPI并不关心物理接口的电气特性,例如信号的标准电压。在最初,大多数SPI应用都是使用间断性时钟脉冲和以字节为单位传输数据的,但现在有很多变种实现了连续性时间脉冲和任意长度的数据帧。

IIC

与SPI的单主设备不同,IIC 是多主设备的总线,IIC没有物理的芯片选择信号线,没有仲裁逻辑电路,只使用两条信号线—— ‘serial data’ (SDA) 和 ‘serial clock’ (SCL)。IIC协议规定:

§ 第一,每一支IIC设备都有一个唯一的七位设备地址;

§ 第二,数据帧大小为8位的字节;

§ 第三,数据(帧)中的某些数据位用于控制通信的开始、停止、方向(读写)和应答机制。

IIC 数据传输速率有标准模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps),另外一些变种实现了低速模式(10 kbps)和快速+模式(1 Mbps)。

物理实现上,IIC 总线由两根信号线和一根地线组成。两根信号线都是双向传输的,参考下图。IIC协议标准规定发起通信的设备称为主设备,主设备发起一次通信后,其它设备均为从设备。

关于I2C和SPI总线协议

IIC 通信过程大概如下。首先,主设备发一个START信号,这个信号就像对所有其它设备喊:请大家注意!然后其它设备开始监听总线以准备接收数据。接着,主设备发送一个7位设备地址加一位的读写操作的数据帧。当所设备接收数据后,比对地址自己是否目标设备。如果比对不符,设备进入等待状态,等待STOP信号的来临;如果比对相符,设备会发送一个应答信号——ACKNOWLEDGE作回应。

当主设备收到应答后便开始传送或接收数据。数据帧大小为8位,尾随一位的应答信号。主设备发送数据,从设备应答;相反主设备接数据,主设备应答。当数据传送完毕,主设备发送一个STOP信号,向其它设备宣告释放总线,其它设备回到初始状态。

关于I2C和SPI总线协议

基于IIC总线的物理结构,总线上的START和STOP信号必定是唯一的。另外,IIC总线标准规定SDA线的数据转换必须在SCL线的低电平期,在SCL线的高电平期,SDA线的上数据是稳定的。

关于I2C和SPI总线协议

在物理实现上,SCL线和SDA线都是漏极开路(open-drain),通过上拉电阻外加一个电压源。当把线路接地时,线路为逻辑0,当释放线路,线路空闲时,线路为逻辑1。基于这些特性,IIC设备对总线的操作仅有“把线路接地”——输出逻辑0。

IIC总线设计只使用了两条线,但相当优雅地实现任意数目设备间无缝通信,堪称完美。我们设想一下,如果有两支设备同时向SCL线和SDA线发送信息会出现什么情况。

基于IIC总线的设计,线路上不可能出现电平冲突现象。如果一支设备发送逻辑0,其它发送逻辑1,那么线路看到的只有逻辑0。也就是说,如果出现电平冲突,发送逻辑0的始终是“赢家”。

总线的物理结构亦允许主设备在往总线写数据的同时读取数据。这样,任何设备都可以检测冲突的发生。当两支主设备竞争总线的时候,“赢家”并不知道竞争的发生,只有“输家”发现了冲突——当它写一个逻辑1,却读到0时——而退出竞争。

10位设备地址

任何IIC设备都有一个7位地址,理论上,现实中只能有127种不同的IIC设备。实际上,已有IIC的设备种类远远多于这个限制,在一条总线上出现相同的地址的IIC设备的概率相当高。为了突破这个限制,很多设备使用了双重地址——7位地址加引脚地址(external configuration pins)。IIC 标准也预知了这种限制,提出10位的地址方案。

10位的地址方案对 IIC协议的影响有两点:

§ 第一,地址帧为两个字节长,原来的是一个字节;

§ 第二,第一个字节前五位最高有效位用作10位地址标识,约定是“11110”。

关于I2C和SPI总线协议

除了10位地址标识,标准还预留了一些地址码用作其它用途,如下表:

关于I2C和SPI总线协议

时钟拉伸

在 IIC 通信中,主设备决定了时钟速度。因为时钟脉冲信号是由主设备显式发出的。但是,当从设备没办法跟上主设备的速度时,从设备需要一种机制来请求主设备慢一点。这种机制称为时钟拉伸,而基于I²C结构的特殊性,这种机制得到实现。当从设备需要降低传输的速度的时候,它可以按下时钟线,逼迫主设备进入等待状态,直到从设备释放时钟线,通信才继续。

高速模式

原理上讲,使用上拉电阻来设置逻辑1会限制总线的最大传输速度。而速度是限制总线应用的因素之一。这也说明为什么要引入高速模式(3.4 Mbps)。在发起一次高速模式传输前,主设备必须先在低速的模式下(例如快速模式)发出特定的“High Speed Master”信号。为缩短信号的周期和提高总线速度,高速模式必须使用额外的I/O缓冲区。另外,总线仲裁在高速模式下可屏蔽掉。更多的信息请参与总线标准文档。

IIC vs SPI: 哪位是赢家?

我们来对比一下IIC 和 SPI的一些关键点:

第一,总线拓扑结构/信号路由/硬件资源耗费

IIC 只需两根信号线,而标准SPI至少四根信号,如果有多个从设备,信号需要更多。一些SPI变种虽然只使用三根线——SCLK, SS和双向的MISO/MOSI,但SS线还是要和从设备一对一根。另外,如果SPI要实现多主设备结构,总线系统需额外的逻辑和线路。用IIC 构建系统总线唯一的问题是有限的7位地址空间,但这个问题新标准已经解决——使用10位地址。从第一点上看,IIC是明显的大赢家。

第二,数据吞吐/传输速度

如果应用中必须使用高速数据传输,那么SPI是必然的选择。因为SPI是全双工,IIC 的不是。SPI没有定义速度限制,一般的实现通常能达到甚至超过10 Mbps。IIC 最高的速度也就快速+模式(1 Mbps)和高速模式(3.4 Mbps),后面的模式还需要额外的I/O缓冲区,还并不是总是容易实现的。

第三,优雅性

IIC 常被称更优雅于SPI。公正的说,我们更倾向于认为两者同等优雅和健壮。IIC的优雅在于它的特色——用很轻盈的架构实现了多主设备仲裁和设备路由。但是对使用的工程师来讲,理解总线结构更费劲,而且总线的性能不高。

SPI的优点在于它的结构相当的直观简单,容易实现,并且有很好扩展性。SPI的简单性不足称其优雅,因为要用SPI搭建一个有用的通信平台,还需要在SPI之上构建特定的通信协议软件。也就是说要想获得SPI特有而IIC没有的特性——高速性能,工程师们需要付出更多的劳动。另外,这种自定的工作是完全自由的,这也说明为什么SPI没有官方标准。IIC和SPI都对低速设备通信提供了很好的支持,不过,SPI适合数据流应用,而IIC更适合“字节设备”的多主设备应用。

小结

在数字通信协议簇中,IIC和SPI常称为“小”协议,相对Ethernet, USB, SATA, PCI-Express等传输速度达数百上千兆字节每秒的总线。但是,我们不能忘记的是各种总线的用途是什么。“大”协议是用于系统外的整个系统之间通信的,“小”协议是用于系统内各芯片间的通信,没有迹象表明“大”协议有必要取代“小”协议。IIC和SPI的存在和流行体现了“够用就好”的哲学。回应文首,IIC和SPI如此的流行,它是任何一位嵌入式工程师必备的工具。

转自:CSDN

围观 467

I2C和SPI是两种不同的通信协议。

听到协议,似乎高不可攀,其实协议就是人们定义的一个标准而已,我们只要遵照这个标准去做事,就可以。比如公司规定早上9点上班,我们就9点上班,不然就会扣薪水,这就是个协议。

用I2C通信的芯片最常用的就是EEPROM芯片,如Atmel的AT24CXX系列,此外,还有一些其它功能的芯片。用SPI通信的芯片有外置FLASH芯片,同样,还有其他功能的一些芯片。

I2C通信需要用到两个引脚:SDA SCL。SCL是时钟引脚,SDA是数据引脚。

理解一下单片机的I2C和SPI通信
(这是EEPROM芯片)

理解一下单片机的I2C和SPI通信
(这是时钟芯片)

SPI通信需要3个引脚或者4个引脚:CS SCK MOSI MISO。SPI通信芯片的引脚名称不一定都是这几个名称,可能还有会别的名称,但是意思是一样的,例如MOSI引脚的意思是“主机输出从机输入”,某个SPI接口的芯片就有可能会写成SDI,因为这个SPI器件是作为从机的,所以它的SDI的意思就是“从机数据输入引脚”。

SPI通信过程为:把CS引脚拉低,然后SCK输出时钟,然后就可以在MOSI引脚上输出数据,同时可以在MISO上获得数据了。

理解一下单片机的I2C和SPI通信
(这是一个SPI FLASH芯片,DO是MISO,DI是MOSI,CLK是SCK,功能一样,叫法不一样而已)

理解一下单片机的I2C和SPI通信
(这是一个SPI接口的ADC芯片,Dout是MISO,DCLOCK就是SCK,这个芯片有3个SPI引脚)

大部分单片机上面都会带有I2C口和SPI口,有可能还会有好几个I2C口和SPI口。不过,不带I2C口和SPI口的单片机,也可以通过普通引脚的模拟他们的时序来进行通信。

而且,如果是初学者的话,一定要学习一下用普通引脚模拟,对他们的通信本质理解更深刻。

通信全程,其实就是控制引脚高低电平和检测引脚高低电平的过程,话说,控制单片机的引脚高低电平和检测引脚的高低电平,第一天学单片机就会了,所以,I2C通信和SPI通信也没什么难的地方。

给大家讲一个最简单的通信过程,例如我们称下面的通信名称为KJLWT,名字是不是看起来很吊,其实是“科技老顽童”的拼音首字母,因为接下来的协议是我刚刚发明的,所以以此命名^_^。主要是让大家理解,名称就是用来吓唬人的。

我们用两条线来通信,一条时钟线,一条数据线。时钟线,其实就是用来产生一个脉冲波形,再说的直接一点,就是把引脚变高变低的信号,如下图:

理解一下单片机的I2C和SPI通信
(这就是个时钟信号)

例如我们规定,在时钟引脚为高电平的时候,读取数据引脚的电平,连续8个时钟,就可以读到一个字节了。那给数据的那一端,要怎么给数据呢?也很简单,给数据的那一端,在检测到低电平的时候,就把要发送的数据按照位体现在数据引脚上面。例如一个数据:0x88,写成二进制以后就是1000 1000。我们来看一下传输这个数据的过程:从机检测时钟引脚,检测到一个下降沿(就是从高电平落到了低电平),就把要发送的数据的bit7体现在数据引脚上,例如1000 1000的bit7是1,就把数据引脚变高电平,主机在时钟引脚的高电平,检测这个数据引脚,把这个位记录下来,从机再次发现时钟引脚的下降沿后,再把数据的bit6体现在数据引脚上,由于1000 1000 的bit6是0,所以从机把数据引脚拉低,然后当时钟引脚为高电平的时候,主机检测数据引脚的高低电平,再把bit6记录下来,……以此8次,就可以把一个字节由从机传输到主机了。是不是很简单呢?

时钟的速率,就是传输数据的快慢,以上面讲的为例,如果脉冲的周期为1秒钟,也就是1Hz,那么传输一个字节就需要8秒钟;如果脉冲的周期为1毫秒,也就是1KHz,那么输出一个字节只需要8毫秒。这下你就理解通信的速率是什么意思了吧?

I2C通信,SPI通信,只不过是在我刚才讲的例子上面,又多了一些协议内容。具体的协议,你们随便找一个I2C和SPI通信接口的芯片看一下时序图就可以了。我们要做的,就是用单片机的引脚,把它的时序做出来。

转自:博客园 - JHJ_BABY

围观 437

总线空闲状态

I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

I2C总线信号时序总结

启动信号

在时钟线SCL保持高电平期间,数据线SDA上的电平被拉低(即负跳变),定义为I2C总线总线的启动信号,它标志着一次数据传输的开始。启动信号是一种电平跳变时序信号,而不是一个电平信号。启动信号是由主控器主动建立的,在建立该信号之前I2C总线必须处于空闲状态。

重启动信号

在主控器控制总线期间完成了一次数据通信(发送或接收)之后,如果想继续占用总线再进行一次数据通信(发送或接收),而又不释放总线,就需要利用重启动Sr信号时序。重启动信号Sr既作为前一次数据传输的结束,又作为后一次数据传输的开始。利用重启动信号的优点是,在前后两次通信之间主控器不需要释放总线,这样就不会丢失总线的控制权,即不让其他主器件节点抢占总线。

停止信号

在时钟线SCL保持高电平期间,数据线SDA被释放,使得SDA返回高电平(即正跳变),称为I2C总线的停止信号,它标志着一次数据传输的终止。停止信号也是一种电平跳变时序信号,而不是一个电平信号,停止信号也是由主控器主动建立的,建立该信号之后,I2C总线将返回空闲状态。

不是在数据有效性中规定在SDA只能在SCL的低电平的时候变化,为何STAR,STOP不一样?首先STAR和STOP不是数据,所以可以不遵守数据有效性中的规定,其它数据都遵守,而STAR和STOP“不遵守”导致STAR和STOP更容易被识别。这样不是不遵守而是更有优势。

起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态,在停止条件的某段时间后总线被认为再次处于空闲状态。

如果产生重复起始(Sr) 条件而不产生停止条件,总线会一直处于忙的状态。此时的起始条件(S)和重复起始(Sr) 条件在功能上是一样的。

如果连接到总线的器件合并了必要的接口硬件,那么用它们检测起始和停止条件十分简便。但是没有这种接口的微控制器在每个时钟周期至少要采样SDA 线两次来判别有没有发生电平切换。

I2C总线信号时序总结

数据位传送

在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。进行数据传送时,在SCL呈现高电平期间,SDA上的电平必须保持稳定,低电平为数据0,高电平为数据1。只有在SCL为低电平期间,才允许SDA上的电平改变状态。逻辑0的电平为低电压,而逻辑1的电平取决于器件本身的正电源电压VDD(当使用独立电源时)。数据位的传输是边沿触发。

I2C总线信号时序总结

应答信号

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

I2C总线信号时序总结

插入等待时间

如果被控器需要延迟下一个数据字节开始传送的时间,则可以通过把时钟线SCL电平拉低并且保持,使主控器进入等待状态。一旦被控器释放时钟线,数据传输就得以继续下去,这样就使得被控器得到足够时间转移已经收到的数据字节,或者准备好即将发送的数据字节。带有CPU的被控器在对收到的地址字节做出应答之后,需要一定的时间去执行中断服务子程序,来分析或比较地址码,其间就把SCL线钳位在低电平上,直到处理妥当后才释放SCL线,进而使主控器继续后续数据字节的发送。

I2C总线信号时序总结

总线封锁状态

在特殊情况下,如果需要禁止所有发生在I2C总线上的通信活动,封锁或关闭总线是一种可行途径,只要挂接于该总线上的任意一个器件将时钟线SCL锁定在低电平上即可。

总线竞争的仲裁

总线上可能挂接有多个器件,有时会发生两个或多个主器件同时想占用总线的情况,这种情况叫做总线竞争。I2C总线具有多主控能力,可以对发生在SDA线上的总线竞争进行仲裁,其仲裁原则是这样的:当多个主器件同时想占用总线时,如果某个主器件发送高电平,而另一个主器件发送低电平,则发送电平与此时SDA总线电平不符的那个器件将自动关闭其输出级。总线竞争的仲裁是在两个层次上进行的。首先是地址位的比较,如果主器件寻址同一个从器件,则进入数据位的比较,从而确保了竞争仲裁的可靠性。由于是利用I2C总线上的信息进行仲裁,因此不会造成信息的丢失。

为何识别到“0”将丢失仲裁呢?因为对于OD门,只能驱动到低电平,释放总线只能通过不驱动总线释放,停止驱动即产生“1”,但是发现总线还是“0”,这说明还有主机在跟自己竞争总线使用权,自己线驱动到“1”,确检测到“0”,那代表自己已经失去了仲裁。

• 主机只能在总线空闲的时侯启动传送。两个或多个主机可能在起始条件的最小持续时间tHD;STA 内产生一个起始条件,结果在总线上产生一个规定的起始条件。

• 当SCL 线是高电平时,仲裁在SDA 线发生;这样,在其他主机发送低电平时,发送高电平的主机将断开它的数据输出级,因为总线上的电平与它自己的电平不相同。然后,进一步获得其的判定条件:

• 仲裁可以持续多位。首先是比较地址位。如果每个主机都试图寻址同一的器件,仲裁会继续比较数据位(假设主机是发送器),或者比较响应位(假设主机是接收器)。

• I2C 总线的地址和数据信息由赢得仲裁的主机决定,在仲裁过程中不会丢失信息。丢失仲裁的主机可以产生时钟脉冲直到丢失仲裁的该字节末尾。

• 在串行传输过程中时,一旦有重复的起始条件或停止条件发送到I2C 总线的时侯,仲裁过程仍在进行。如果可能产生这样的情况,有关的主机必须在帧格式相同位置发送这个重复起始条件或停止条件。

• 此外,如果主机也结合了从机功能,而且在寻址阶段丢失仲裁,它很可能就是赢得仲裁的主机在寻址的器件。那么,丢失仲裁的主机必须立即切换到它的从机模式。

• I2C 总线的控制只由地址或主机码以及竞争主机发送的数据决定,没有中央主机,总线也没有任何定制的优先权。

I2C总线信号时序总结

上图显示了两个主机的仲裁过程当然可能包含更多的内容由连接到总线的主机数量决定此时产生DATA1 的主机的内部数据电平与SDA 线的实际电平有一些差别如果关断数据输出这就意味着总线连接了一个高输出电平这不会影响由赢得仲裁的主机初始化的数据传输。

时钟信号的同步

在I2C总线上传送信息时的时钟同步信号是由挂接在SCL线上的所有器件的逻辑“与”完成的。SCL线上由高电平到低电平的跳变将影响到这些器件,一旦某个器件的时钟信号下跳为低电平,将使SCL线一直保持低电平,使SCL线上的所有器件开始低电平期。此时,低电平周期短的器件的时钟由低至高的跳变并不能影响SCL线的状态,于是这些器件将进入高电平等待的状态。当所有器件的时钟信号都上跳为高电平时,低电平期结束,SCL线被释放返回高电平,即所有的器件都同时开始它们的高电平期。其后,第一个结束高电平期的器件又将SCL线拉成低电平。这样就在SCL线上产生一个同步时钟。可见,时钟低电平时间由时钟低电平期最长的器件确定,而时钟高电平时间由时钟高电平期最短的器件确定。

I2C总线信号时序总结

转自: 博乐Bar

围观 583

这是一份介绍性指南,指导你如何用超低功耗MSP微控制器 (MCU) 开始一个与I2C通信有关的项目:

简介

I2C(或称为I2C,集成电路总线)是一种两线制通信形式,主要用来在短距离、电路板间的应用中,实现微控制器与外设IC之间的低速通信。由于其采用范围很广,所以学习使用I2C与MSP MCU之间的通信已经在帮助工程师开发应用方面变得十分必要。通过使用一个超低功耗MSP MCU来访问和控制IC器件,这份指南提供了理解I2C协议并执行这一协议所需的工具与资源。

器件术语

驱动SCL时钟线路的器件被称为主器件,而对其进行响应的器件被称为从器件。在大多数应用中,MSP MCU为主器件,而外设IC为从器件,虽然有时候MSP器件是其它MCU或处理器的从器件。

物理总线

I2C总线由两条线路组成,SCL和SDA。SCL是用来将所有数据传输同步的时钟线路,而SDA是实际的数据线路。还需要第三条线路,即普通接地,不过通常不被提及。由于两条线路都是“开漏”驱动器,它们都需要到电源线路的上拉电阻,这样的话,输出在无运行期间保持在高电平。对于MSP MCU应用来说,电源电压应该与MSP MCU的Vcc相匹配。传统上,上拉电阻器的值为4.7kΩ,不过这个值的范围可以在少于1kΩ到10kΩ之间,取决于所使用的从器件。要获得正确的上拉电阻值,请参考器件数据表。多个从器件可以共用一条I2C总线,单个上拉电阻器

I2C软件协议

不论何种应用,每个支持I2C器件都需要遵守针对全部I2C器件所定义的共同软件协议,其一般结构始终保持不变。通信从启动序列开始,并在一个停止序列中结束,两个序列之间有一个8位数据传输序列。启动位之后是从地址,通常为7位(虽然很少情况下也使用10位寻址)。这7个数据位被放置在一个字节的上7位,而LSB(最低有效位)被用来存储读/写 (R/W) 位。这个位让从器件知道是对其进行写入操作(位值为0),还是读取操作(位值为1)。

对一个写入操作,操作序列如下:

1.发送启动序列
2.发送从地址,其中R/W位为低电平
3.发送寄存器数
4.发送数据字节
5.发送停止序列

读取操作序列与写入操作十分相似,除了它不发送数据字节,而是重新发送启动序列(被称为一个重复启动)和从地址(不过此时,对于读取操作来说,R/W位为高电平),这样的话,它可以接收数据,而不是发送数据。这个操作在主器件发出典型停止序列后结束。

下面是读取操作序列:

1.发送启动序列
2.发送从地址,其中R/W位为低电平
3.发送寄存器数
4.再次发出启动序列(重复启动)
5.发出从地址,其中R/W位为高电平
6.读取数据字节
7.发出停止序列

MSP MCU通信外设

为了实现串行通信,MSP器件上有可能提供4种不同的外设。其中只有一个外设会因器件的不同而不同。根据在MSP MCU上实现I2C通信的难易程度(从最难到最容易),将这些使用的外设列出如下:

• UART:通用同步/异步接收器/发射器。这是最早出现的通信形式,并且存在于大多数MSP430F1xx MCU上。它不支持I2C,因此必须使用一个基于软件的位响应 (bit-bang) 解决方案来与I2C器件实现通信。

• USI:通用串行接口。另外一个更加简单的通信形式,用于MSP430G2xx系列内的某些组件等成本有效或空间受限器件。器件上没有I2C状态机,必须在软件中实现。通常情况下,通过使用单独的函数来实现。

• USCI:通用串行接口。一个针对ISR和标志用法进行优化的标准通信外设。这个外设常见于MSP430F5xx/F6xx系列中,其中包括一个基于硬件的I2C状态机,因此运行所需要的代码更少。

• eUSCI:增强型通用串行通信接口。MSP器件上提供的最先进通信外设,它改进了现有USCI功能,并且包含于所有MSP430FRxx (FRAM) MCU中。

当考虑使用一个具有I2C应用的MSP器件时,用户应该明白,代码结构会随着特定MSP系列器件上存在的外设而变化。每个变量包括必须考虑在内的不同寄存器、ISR和函数。还需要澄清的一点是,并不是所有的器件系列都使用同样的外设(USCI和eUSCI存在于MSP430F5xx/6xx中,USI和USCI存在于MSP430G2xx系列中,等等),这一点在用户参考系列用户指南时会感到很困惑。

因此,需要注意的一点是,在开始应用开发时,要根据实际情况来查看正确的材料,并选择合适的示例代码。德州仪器 (TI) 提供针对USI、USCI和eUSCI通信的基本I2C代码示例;这些代码示例可以在工具&软件->软件->示例 (Tools & software -> Software -> Examples) 下的MSP系列器件产品页面内找到(提供ZIP格式的文件,需要注意的是,这些软件包只包含与特定器件上存在的外设相关的代码示例)。对于那些使用USART,或者不包含一个通信外设的器件,社区技术支持内提供在线I2C位响应解决方案。不论是否使用外设,始终需要上拉电阻器来实现I2C通信。某些MSP器件具有内部上拉电阻器,不过不建议使用这些电阻器,因为几个从器件需要特定的、无法在内部满足的电阻值。

用MSP实现I2C的窍门

当试图用I2C在外设IC与MSP之间进行通信时,为了帮助避免常见的执行错误,以下的一些建议值得我们仔细地看一看:

• 从专门为你的MSP系列器件提供的示例I2C代码入手(产品页面-> Tools & software -> Software -> Examples)。查看根据系列用户指南对I2C寄存器的更改(一定要确保你查看的是正确的外设章节),这样的话,你就可以牢牢掌握实现通信所必须的更改。

• 使用从器件数据表中指定的上拉电阻和地址(有时会随着输入变量的不同而变化)。需牢记的一点是,从地址的7位被存储在这个字节的上7位,之后是由通信外设设定的一个R/W位,因此,在设置从地址寄存器时,这个值也许需要向左移动一位。

• 从写入一个寄存器开始,并且监视MSP器件中的ACK。利用故障标志和实验室设备来警告通信故障。使用CCS或IAR提供的调试工具来了解代码的运行方式,哪些寄存器被访问,何时访问函数/ISR,以及它们的访问方式。在完成了这些操作后,在添加寄存器读取功能性方面会变得更加容易。

• USCI/eUSCI状态图表示,在接收到最后一个字节前,需要设定UCTXSTP位。在只接收到一个字节的应用中,UCTXSTP位与UCTXSTT位一同设置。如果接收到多个字节,那么应该在接收到第N-1字节后设定UCTXSTP。这样就确保了在接收到最后一个字节后,立即发送停止序列。

调试建议

在放弃那些看起来似乎无法正确运行的代码前,以下是调试这个系统时需要考虑的某些关键点:

• 确认上拉电阻值&从地址值,用从器件数据表对它们进行验证。

• 再次检查通信外设初始化,其中包括:寄存器设置、正确的引脚分配、已使能中断、针对运行的外设接通/释放等。

• 使用任何提供的工具(IDE调试器、逻辑分析器、示波器等)来确认MSP430和从器件严格遵循I2C软件协议。

• 查看针对已知I2C问题的勘误表,并且查看勘误表说明是否与应用的故障症状相匹配。

• 研究E2E论坛内的问题,看一看有没有相似的情况已经被解决。尝试不同的I2C相关关键字组合,并且充分利用搜索过滤器。

E2E支持

如果适当的调试和研究方法没有成功,TI E2E社区论坛可以成为与器件专家进行直接沟通的极佳资源。无论遇到何种问题,一定要掌握与之相关的详细信息,以帮助社区成员和TI工程师更好地为请求提供技术支持,其中包括:

• MSP430系列器件
• 使用的LaunchPad或TI目标板,或者定制电路板的电路原理图
• 从器件
• 所发现情况或问题的准确描述
• 使用调试器的同时,所观察到的运行方式(CCS或IAR)
• I2C初始化和函数/ISR代码片段(并不是全部代码)
• 包含合适标签的逻辑分析器和示波器图像

资源

从USCI模块迁移至eUSCI模块 (SLAA522): http://www.ti.com/lit/an/slaa522a/slaa522a.pdf
使用USCI I2C主器件 (SLAA382): http://www.ti.com/lit/an/slaa382a/slaa382a.pdf
使用USCI I2C从器件 (SLAA383): http://www.ti.com/lit/an/slaa383/slaa383.pdf
使用I2C总线(博客): http://www.robot-electronics.co.uk/i2c-tutorial

原文链接: https://e2e.ti.com/blogs_/b/msp430blog/archive/2016/05/03/msp-i2c-gettin...

转自: 博乐Bar

围观 470

前言

在参考Cube软件包中I2C例程后, 根据应用需要新增了一路I2C接口,结果新增I2C无法收发数据。本文主要对问题进行描述,分析产生原因,提供解决方法。

一、问题描述

如前言所述,现象表现为I2C无法收发数据。得无法理解之处,在于之前已经完成了I2C的移植工作,并且运行正常。现在遵照正确的方式,新添一路I2C接口,只是更改了对应的I2C接口及引脚,为什么无法收发数据。简化测试程序如下。

GPIO_InitTypeDef GPIO_InitStruct;
 /* Enable GPIO TX/RX clock */
 I2Cx_SCL_GPIO_CLK_ENABLE();
 I2Cx_SDA_GPIO_CLK_ENABLE();
 /* Enable I2Cx clock */
 I2Cx_CLK_ENABLE();
 /*##-2- Configure peripheral GPIO ##########################################*/
 /* I2C TX GPIO pin configuration */
 GPIO_InitStruct.Pin = I2Cx_SDA_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
 GPIO_InitStruct.Alternate = I2Cx_SCL_SDA_AF;
 HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
 GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
 HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);

 I2cHandle.Instance = I2Cx;
 I2cHandle.Init.ClockSpeed = 100000;
 I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE;
 I2cHandle.Init.OwnAddress1 = 0;
 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 I2cHandle.Init.OwnAddress2 = 0;
 I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

 if(HAL_I2C_Init(&I2cHandle) != HAL_OK)
 {
 /* Initialization Error */
 Error_Handler();
 }
 while(1)
 {
 HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer,TXBUFFERSIZE, 10000);
 }

二 现象分析

将上述程序在STM32F469i-Disco板上实现,复现现象并寻找规律。发现规律如下:

I2C配置顺序引发的异常案例

分析上表可以发现问题的产生与硬件设计有一定关系。观察发现,如果I2C没有外部上拉时,会导致问题产生。

通过单步调试,定位于HAL_I2C_Master_Transmit(),在这个函数中调用的I2C_WaitOnFlagUntilTimeout()无法执行异常,返回HAL_BUSY,导致了I2C写功能失败。在I2C_WaitOnFlagUntilTimeout函数内部,是对忙标志位BUSY@I2Cx_SR2的检测。通过对参考手册的阅读(如下截图所述),如果在未占用I2C总线时,SDA或SCL引脚存在低电平,则意味着总线处于忙状态。这种检测机制在I2C接口失能时依然工作。

I2C配置顺序引发的异常案例

结合程序中调用顺序,在I2C3时钟使能时,虽然I2C3没有使能,但是忙状态检测已经开始。由于对应的SCL引脚上无上拉电阻,并且由于还未对I2C3的SCL引脚进行配置。此时SCL引脚为浮空输入状态,实际测量发现为低电平,BUSY标志被置位。

三 解决方法

通过现象及分析,可了解到问题可通过硬件或者软件解决。

硬件方面,为SDA、SCL引脚提供外部的I2C上拉电阻,问题不在出现。

软件方面,发现在对SCL、SDA引脚配置时会启用内部上拉。通过将I2C时钟使能代码放于I2C引脚配置语句后面,问题也不再出现。

需要注意, I2C的SDA、SCL引脚内部上拉电阻,为弱上拉。使用者可以通过对应型号STM32的数据手册,查看对应引脚的上拉电阻,以便判断是否能够满足应用需要。如下为STM32F469上拉电阻信息截图。

I2C配置顺序引发的异常案例

来源: STM32单片机

围观 807

作者:ce123

IICvs SPI

现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求制定了这两种标准通信协议。

IIC 开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互联方式。电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped I/O)的方式来互联微控制器和外围设备的。要实现内存映射,设备必须并联入微控制器的数据线和地址线,这种方式在连接多个外设时需大量线路和额外地址解码芯片,很不方便并且成本高。

为了节省微控制器的引脚和和额外的逻辑芯片,使印刷电路板更简单,成本更低,位于荷兰的Philips实验室开发了 ‘Inter-Integrated Circuit’,IIC 或 IIC ,一种只使用二根线接连所有外围芯片的总线协议。最初的标准定义总线速度为100kbps。经历几次修订,主要是1995年的400kbps,1998的3.4Mbps。

有迹象表明,SPI总线首次推出是在1979年,Motorola公司将SPI总线集成在他们第一支改自68000微处理器的微控制器芯片上。SPI总线是微控制器四线的外部总线(相对于内部总线)。与IIC不同,SPI没有明文标准,只是一种事实标准,对通信操作的实现只作一般的抽象描述,芯片厂商与驱动开发者通过data sheets和application notes沟通实现上的细节。
SPI

对于有经验的数字电子工程师来说,用SPI互联两支数字设备是相当直观的。SPI是种四根信号线协议(如图):

§ SCLK: Serial Clock (output from master);

§ MOSI; SIMO: Master Output, Slave Input(output from master);

§ MISO; SOMI: Master Input, Slave Output(output from slave);

§ SS: Slave Select (active low, outputfrom master).

SPI是[单主设备( single-master )]通信协议,这意味着总线中的只有一支中心设备能发起通信。当SPI主设备想读/写[从设备]时,它首先拉低[从设备]对应的SS线(SS是低电平有效),接着开始发送工作脉冲到时钟线上,在相应的脉冲时间上,[主设备]把信号发到MOSI实现“写”,同时可对MISO采样而实现“读”,如下图:

SPI有四种操作模式——模式0、模式1、模式2和模式3,它们的区别是定义了在时钟脉冲的哪条边沿转换(toggles)输出信号,哪条边沿采样输入信号,还有时钟脉冲的稳定电平值(就是时钟信号无效时是高还是低)。每种模式由一对参数刻画,它们称为时钟极(clock polarity)CPOL与时钟期(clock phase)CPHA。

[主从设备]必须使用相同的工作参数——SCLK、CPOL 和 CPHA,才能正常工作。如果有多个[从设备],并且它们使用了不同的工作参数,那么[主设备]必须在读写不同[从设备]间重新配置这些参数。以上SPI总线协议的主要内容。SPI不规定最大传输速率,没有地址方案;SPI也没规定通信应答机制,没有规定流控制规则。事实上,SPI[主设备]甚至并不知道指定的[从设备]是否存在。这些通信控制都得通过SPI协议以外自行实现。例如,要用SPI连接一支[命令-响应控制型]解码芯片,则必须在SPI的基础上实现更高级的通信协议。SPI并不关心物理接口的电气特性,例如信号的标准电压。在最初,大多数SPI应用都是使用间断性时钟脉冲和以字节为单位传输数据的,但现在有很多变种实现了连续性时间脉冲和任意长度的数据帧。

IIC

与SPI的单主设备不同,IIC 是多主设备的总线,IIC没有物理的芯片选择信号线,没有仲裁逻辑电路,只使用两条信号线—— ‘serial data’ (SDA) 和 ‘serial clock’ (SCL)。IIC协议规定:

§ 第一,每一支IIC设备都有一个唯一的七位设备地址;

§ 第二,数据帧大小为8位的字节;

§ 第三,数据(帧)中的某些数据位用于控制通信的开始、停止、方向(读写)和应答机制。

IIC 数据传输速率有标准模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps),另外一些变种实现了低速模式(10 kbps)和快速+模式(1 Mbps)。

物理实现上,IIC 总线由两根信号线和一根地线组成。两根信号线都是双向传输的,参考下图。IIC协议标准规定发起通信的设备称为主设备,主设备发起一次通信后,其它设备均为从设备。

IIC 通信过程大概如下。首先,主设备发一个START信号,这个信号就像对所有其它设备喊:请大家注意!然后其它设备开始监听总线以准备接收数据。接着,主设备发送一个7位设备地址加一位的读写操作的数据帧。当所设备接收数据后,比对地址自己是否目标设备。如果比对不符,设备进入等待状态,等待STOP信号的来临;如果比对相符,设备会发送一个应答信号——ACKNOWLEDGE作回应。

当主设备收到应答后便开始传送或接收数据。数据帧大小为8位,尾随一位的应答信号。主设备发送数据,从设备应答;相反主设备接数据,主设备应答。当数据传送完毕,主设备发送一个STOP信号,向其它设备宣告释放总线,其它设备回到初始状态。

基于IIC总线的物理结构,总线上的START和STOP信号必定是唯一的。另外,IIC总线标准规定SDA线的数据转换必须在SCL线的低电平期,在SCL线的高电平期,SDA线的上数据是稳定的。

在物理实现上,SCL线和SDA线都是漏极开路(open-drain),通过上拉电阻外加一个电压源。当把线路接地时,线路为逻辑0,当释放线路,线路空闲时,线路为逻辑1。基于这些特性,IIC设备对总线的操作仅有“把线路接地”——输出逻辑0。

IIC总线设计只使用了两条线,但相当优雅地实现任意数目设备间无缝通信,堪称完美。我们设想一下,如果有两支设备同时向SCL线和SDA线发送信息会出现什么情况。
基于IIC总线的设计,线路上不可能出现电平冲突现象。如果一支设备发送逻辑0,其它发送逻辑1,那么线路看到的只有逻辑0。也就是说,如果出现电平冲突,发送逻辑0的始终是“赢家”。
总线的物理结构亦允许主设备在往总线写数据的同时读取数据。这样,任何设备都可以检测冲突的发生。当两支主设备竞争总线的时候,“赢家”并不知道竞争的发生,只有“输家”发现了冲突——当它写一个逻辑1,却读到0时——而退出竞争。

10位设备地址

任何IIC设备都有一个7位地址,理论上,现实中只能有127种不同的IIC设备。实际上,已有IIC的设备种类远远多于这个限制,在一条总线上出现相同的地址的IIC设备的概率相当高。为了突破这个限制,很多设备使用了双重地址——7位地址加引脚地址(external configuration pins)。IIC 标准也预知了这种限制,提出10位的地址方案。

10位的地址方案对 IIC协议的影响有两点:

§ 第一,地址帧为两个字节长,原来的是一个字节;

§ 第二,第一个字节前五位最高有效位用作10位地址标识,约定是“11110”。

除了10位地址标识,标准还预留了一些地址码用作其它用途,如下表:

时钟拉伸

在 IIC 通信中,主设备决定了时钟速度。因为时钟脉冲信号是由主设备显式发出的。但是,当从设备没办法跟上主设备的速度时,从设备需要一种机制来请求主设备慢一点。这种机制称为时钟拉伸,而基于I²C结构的特殊性,这种机制得到实现。当从设备需要降低传输的速度的时候,它可以按下时钟线,逼迫主设备进入等待状态,直到从设备释放时钟线,通信才继续。

高速模式

原理上讲,使用上拉电阻来设置逻辑1会限制总线的最大传输速度。而速度是限制总线应用的因素之一。这也说明为什么要引入高速模式(3.4 Mbps)。在发起一次高速模式传输前,主设备必须先在低速的模式下(例如快速模式)发出特定的“High Speed Master”信号。为缩短信号的周期和提高总线速度,高速模式必须使用额外的I/O缓冲区。另外,总线仲裁在高速模式下可屏蔽掉。更多的信息请参与总线标准文档。

IIC vs SPI: 哪位是赢家?

我们来对比一下IIC 和 SPI的一些关键点:

第一,总线拓扑结构/信号路由/硬件资源耗费

IIC 只需两根信号线,而标准SPI至少四根信号,如果有多个从设备,信号需要更多。一些SPI变种虽然只使用三根线——SCLK, SS和双向的MISO/MOSI,但SS线还是要和从设备一对一根。另外,如果SPI要实现多主设备结构,总线系统需额外的逻辑和线路。用IIC 构建系统总线唯一的问题是有限的7位地址空间,但这个问题新标准已经解决——使用10位地址。从第一点上看,IIC是明显的大赢家。

第二,数据吞吐/传输速度

如果应用中必须使用高速数据传输,那么SPI是必然的选择。因为SPI是全双工,IIC 的不是。SPI没有定义速度限制,一般的实现通常能达到甚至超过10 Mbps。IIC 最高的速度也就快速+模式(1 Mbps)和高速模式(3.4 Mbps),后面的模式还需要额外的I/O缓冲区,还并不是总是容易实现的。

第三,优雅性

IIC 常被称更优雅于SPI。公正的说,我们更倾向于认为两者同等优雅和健壮。IIC的优雅在于它的特色——用很轻盈的架构实现了多主设备仲裁和设备路由。但是对使用的工程师来讲,理解总线结构更费劲,而且总线的性能不高。

SPI的优点在于它的结构相当的直观简单,容易实现,并且有很好扩展性。SPI的简单性不足称其优雅,因为要用SPI搭建一个有用的通信平台,还需要在SPI之上构建特定的通信协议软件。也就是说要想获得SPI特有而IIC没有的特性——高速性能,工程师们需要付出更多的劳动。另外,这种自定的工作是完全自由的,这也说明为什么SPI没有官方标准。IIC和SPI都对低速设备通信提供了很好的支持,不过,SPI适合数据流应用,而IIC更适合“字节设备”的多主设备应用。

小结

在数字通信协议簇中,IIC和SPI常称为“小”协议,相对Ethernet, USB, SATA, PCI-Express等传输速度达数百上千兆字节每秒的总线。但是,我们不能忘记的是各种总线的用途是什么。“大”协议是用于系统外的整个系统之间通信的,“小”协议是用于系统内各芯片间的通信,没有迹象表明“大”协议有必要取代“小”协议。IIC和SPI的存在和流行体现了“够用就好”的哲学。回应文首,IIC和SPI如此的流行,它是任何一位嵌入式工程师必备的工具。

文章来源: 极客头条

围观 255

页面

订阅 RSS - I2C