研究I2C总线多主通信与软件设计

时间:2011-09-04

   

    I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器MCU)及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点,现已得到广泛的应用。它除了可以进行简单的单主节点通信外,还可以应用在多主节点的通信系统中。在多主节点通信系统中,如果两个或者更多的主节点同时启动数据传输,总线具有冲突检测和仲裁功能,保证通信正常进行并防止数据破坏。现在许多微控制器都具有I2C总线接口,能方便地进行I2C总线设计。对于没有I2C总线接口的MCU,可以采用两条I/O接口线进行模拟。目前,一些介绍模拟I2C的资料主要讲的是在单主节点系统中进行的通信,这使得模拟I2C总线的应用具有一定的局限性。本文根据总线仲裁的思想,提出一种多主节点通信的思想及实现流程。


1 I2C总线系统简介

     I2C总线系统是由SCL(串行时钟)和SDA(串行数据)两根总线构成的。该总线有严格的时序要求,总线工作时,由串行时钟线SCL传送时钟脉冲,由串行数据线SDA传送数据。除此之外,I2C总线系统还有每个连接到总线的器件都可以通过的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;串行的8 位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;连接到相同总线的IC 数量只受到总线的电容400pF 限制等特征。总线协议规定,各主节点进行通信时都要有起始、结束、发送数据和应答信号。这些信号都是通信过程中的基本单元。总线传送的每1帧数据均是1个字节,每当发送完1个字节后,接收节点就相应给一应答信号。协议规定,在启动总线后的第1个字节的高7位是对从节点的寻址地址,第8位为方向位(“0”表示主节点对从节点的写操作;“1”表示主节点对从节点的读操作),其余的字节为操作数据。由于连接到I2C 总线的器件有不同种类的工艺(CMOS、NMOS、双极性),逻辑0(低)和逻辑1(高)的电平不是固定的,它由电源VDD的相关电平决定,每传输一个数据位就产生一个时钟脉冲。

  I2C总线术语包括,发送器:发送数据到总线的器件;接收器:从总线接收数据的器件;主机:初始化发送产生时钟信号和终止发送的器件;从机:被主机寻址的器件;多主机:同时有多于一个主机尝试控制总线但不破坏传输;仲裁:是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使传输不被破坏的过程;同步:两个或多个器件同步时钟信号的过程 。

  图1列出I2C总线上几个基本信号的时序。图1中包括起始信号、停止信号、应答信号、非应答信号以及传输数据“0”和数据“1”的时序。SCL 线是高电平时,SDA 线从高电平向低电平切换,这个情况表示起始条件;SCL 线是高电平时,SDA 线由低电平向高电平切换,这个情况表示停止条件。起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态。起始和停止条件,在停止条件的某段时间后总线被认为再次处于空闲状态。如果产生重复起始条件而不产生停止条件,总线会一直处于忙的状态,此时的起始条件(S)和重复起始条件(Sr)在功能上是一样的。应答信号是在SCL为高时SDA为低;非应答信号则与之相反。传输数据“0”和数据“1”与发送应答位和非应答位时序图是相同的。


图1 I2C总线上基本信号的时序

    图2表示了一个完整的数据传送过程。在I2C总线发送起始信号后,发送从机的7位寻址地址和1位表示这次操作性质的读写位,在有应答信号后开始传送数据,直到发送停止信号。数据是以字节为单位的。发送节点每发送1个字节就要检测SDA线上有没有收到应答信号,有则继续发送,否则将停止发送数据。


图2 完整的数据传送过程

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

2 I2C总线的仲裁

    在多主的通信系统中。总线上有多个节点,他们都有自己的寻址地址,能作为从节点被别的节点访问,同时他们都能作为主节点向其他的节点发送控制字节和传送数据。不过如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I2C总线上的仲裁。

  在以下几种情况下,I2C总线仲裁会失败。

  (1)在地址或数据发送周期,当主设备输出“1”,而SDA被采样为“0”。

  (2)在数据接收周期的应答位,当主设备输出“1”,而SDA被采样为“0”。

  (3)当总线忙时,企图有一个START。

  (4)在从模式中,企图有一个Repeat START。

  (5)检测到一个STOP,而主设备并没有STOP请求。

  如果I2C控制器工作在主模式,输出SDA信号将会与输入SDA信号进行比较以确定总线仲裁是甭失效。在数据传输过程中,SDA信号仅在SCL为高电平的时被检查(ACK周期除外),以确保START/STOP不会在错误的时间内产生。如果发现输出SDA与输入SDA不同,则总线仲裁失败,这时MAL位被置位。同时CoolRunner-II I2C控制器切换到从模式并复位MSTA位。

  CoolRunner-II fc控制器在总线忙时不会产生START,然而如果在总线忙时,uC依然发出START/Repeat START请求,则MAL位将会被置位。另外,在主设备没有发出STOP请求时,MAL仍然因为STOP被检测到而置位。这些都被视为仲裁失败,应该避免,并正确处理。

  如果仲裁失败发生在字节传输过程中,SOL会一直产生,直到字节传输完成。

  I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。SCL同步是由于总线具有线“和”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“和”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号。这就是SCL的同步原理。

  SDA线的仲裁也是建立在总线具有线“和”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据和自己发送的是否一致。是,继续发送;否则,退出竞争。图3中给出了两个节点在总线上的仲裁过程。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时,能够正常通信并且不丢失数据。所以当一个节点发送数据时,每发送一位数据后,都需要判断总线上所呈现的数据是否与自己发送的一致,如果不一致,放弃发送;否则,继续发送。

    图3是以两个节点为例的仲裁过程。DATA1和DATA2分别是主节点向总线所发送的数据信号,SDA为总线上所呈现的数据信号,SCL是总线上所呈现的时钟信号。当主节点1、2同时发送起始信号时,两个主节点都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号和自己发送的信号相同,继续发送数据。第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“和”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不相同,就断开数据的输出级,转为从机接收状态。这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据和主节点2所发送的数据相同,而主节点1在转为从节点后继续接收数据,同样也没有丢掉SDA线上的数据。因此在仲裁过程中数据没有丢失。


图3 两个主节点的仲裁过程


3 多主通信的原理及其实现流程

    多主通信就是在总线上有多个节点。这些节点既能作为主节点访问其他的节点,也能作为从节点被其他节点访问。当有多个节点同时企图占用总线时,就需要总线的仲裁。对于模拟I2C总线系统,怎样去实现总线的仲裁是目前研究模拟I2C总线系统的难点。有些人提出在系统中增加1根BUSY线,在占用总线之前先检测BUSY线,看总线是否被占用。若总线空闲,则设置BUSY线并向总线上传送数据;否则,接收数据,直到总线空闲时才占有总线。这种实现多主通信的方法有两个缺点:① 因为I2C的好处就是接口少、效率高,这样做不仅增加了使用资源而且减少了I2C总线的优势;② 当主节点数比较多时,等待时间较长,效率不高。本设计根据总线的仲裁原理,提出一种基于延时比较的仲裁方法。当主节点想要占用总线时,先检测总线上是否空闲,如果总线是空闲的就发送数据。在发送数据的同时,将总线上的数据接收并和发送的数据进行比较。如果不同,说明总线上同时还存在其他节点,那么就退出;否则,一直到发送完数据。这种方法既体现了I2C总线的高效性,同时还具有良好的扩展性。



图4 多主通信流程

    图4给出了基于延时比较的多主通信流程,其中MCU作为从节点部分的流程在图5中给出。在节点发送起始信号之前先要检测一下总线上是否为空闲状态(BUSY是否为0)。这里使用的检测方法是,持续检测一段时间看总线上的电平是否一直为高,若是说明总线上为闲状态,否则说明有其他的节点正在使用总线,要等一段时间再发送。当总线空闲时,发送起始信号,接着发送要访问的从节点的地址字节。每发送1位数据就接收比较1次,看发送和接收的是否一致,若是则继续,否则跳出到从节点的接收状态。如果没有产生冲突,MCU作为主节点继续发送数据,一直到任务结束,然后发送停止信号并返回。如果数据不相同,则MCU将跳转到从节点状态。由于在跳转到从节点接收状态的过程中累加器(ACC)和工作寄存器(Ri)的数据没有发生变化,所以数据不会丢失,作为从节点能继续接收总线上的数据。这样整个通信的过程没有中断,数据也没有丢失。



图5 从节点部分的流程

    图5给出了从节点的流程。进入从节点时,要将BUSY置为高,说明MCU目前正在工作,不能完成其他的任务。在MCU作为从节点完成接收任务后,则要将BUSY置为低。MCU在接收到寻址字节后和自己的地址字节进行比较。如果是访问自己的就进入到下面的接收程式,否则跳出。在访问自己的时候,还要判断主节点是读数据还是写数据,以便进入相应的程式。在写字节的子程式中,从节点每发送1个字节的数据后都要察看是否有应答信号(ACK),有则说明数据接收到了;否则要跳出等待,重新发送。在读字节的子程式中,每接收1个字节的数据就要发送1个应答信号(ACK),以示接收正常,否则主节点将停止继续发送。在现有的资料中,关于从节点的原理和原始码比较少,这里给出作为从节点时写字节子程式的原始码。由于篇幅有限其他的子程式没有列出。

4 部分源代码

    本节是在微控制器多主通信中的部分原始码。多主通信的实现中有几个难点和重点。一是在作为主节点时的写字节子程式,里面要包括发送的每位数据和总线的数据进行比较并做出判断。如果数据不同,要跳出并进入从节点的状态。由于子程式返回主程式时改动的只是PC的值而累加器(ACC)和工作寄存器(Ri)里面的值是不变的,因此微控制器进入从机状态后继续接收总线剩下的数据,这样总线的数据并没有丢失。二是作为从节点时的写字节的子程式。由于时钟线是由主节点的微控制器控制的,所以怎样根据SCL(串行时钟)线来读取SDA(串行数据)线的数据是其中的一个难点。三是在具有子地址的从节点关于是写字节还是读字节时的判断。如果是写字节时主节点会给出新的起始信号,并再次发送从节点的地址数据。这时从节点需要做出判断是读取数据还是写数据,并进入相应的子程式。这里给出以上三个重点和难点的子程式的原始码,以供读者参考。这些原始码经实践证实都是正确的。

  主节点的写字节子程序:

  ;其中的NOP可根据时钟的快慢自己加减

  WRBYTE:MOV R0,#08H

  CLR BUSY;将BUSY值清零

  WLP:  RLC A;取数据位

  JC   WR1

  SJMP WR0;判断数据位

  WLP1: DJNZ R0,WLP

  NOP

  OUT1: RET

  WR1:  SETB SDA;发送1

  NOP

  SETB  SCL

  MOV  C,SDA;判断是否与发送的数据相同

  JC   GOON

  SETB  BUSY

  AJMP  OUT1

  GOON: NOP

  NOP

  NOP

  CLR SCL

  SJMP WLP1

  1

  NOP

  SCL

  NOP

  NOP

  NOP

  NOP

  NOP

  CLR

  SCL

  SJMP  WLP1

  从节点的写字节子程序(返回为ACK):

  SWRBYTE:MOV R0,#08H

  WAGAIN: RRC A

  MOV B,#37H

  WWAIT1: JB SCL,WWAIT1;等待SCL为低

  JC WR1;判断是发送“1”还是发送“0”

  SETB SDA;发送“1”

  AJMP COM

  WR1:  CLR SDA;发送“0”

  COM:  DJNZ R0,WWAIT2;判断是否发送完毕

  WWAIT3: JNB SCL,WWAIT3;发送完毕等待应答信号

  WWAIT4: JB SCL,WWAIT4

  WWAIT5: JNB SCL,WWAIT5

  CLR ACK

  JB  SDA,ST0

  SETB ACK

  ST0:  RET;返回

  WWAIT2: JNB SCL,WWAIT2;等待SCL为高

  SJMP WAGAIN

  从节点的读字节同时判断是否有起始信号的子程序。如果有起始信号,则转为写字节子程序:

  SRDBYTE:MOV R0,#08H

  SETB 20H;设置标志位判断是读还是写

  SETB SDA;释放总线

  RWAITJ: JNB SCL,RWAITJ;等待SCL为高

  MOV C,SDA;从总线上读取数据

  RRC A;存入累计器

  DEC R0

  MOV C,ACC.7;判断是否为起始信号

  JNC RWAITJ1;为低继续读取数据

  REWAIT: JNB SCL,RWAITJ1;开始判断是否为起始信号

  JB  SDA,REWAIT

  CLR 20H;是,则清标志位并返回

  AJMP SjRDOUT

  RWAITJ1:JB SCL,RWAITJ1;等待SCL为低

  RWAITJ3:JNB SCL,RWAITJ3;等待SCL为高

  MOV C,SDA

  RRC A

  DJNZ R0,RWAITJ2

  SjRDOUT:RET

  RWAITJ2:JB SCL,RWAITJ2;等待SCL为低继续读数据

  SJMP RWAITJ3

  5 总结

  根据总线协议中的仲裁原理,提出的基于延时比较的模拟I2C多主通信的方法,不仅能够体现了I2C总线的高效性,而且还具有良好的扩展性。他使普通不具有I2C接口的MCU能应用在多主通信的系统中,既增加了普通MCU的使用范围,又突破了模拟I2C总线的应用局限性,为I2C总线的推广起到了积极的作用。



  
上一篇:Windows CE开设计之历史简介
下一篇:设计热电表流量自动标定系统

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料