I2C与SMBUS区别,及smbus实例

来源:互联网 发布:移动网络电视怎么样 编辑:程序博客网 时间:2024/05/21 06:55

(1)SMBus是一种二线制串行总线,1996年第一版规范开始商用。它大部分基于I2C总线规范。和 I2C一样,SMBus不需增加额外引脚,创建该总线主要是为了增加新的功能特性,但只工作在100KHZ且专门面向智能电池管理应用。它工作在主/从模式:主器件提供时钟,在其发起一次传输时提供一个起始位,在其终止一次传输时提供一个停止位;从器件拥有一个唯一的7或10位从器件地址。

      SMBus与I2C总线之间在时序特性上存在一些差别。首先,SMBus需要一定数据保持时间,而 I2C总线则是从内部延长数据保持时间。SMBus具有超时功能,因此当SCL太低而超过35 ms时,从器件将复位正在进行的通信。相反,I2C采用硬件复位。SMBus具有一种警报响应地址(ARA),因此当从器件产生一个中断时,它不会马上清除中断,而是一直保持到其收到一个由主器件发送的含有其地址的ARA为止。SMBus只工作在从10kHz到最高100KHZ。最低工作频率10kHz是由SMBus超时功能决定的。

(2)参照i2c时序图,才用smbus总线完成对应读写函数。

A,mma7660

 

static int mma7660_write_register( const u8 subAddress, u8 *bufP )
{
      int ret;
      unsigned long flags;
      spinlock_t *lock = get_i2c_lock();
      if( g_client == NULL || lock == NULL) /* No global client pointer? */
             return -1;

      spin_lock_irqsave(lock,flags);
      ret =  i2c_smbus_write_byte_data(g_client, subAddress, *bufP);  //写一个字节的数据
      spin_unlock_irqrestore(lock, flags);
      return ret;
}

static int mma7660_read_register( const u8 subAddress, u8 *bufP )
{
       int ret = 0;
       unsigned long flags; 
       spinlock_t *lock = get_i2c_lock();
       if( g_client == NULL || lock == NULL) /* No global client pointer? */
             return -1;
 

       spin_lock_irqsave(lock,flags);
       g_client->flags|=I2C_M_NOSTOP;  //注意写两个器件地址之间的SR,中间没有STOP,相当于重发。所以要置标志
       ret = i2c_smbus_write_byte(g_client, subAddress);   //写一次写命令地址,及子地址

       if(ret){
             printk("mma7660_read_register read error/r/n");
             spin_unlock_irqrestore(lock, flags);
             return ret;
       }
       ret = i2c_smbus_read_byte(g_client);//开始读,发个读命令地址
       g_client->flags&=(~I2C_M_NOSTOP);   //使用完后清该标志。此标志用不用与具体实例有关,有的器件两种都支持
       if (ret >= 0) {
             *bufP = ret;
       }

       spin_unlock_irqrestore(lock, flags);
       return ret;
}

 

B,DA9034

写时序与7660是相同的;读时序也基本一样,只不过中间的重发开始是可有可无,都支持。

int micco_read(u8 reg, u8 *pval)
{

       int ret;
       int status;
       unsigned long flags;
       spinlock_t *lock = get_i2c_lock();
       if (g_client == NULL || lock == NULL) /* No global client pointer? */
             return -1;

       spin_lock_irqsave(lock, flags);
       ret = i2c_smbus_read_byte_data(g_client, reg);
       if (ret >= 0) {
             *pval = ret;

             status = 0;

       }

       else

              status = -EIO;

       spin_unlock_irqrestore(lock,flags);

       return status;

}

该smbus总线函数与i2c总线的缺点在于,不能带读数据的数据长度参数。

 

参考原文:http://blog.csdn.net/wenlifu71022/archive/2009/08/20/4465339.aspx