设为首页收藏本站自媒体平台

研发设计门户网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 232|回复: 0

I2C时钟延展 ZT

[复制链接]

58

主题

66

帖子

376

积分

特邀技术专家

Rank: 9Rank: 9Rank: 9

积分
376
发表于 2023-3-21 16:35:37 | 显示全部楼层 |阅读模式

高速电路PCB网,专注于嵌入式方案,信号完整性和电源完整性仿真分析,高速电路PCB设计,各种EDA工具(Cadence\Mentor\\AD\\CAM\ANSYS HFSS)交流学习。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x



时钟拉伸(Clock stretching)

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


  某人在调试DS90ub913与DS90ub914通过模拟I2C与DZ60通信时,914可是正常读写,而913不可以正常读写,换作DZ60硬件IIC却可以正常通信,最后在查找913规格书是才发现Clock Stretching问题,实际就是从设备在高速模式下在应答位将clk时钟拉低,通知主设备等待,等从设备释放时钟后,主设备可继续发送命令。

现象(如下图):

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


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

原因:通信中,从设备由于某种原因(数据处理或准备)拉低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;   
}

全文转自:

https://blog.csdn.net/liuligui5200/article/details/80900951




该帖已经同步到研发自媒体平台 水手的微博
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

内容正在加载中,请稍候……

QQ|我的微博|小黑屋|手机版|Archiver|YanFa.Tech(gaosupcb Inc.)    

GMT+8, 2024-3-28 08:37 PM , Processed in 0.059927 second(s), 28 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表