《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 基于C8051F的SMBus串行通信的原理和实现
基于C8051F的SMBus串行通信的原理和实现
来源:电子技术应用2010年第5期
张媛媛 徐雪松 何怡刚
长沙湖南大学电气与信息工程学院(410082)
摘要: 在介绍C8051F串行通信总线SMBus的特点及功能的基础上,重点介绍了其协议、总线仲裁、寄存器以及C8051F02x与多个EEPROM串行通信的实现,并给出了部分应用程序。
Abstract:
Key words :

摘 要: 在介绍C8051F串行通信总线SMBus的特点及功能的基础上,重点介绍了其协议、总线仲裁、寄存器以及C8051F02x与多个EEPROM串行通信的实现,并给出了部分应用程序。
关键词: C8051F单片机  片上系统  SMBus总线  总线仲裁

  由于MCU具有小巧灵活、价格低廉的特点,所以在控制系统、嵌入式系统等领域中得到广泛应用。这些应用中,数据传输总线的选择是重要的环节。并口传输速度虽快,但是实现时需要较多的I/O口,而许多应用系统的设计又必须兼顾低成本、高可靠性、高效率三方面,所以经常要求在一个或几个单片机和若干外围器件之间传送短的数据。目前,大部分C8051F单片机中都集成了SMBus(System Management Bus)总线,主要是希望通过一条廉价并且功能强大的总线(由二条线组成)控制主板上的设备并收集相应的信息。使用 SMBus 的系统中,设备之间发送和接收消息都是通过 SMBus,而不是使用单独的控制线,这样可以节省设备的管脚数。SMBus的数据传输率比较低,可允许单一主机与多个从设备同时收发数据。
1  系统管理总线SMBus
  SMBus是1995年由Intel提出的一种双线通信专利技术,它完全符合系统管理总线规范1.1版,与I2C串行总线兼容。系统控制器对总线的读写操作都是以字节为单位,由SMBus接口自动控制数据的串行传输。SMBus可以工作在主方式和(或)从方式,一个总线上可以有多个主器件。SMBus提供SDA(串行数据)控制、SCL(串行时钟)产生和同步、仲裁逻辑以及起始/停止的控制和产生电路。有三个与之相关的特殊功能寄存器:配置寄存器SMB0CF、控制寄存器SMB0CN及用于发送和接收数据的数据寄存器SMB0DAT。
1.1 SMBus协议
  SMBus有二种可能的数据传输类型:从主发送器到所寻址的从接收器(写)和从被寻址的从发送器到主接收器(读)。这二种数据传输都由主器件启动,主器件还提供串行时钟。SMBus接口可以工作在主方式或从方式。总线上可以有多个主器件,如果二个或多个主器件同时启动数据传输,则仲裁机制保证有一个主器件会赢得总线。
  一次典型的SMBus数据传输包括一个起始条件(Start)、一个地址字节(位7~1:7位从地址;位0:R/W方向位)、一个或多个字节的数据和一个停止条件(Stop)。方向位占据地址字节的最低位,当被设置为逻辑1时表示这是一个“读”(READ)操作,为逻辑0时表示这是一个“写”(WRITE)操作。
  所有的数据传输都由主器件启动,可以寻址一个或多个目标从器件。主器件产生一个起始条件,然后发送地址和方向位。如果本次数据传输是一个从主器件到从器件的写操作,则主器件每发送一个数据字节后等待来自从器件的确认。如果是一个读操作,则由从器件发送数据并等待主器件的确认。在数据传输结束时,主器件产生一个停止条件,结束数据交换并释放总线。
1.2 总线仲裁
  一个主器件只能在总线空闲时启动一次传输。在一个停止条件之后或SCL和SDA保持高电平已经超过了指定时间时,总线是空闲的。二个或多个主器件可能在同一时刻产生起始条件。由于产生起始条件的器件并不知道其他器件也正想占用总线,所以使用仲裁机制迫使一个主器件放弃总线。这些主器件继续发送起始条件,直到其中一个主器件发送高电平,而其他主器件在SDA上发送低电平。赢得总线的器件继续其数据传输过程,而未赢得总线的器件成为从器件。该仲裁机制是非破坏性的,因为总会有一个器件赢得总线,不会发生数据丢失。
1.3 SMBus数据传输方式
  SMBus接口可以被配置为工作在主方式和(或)从方式。在某一时刻,它将工作在下述四种方式之一:主发送器、主接收器、从发送器或从接收器。在本文的应用举例中,SMBus工作在主发送器和主接收器模式下。下面以中断驱动的SMBus0应用为例来重点说明这二种工作方式。当然SMBus0也可以工作在查询方式。
  (1)主发送器方式
  在SDA上发送串行数据,在SCL上输出串行时钟。SMBus0接口首先产生一个起始条件,然后发送含有目标从器件地址和数据方向位的第一个字节。在这种情况下数据方向位(R/W)为逻辑0,表示这是一个“写”操作。SMBus0接口发送一个或多个字节的串行数据,并在每发送完一个字节后等待由从器件产生的确认信号(ACK)。最后,为了指示串行传输的结束,SMBus0产生一个停止条件。
  (2)主接收器方式
  在SDA上接收串行数据,在SCL上输出串行时钟。SMBus0接口首先产生一个起始条件,然后发送含有目标从器件地址和数据方向位的第一个字节。在这种情况下数据方向位(R/W)应为逻辑1,表示这是一个“读”操作。SMBus0接口接收来自从器件的串行数据并在SCL输出串行时钟。每收到一个字节后,SMBus0接口根据寄存器SMB0CN中AA位的状态产一个ACK或NACK。最后,为了指示串行传输的结束,SMBus0产生一个停止条件。
1.4 SMBus特殊功能寄存器
  对SMBus串行接口的访问和控制是通过5个特殊功能寄存器来实现的:控制寄存器SMB0CN、时钟速率寄存器SMB0CR、地址寄存器SMB0ADR、数据寄存器SMB0DAT和状态寄存器SMB0STA。SMB0DAT将保存要发送或刚接收的串行数据字节;SMB0CR时钟速率寄存器用于控制主方式下串行时钟SCL的频率;SMB0ADR保存SMBus0接口的从地址。下面将重点介绍控制寄存器和状态寄存器。
  (1)控制寄存器SMB0CN
SMBus控制寄存器SMB0CN用于配置和控制SMBus0接口,操纵所有SMBus的状态信息。它包括起始标志(STA)、停止标志(STO)、确认(AA)、中断标志(SI)和超时允许等。该寄存器中的所有位都可以用软件读或写,有二个控制位SI和STO受SMBus0硬件的影响。图1为SMBus控制寄存器图。

  (2)状态寄存器SMB0STA
  状态寄存器SMB0STA保存一个8位的状态码,用于指示SMBus0接口的当前状态,共有28个可能的SMBus0状态,每个状态有一个惟一的状态码与之对应。状态码的高5位是可变的,而一个有效状态码的低3位固定为0(当SI=1时),因此所有有效的状态码都是8的整数倍,这使得在软件中用状态码作为转移到正确的中断服务程序的索引变得很容易。在本文的应用举例中,SMBus主要工作在主发送器、主接收器和主发送器/主接收器方式,并且在中断服务程序中用到了这些状态码。
2  SMBus通信实现
  C8051F具有与8051兼容的高速CIP-51内核,与MCS-51指令集完全兼容。除了具有标准8051数字外设部件之外,片内还集成了数据采集和控制系统中常用的模拟部件和其他数字外设及功能部件,是真正的混合信号片上系统。所以,该例中用C8051F020通过SMBus与三个16位地址空间的8KB字节E2PROM进行通信传输。它们之间由SCL和SDA连接起来。多个E2PROM的通信配置如图2所示。将C8051F020设置为主发送器,chip_A、chip_B、chip_C设置为从接收设备。有A0~A2三个地址选择管脚用来设置E2PROM的地址。高四位统一设置为‘0101’,低四位分别是000.001.010。所以从设备的地址是:chip_A=1010000,chip_B=1010001,chip_C=1010010。

  由于E2PROM有二个字节的地址空间,这意味着在READ和WRITE操作过程中要多传送一个字节的地址(如图3所示)。当中断服务程序收到“数据已传输,接收到ACK”的状态信号时,它必须知道已传送的是高地址字节、低地址字节还是数据字节。程序中,BYTE_NUMBER变量将保存该信息。

  下面的程序为SMBus写函数SM_Send,它一次将一字节写入指定的E2PROM中;SMBus读函数SM_Receive,它将从指定的E2PROM中读出一字节信息;最后,给出了中断服务程序。
//SMBus写函数
//chip_select为被写的设备E2PROM的地址
//byte_address为被读的存储单元的地址
//out_byte为要写入存储单元的数据
void SM_Send(char chip_select,unsigned int byte_address,
char out_byte)
{
while(SM_BUSY);  //等待SmBus空闲
SM_BUSY=1;    //占用SMBus总线
SMB0CN=0x44;     //使能SMBus,在应答周期内返回确认
BYTE_NUMBER=2;                              //地址为二字节
COMMAND=(chip_select | WRITE);  //Chip select+ WRITE
HIGH_ADD=((byte_address >> 8) & 0xFF); //高八位地址
LOW_ADD=(byte_address & 0xFF);  //低八位地址
WORD=out_byte;//写数据
STO=0;     //发送一个停止条件
STA=1;     //开始传输数据
}
//SMBus读函数
//chip_select为被读设备E2PROM的地址
//byte_address为被读存储单元的地址
char SM_Receive(char chip_select,unsigned int byte_address)
{
while(SM_BUSY);  //等待总线空闲;
SM_BUSY=1;   //占用SMBus;
SMB0CN=0x44;  //使能enabled,在应答周期内返回确认
BYTE_NUMBER=2;
COMMAND=(chip_select | READ);//Chip select+ READ
HIGH_ADD=((byte_address >> 8) & 0xFF);
LOW_ADD=(byte_address & 0xFF);
STO=0;
STA=1;
while(SM_BUSY);   //等待传输完毕
return WORD;
}
          //SMBus中断服务程序
void SMBUS_ISR (void) interrupt 7
{
  switch(SMB0STA){  //SMBus的状态码(SMB0STA寄存器)
     case SMB_START:  //SMB_START=0x08
        SMB0DAT=(COMMAND & 0xFE);//将从地址+R/W
                   //装入到SMB0DAT
     STA=0;                                //STA清‘0’
      break
        case SMB_RP_START:  //SMB_RP_START=0x10
     SMB0DAT=COMMAND;  //将从地址+R装入
                                                            //到SMB0DAT
     STA=0;
      break;
        case SMB_MTADDACK:  //SMB_MTADDACK=0x18
     SMB0DAT=HIGH_ADD;  //将高地址装入SMB0DAT
     break;
     case SMB_MTADDNACK:   //SMB_MTADDNACK=0x20
     STO=1;    //确认查询重试
     STA=1;
     break;
     case SMB_MTDBACK:  //SMB_MTDBACK=0x28
     switch (BYTE_NUMBER){
   case 2:        //如果BYTE_NUMBER=2,仅高地址已发送
    SMB0DAT=LOW_ADD;
    BYTE_NUMBER--;
       break;
      case 1:       //如果BYTE_NUMBER=1,LOW_ADD已发送
      if(COMMAND & 0x01){  //如果R/W=READ,
               //重复发送START
           STO=0;
           STA=1;
      } else {
           SMB0DAT=WORD;  //如果R/W=WRITE,
           //准备发送数据字节
           BYTE_NUMBER--;
        }
        break;
     default:     //如果BYTE_NUMBER=0,传输结束
     STO=1;
     SM_BUSY=0;  //释放SMBus
     }
     break;
case SMB_MTDBNACK://SMB_MTDBNACK=0x30
     STO=1;    //重试传输,置为STO
     STA=1;
     break;
case SMB_MTARBLOST://SMB_MTARBLOST=0x38
     STO=1;    //重试传输
     STA=1;
     break;
case SMB_MRADDACK://SMB_MRADDACK=0x40
     AA=0;   //清AA,等待接收数据
     break;
case SMB_MRADDNACK://SMB_MRADDNACK=0x48
     STO=0;   //确认查询重试
     STA=1;
     break;

case SMB_MRDBACK: //SMB_MRDBACK=0x50
     STO=1;
     SM_BUSY=0;
     break;
     case SMB_MRDBNACK://SMB_MRDBNACK=0x58
     WORD=SMB0DAT;
     STO=1;
     SM_BUSY=0;  //释放SMBus
     break;

default:
     STO=1;     //重新安排通讯
     SM_BUSY=0;
     break;
}
SI=0;                                       //清中断标志
}
3  结束语
  SMBus具有可靠性高以及接线方便的特点,而且具有SMBus总线接口的外围芯片也很多,所以应用起来非常方便。在本文应用举例中,实现了二个以上的多设备通信。但需要注意的是:在主发送、接收方式下,一旦SMBus检测到仲裁丢失,会立即释放SDA和SCL线。以后如未检测到停止条件,可能会引起死循环。为此,应使用软件超时来控制这种情况,以保证系统能够退出。
参考文献
1   CygnalC8051Fxxx数据手册.www.xhl.com.cn,2002,12
2   郝冬妮,孙立春,李晶皎.基于MCU的I2C总线传输设计. 单片机与嵌入式系统,2003;(6)
3   潘琢金.C8051F高速SOC单片机原理及应用.北京:北京航空航天大学出版社,2000
 

此内容为AET网站原创,未经授权禁止转载。