打印
[STM32]

怎么根据时序参数确定IIC的延时啊

[复制链接]
5301|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
沙发
c834706901|  楼主 | 2018-11-18 23:17 | 只看该作者
有人教教我吗,教会我50元红包 加Q直接发

使用特权

评论回复
板凳
ayb_ice| | 2018-11-19 08:40 | 只看该作者
最简单的方法,高低电平各延时2US,读取数据时延时1US

使用特权

评论回复
地板
c834706901|  楼主 | 2018-11-19 10:45 | 只看该作者
ayb_ice 发表于 2018-11-19 08:40
最简单的方法,高低电平各延时2US,读取数据时延时1US

你是怎么判断延时这么长时间的呢

使用特权

评论回复
5
ayb_ice| | 2018-11-19 11:39 | 只看该作者
c834706901 发表于 2018-11-19 10:45
你是怎么判断延时这么长时间的呢

上面不是写的
SCL高电平时间吗,最小0.6,可以大于这个时间,不可以小于这个时间,所以2US是合适的。。。

使用特权

评论回复
6
ningling_21| | 2018-11-19 11:54 | 只看该作者
c834706901 发表于 2018-11-18 23:17
有人教教我吗,教会我50元红包 加Q直接发

不能小于0.6US,可以大于

使用特权

评论回复
7
c834706901|  楼主 | 2018-11-19 12:15 | 只看该作者
ayb_ice 发表于 2018-11-19 11:39
上面不是写的
SCL高电平时间吗,最小0.6,可以大于这个时间,不可以小于这个时间,所以2US是合适的。。。 ...

下面的sda保持时间和有效时间是什么意思是,有什么作用吗

使用特权

评论回复
8
ningling_21| | 2018-11-19 13:35 | 只看该作者
本帖最后由 ningling_21 于 2018-11-19 13:36 编辑
c834706901 发表于 2018-11-19 12:15
下面的sda保持时间和有效时间是什么意思是,有什么作用吗

保持时间:MCU输出数据到SDA线,并要维持该数据电平的时间长度有效时间:MCU输出的数据电平,能被外部器件识别到的时间长度,不在这个时间范围内可能识别不了

使用特权

评论回复
9
雪山飞狐D| | 2018-11-19 16:55 | 只看该作者
c834706901 发表于 2018-11-19 10:45
你是怎么判断延时这么长时间的呢

I2C  大部分器件是SCL 100K ,小部分高速是400K,为了通用,SCL频率要小于100K即可

使用特权

评论回复
10
雪山飞狐D| | 2018-11-19 17:02 | 只看该作者
本帖最后由 雪山飞狐D 于 2018-11-19 17:46 编辑
c834706901 发表于 2018-11-19 12:15
下面的sda保持时间和有效时间是什么意思是,有什么作用吗

SDA的保持时间是指I2C时钟进入到0电位时,MUC上数据SDA保持上一次的逻辑电平不改变的时间,以便I2C器件进行数据采样输入有一个稳定性

使用特权

评论回复
11
雪山飞狐D| | 2018-11-19 17:11 | 只看该作者
本帖最后由 雪山飞狐D 于 2018-11-19 17:14 编辑
c834706901 发表于 2018-11-19 12:15
下面的sda保持时间和有效时间是什么意思是,有什么作用吗

SDA 有效时间是指,当SLC时钟跳变成0电平时,I2C器件会在这个有效时间内进行逻辑电平跳变,输出下一个数据,你的数据手册上描述对象应该是指I2C本身器件的特性,按照这个特性给单片机适量的延迟就可以了,12周期的51单片机可能都不需要延迟,本身指令周期都是1uS 了,最好买个USB逻辑分析仪,边写边对着时序就容易调通了

使用特权

评论回复
12
玄德| | 2018-11-20 21:18 | 只看该作者

启动或者读写数据的时候延时多少

这句话是什么意思? 你究竟想知道什么参数?


使用特权

评论回复
13
Prry| | 2018-11-21 00:26 | 只看该作者
将时序抽象出来,方便移植。一般i2c器件都是标准400K,用100K基本通用所有器件。
参考:
https://blog.csdn.net/qq_20553613/article/details/78878211

使用特权

评论回复
14
qinlu123| | 2018-11-21 10:17 | 只看该作者
让IIC一直发用示波器看着SCL和SDA调就行了,计算+实验。

使用特权

评论回复
15
c834706901|  楼主 | 2018-11-23 09:07 | 只看该作者
玄德 发表于 2018-11-20 21:18
启动或者读写数据的时候延时多少

这句话是什么意思? 你究竟想知道什么参数?

我就是想知道delay(4) delay(2)这些延时是怎么得出来的

使用特权

评论回复
16
玄德| | 2018-11-23 14:33 | 只看该作者

一定要先搞明白:
这个时间是芯片自己的行为,还是芯片对你的要求。这很重要。


比如 tsu 这个参数,它是 对“Data In”的规定,所以是对外界、对工程师的要求,
你操作芯片时必须满足这个要求,芯片才能正常接受你的数据。
最小值是 100ns ,意思是:
你在发出 SCL 的上升沿之前,必须把数据的值提前放在 SDA 线上,而且至少提前 100ns;
芯片只关心最小值,所以没有给出最大值,你提前比如 200ns、300ns、1000ns 甚至 1 秒都可以。自己看情况,选个合适的数。

比如 tvd:
这是芯片自身的行为, SCL 的下降沿是“你”提供的,芯片将在这个时间里,把内部数据放在 SDA 线上;
在这个时间内,芯片不能保证 SDA 的数据是正确的;
所以,工程师要在这个时间以后再读取 SDA 的数值。
按说,这个值只会给出最大值。很显然,只有最大值才有意义。

使用特权

评论回复
17
雪山飞狐D| | 2018-11-24 12:30 | 只看该作者
c834706901 发表于 2018-11-23 09:07
我就是想知道delay(4) delay(2)这些延时是怎么得出来的

    图片是24CXX的中文数据手册,可以看到,只有电压在5V时,24C系列才能达到400K的时钟速率,2.5V 左右的速率只有100K,IO模拟的时序只有按照100K的速率去写,才能保证兼容,而这个I2C的程序模块可以兼容400K的器件,所以才会出现delay4 us......

QQ图片20181124122237.png (312.58 KB )

QQ图片20181124122237.png

使用特权

评论回复
18
雪山飞狐D| | 2018-11-25 19:45 | 只看该作者
本帖最后由 雪山飞狐D 于 2018-11-26 01:34 编辑
#include "stc15f2k60s2.h"
#include <intrins.h>
#include "Delay.h"
#include "I2C.h"

void Start_I2c(void);
void Stop_I2c(void);
unsigned char I2c_wait_ack(void);
void Ack_I2c(void);
void Nack_I2c(void);

void SendByte(unsigned char );
unsigned char RcvByte();

//起动总线函数               
//Start_I2c();  
//功能:启动I2C总线,即发送I2C起始条件.  
void Start_I2c()
{
  SCL=1;
  Delay5us();            //tSU:STA
  SDA=0;         //发送起始信号
  Delay5us();    //tHD:STA
  SCL=0;         //条件保持SCL处于0状态才能进行写入
}


//结束总线函数               
//Stop_I2c();  
//功能:结束I2C总线,即发送I2C结束条件.  
void Stop_I2c()
{
   SCL=0;
   SDA=0;      
   Delay5us(); //tSU:STO
   SCL=1;      //结束条件建立时间大于4μs
   Delay5us(); //tBUF总线空闲时间大于4.7us
   SDA=1;      //发送I2C总线结束信号
}


//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 I2c_wait_ack(void)
{
    u8 Time=0;
        
    SCL=0;
    SDA=1;        //准备接收应答位
    Delay5us();   //tAA tLOW
    SCL=1;            
    Delay5us();          //tHIGH
        
         while(SDA)                           
         {
              Time++;
              if(Time>250)
            {
               Stop_I2c();
                                
                return 1;         //超时检测无应答返回1
             }
         }
        
          SCL=0;    //时钟输出0
        

          return 0;  //有应答返回0
}




<blockquote>
//字节数据发送函数               
//SendByte(u8 DAT);
//功能: 将数据DAT发送出去,可以是地址,也可以是数据


void  SendByte(u8 DAT)
{
    u8  i=0;
     SCL=0;
         
        
    for(i=0;i<8;i++)  //要传送的数据长度为8位
    {
         if((DAT<<i)&0x80)
         {
            SDA=1;   //判断发送位  发送是由高位开始发送
         }
        else  
         {         
            SDA=0;
         }        
                 
        Delay5us();
        SCL=1;        //置时钟线为高,通知被控器开始接收数据位
        Delay5us();        
        SCL=0;       //出函数保持SLC=0
                        
       _nop_();            //tHD 数据输出保持时间0ns
                          
    }

}

//功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
//发完后请用应答函数应答从机。   
u8 RcvByte()
{
   u8 Dat=0;
   u8 i=0;

   for(i=0;i<8;i++)
   {         
        SCL=0;        //置时钟线为低,准备接收数据位
        _nop_();            //tDH从器件数据输出保持时间100ns      

        
        SDA=1;        //释放总线准备接收数据位
        Delay5us();
        SCL=1;       //置时钟线为高使数据线上数据有效
        Dat<<=1;     //最后一位不需要移位,所以移位放在此处
                 
        if(SDA==1)
    {        
        Dat|=0x01;   //读数据位,接收的数据位放入Dat中
    }  
       Delay5us();  
   }

   SCL=0;  //出函数保持SLC=0         

   _nop_();            //tDH从器件数据输出保持时间100ns
   return Dat;                                       
}


//应答子函数
//主机应答
void Ack_I2c(void)
{
  SCL=0;
  SDA=0;              
  Delay5us();     
  SCL=1;
  Delay5us();   
  SCL=0;       //清时钟线,钳住I2C总线以便继续接收
}


//主机不应答
void Nack_I2c(void)
{
  SCL=0;
  SDA=1;
  Delay5us();     
  SCL=1;
  Delay5us();  
  SCL=0;      
}        


 /*************************此部分为AT2402的驱动程序使用I2C总线连接*************************************/
#include  "stc15f2k60s2.h"
#include  "Delay.h"
#include  "24C04.h"
#include  "I2C.h"

//24c 默认的硬件地址都是 0xa0  即 1010   然后A2 A1 A0  最后一位 为读写位  1读 0写
//24c02  256x8 bit   
//24c04  512x8 bit
//而子地址 只是8位的 即最大也就256个字节  那么24c04 就要占用2个256个字节
//这里24c04硬件上采用的是 分页方法  即有24c02里有A2 A1 A0 当是24c04时 A0做为分页位
//当A0为0 表示第一页 写入第一页256字节
//当A0为1 表示第二页 写入第二页256字节

//在AT24CXX指定地址读出一个数据
//Addr:开始读数的地址  
//返回值  :读到的数据
u8 AT24C_Rcvone(u8 Addr)
{
   u8 temp=0;
   Start_I2c();        //启动总线
   SendByte(0xa0);     //发送器件I2C地址,写模式
   I2c_wait_ack();          //等待应答
   SendByte(Addr);    //发送器件存储地址
   I2c_wait_ack();         //等待应答

   Start_I2c();      //重新启动总线
   SendByte(0xa1);   //设置为读操作
   I2c_wait_ack();         //等待应答;

   temp=RcvByte();         //读字节
   Nack_I2c();                   //非应答

   Stop_I2c();                 //结束总线
   return temp;
}



//在AT24CXX指定地址写入一个数据         此函数只限于 c02-c16
//Addr:写入数据的目的地址   
//Data:要写入的数据
void AT24C_Sendone(u8 Addr,u8 Data)
{
   Start_I2c();           //启动总线

   SendByte(0xa0);        //发送写命令
   I2c_wait_ack();                          //等待应答
   SendByte(Addr);        //发送地址
   I2c_wait_ack();                          //等待应答
   SendByte(Data);                          //发送字节数据
   I2c_wait_ack();                          //等待应答
   Stop_I2c();            //结束总线
   
  Delay10ms();          //tWR 周期,等待I2C器件写完毕
}


楼主搞定了没,你对着我严格按datasheet写24C04的100K SCL程序,注意红色的标注的地方,不同器件参数不太一样,要全部通用的话可以统一延迟为1us, 那么就可以对应上你的器件上的最大900ns







QQ图片20181125194220.png (368.08 KB )

QQ图片20181125194220.png

捕获.PNG (271.65 KB )

捕获.PNG

使用特权

评论回复
19
天风立马| | 2018-12-2 13:29 | 只看该作者
本帖最后由 天风立马 于 2018-12-2 13:32 编辑

我喜欢追渔的人. 去找我QQ, 你应该能找到. 我教你, 不收费. 你也可以去下载我之前分享的一个资料自己学.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

28

帖子

1

粉丝