模拟IIC的时钟延展问题(Clock Stretching)

时钟拉伸(Clock stretching)

clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.clock stretching是可选的,实际上大多数从设备不包括SCL驱动,所以它们不能stretch时钟.

链接是IIC标准官网说明http://www.i2c-bus.org/clock-stretching/,贴到这里

Clock Stretching

In an I2C communication, the master device determines the clock speed. Unlike RS232 the I2C bus provides an explicit clock signal which relieves master and slave from synchronizing exactly to a predefined baud rate.

However, there are situations where an I2C slave is not able to co-operate with the clock speed given by the master and needs to slow down a little. This is done by a mechanism referred to as clock stretching.

An I2C slave is allowed to hold down the clock if it needs to reduce the bus speed. The master, on the other hand, is required to read back the clock signal after releasing it to the high state and wait until the line has actually gone high.

Bandwith

Clock stretching sounds a bit odd but is common practice. However, the total bandwidth of the shared bus might be significantly decreased. So, especially for I2C buses shared by multiple devices, it is important to estimate the impacts of clock stretching. So do not make the slowest I2C device dominate your bus performance.

Clock Stretching in High Speed Mode

Clock stretching in High-Speed-Mode is only allowed after the ACK bit (and before the 1st bit of the next byte). Stretching between bits 2-9 is illegal because the edges of these bits are boosted with an additional current source. See I2C specification Rev. 03 chapter 5.3.1 for further details.

    本人具体遇到的情况是从设备有Clock stretching功能,在调试DS90ub913与DS90ub914通过模拟IIC与DZ60通信事,914可是正常读写,而913不可以正常读写,换作DZ60硬件IIC却可以正常通信,最后在查找913规格书是才发现Clock Stretching问题,而之前本人没遇到过,还以为是硬件出了问题,实际就是从设备在高速模式下在应答位将clk时钟拉低,通知主设备等待,等从设备释放时钟后,主设备可继续发送命令。

现象(如下图):

       由于在发送读命令之后,即ACk之后,下面从设备需要准备数据时间,(大约10us,一个时钟的时间),此时还在I2C中断中,因此SCLK上是被拉低。由于主设备,并未检查该SCLK信号,导致下一个数据的第一个时钟信号被拉低,而不知道,而当做有效信号采样,结果导致数据采用出错;我们自己的主设备,采用硬件I2C,有判断总线是否占用和超时机制,故没有这个问题。

I2C的时钟可能被从设备拉低,从示波器看好像主少发了时钟(只有8个时钟,实际应该9个,最前面一个被从设备拉低了),实际是从设备拉低,这时候主设备最好检查时钟信号变高后,再发时钟信号脉冲!

(还在调试爱立信电源PMBUS问题:主发第九个时钟未检查总线,此时从设备把SCL拉低《此时从设备正在做相应数据处理,所以拉低总线》,导致ACK应答失败,从示波器看好像少发了第九时钟;方法发第九个时钟的时候检查SCL电平,发现它变高后,才发第九个时钟)

原因:通信中,从设备由于某种原因(数据处理或准备)拉低SCL时钟线(此时总线属于被占用状态),而主设备并未判断SCL的是否为高空闲,而继续通信,导致失败 

解决方法:在通信中,要随时检查SCL电平,当它为低的时候,需要超时等待,等它为高时候,再发新的SCL信号

 (即在代码中,主设置SCL为高后,要超时判断SCL是否为高,再发后面的时序)

具体可以在主机应答位检查子程序中进行程序的完善实现Clock Stretching功能;操作如下面红色标注:

//--------------------------------------------------------------------------------------------------  
// 函数名称: check_ACK  
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束  
//--------------------------------------------------------------------------------------------------  

int8u iic1_check_ACK(void)  
{   
    int8u check;
    int16u ucErrTime=0;
    SDA1 = 1;
    DelayUS(2);
    SCL1 = 1;

 /*****************************************添加部分*********************************************/ 
    DelayUS(10);
    while(0 == SCL1) //用于检测SCL stretch 需要将检测引脚与SCL短接
    {
      ucErrTime++;
      DelayUS(1);
      if(ucErrTime>1000)
      {
        ucErrTime = 0;
        break;
      }
    }
    DelayUS(10);
 /****************************************添加部分**********************************************/
    SDA1_Dir = 0;   //SDA设置为输入端口
    DelayUS(3);     //延时3us
    check = 0;
    if(SDA1 == 1)   // 若SDA1==1 表明非应答
      check = 1;
    SCL1 = 0;
    DelayUS(2);
    SDA1_Dir = 1;
    return check;   
}

另:个人认为硬件i2c有总线占用和超时判断,相对于模拟i2c更好; 但硬件i2c容易出现死锁的问题

  • 12
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值