现在的位置: 首页 > 综合 > 正文

I2c通信问题分析(欢迎高手补充)

2017年05月19日 ⁄ 综合 ⁄ 共 2557字 ⁄ 字号 评论关闭

I2C 总线比较简单,可能的问题主要出在时序上,一般设计者即使忽略也不太会有麻烦,但是有几个指标一定要认真考虑:

 

1、总线驱动能力。上拉电阻和负载电容决定了总线在某一速率下的稳定性。当输出为高时,电流通过上拉电阻对负载电容充电。上拉越大,电容越大,所需要的时间就越长,如果超过了通信周期的10%,那么这个上升沿就太缓了,相应的建立时间会受到影响,I2C规范的最大负载电容是400pF,快速模式下是100pF。如果输出为低,电流通过上拉电阻被I2C
master器件吸取,(注意根据I2C规范,最小只有3毫安的吸取电流)那么这个吸取电流在上拉电阻上的压降就决定了输出低电平能达到的范围,如果不能达到0.3VDD以下,就会有误采样。有人说加大上拉电阻是不妥当的,要具体分析吸取电流、负载电容、上拉电平和通信速率才能决定(普通模式和快速模式是不一样的)。

 

2。总线空闲时间(bus free time)。它的定义是从上一次通信的停止到下一次通信的开始的间隔时间。通常一些I2C器件的要求是4.7微秒,也有要20微秒的,比如某种激光器内嵌的PROM。对CPU来说,它往往是I2C的master
器件,由于运行速度很快,这个指标如果不注意的话就会达不到,导致I2C总线不响应。另外要注意的是CPU内部的I2C停止时刻标志位置位和硬件总线上的I2C停止标志(clock 为高时数据从低到高的跳变)时刻往往是不一致的。有的芯片有15-20个微秒的差别,所以要用示波器量出来为准。

 

3。总线保持时间。I2C的总线建立和保持与有的时序定义不一样。建立时间是指从数据跳变沿到时钟上升沿的间隔;而保持时间是指从时钟下降沿到数据下一个跳变沿的间隔。通常建立时间都能保证,保持时间一般为0纳秒。但是有的器件做不到,一般为900纳秒;还有的虽然宣称是0纳秒,时间也要近1微秒(比如说TI的某器件)

仅供参考! 

 

 

a.完全不能进行读写:

 

(1)通信协议不正确:有很多的I2C设备,并不支持所有的I2C协议,同时也不是一个比较标准的I2C设备;软件的通信时序不正确。

 

(2)I2C设备地址不正确:有很多的I2C设备的地址是可以通过硬件设定的;也有器件资料提供的数据是错误的。

 

(3)I2C通信线上没有加上拉电阻:由于I2C的从设备的SDA,SCL的PIN是输出开漏的,所以必须加上拉电阻,同时根据I2C设备的数量上拉电阻的大小也会不同。从1K~10K以上,当然不能太大,也不能太小。

 

(4)I2C设备损坏:有时我们会经常遇到问题时总是认为我们自己在软件上是不是有问题,是不是电路上没有焊接好,实际上都不是,而是器件是坏的。

 

b.读写失败,不能正确的读写某个地址的数据:

(1)电路干扰:在I2C设备的电源入口处没有加滤波电路,一般入口处加10nF或 0.1uF电容;SDA,SCL线上干扰,没有滤波处理,线上串一几十ohm电阻,对地加几十pF电容;千万别小看这几颗小小的电容!

(2)通信时序:读写是有速度过快,例如在写24C02时,当你用一个字节的方式去写EEPROM时,如果速度过快,前面的数据是不会被写入的,具体的间隔时间没有测试过;由于某种原因,导致读写间过长,例如在通信过程中,被中断打断,同时中断时间过长。

(3)SDA,SCL的输入电平不一致:如果I2C设备既有3.3V也有5V的,上拉电阻最好不要同时接3.3V和5V两组,一定要根据实际情况选择一组。

(4)读写软件的方式的影响:在块读写时,起始的地址和数量是很重要的。例如块写24C02,如果我们想连续写A0页05H~16H地址,我们会发现16H的数据是没有被写入,00H的数据被改了(如果没有记错的话24C02是16字节循环的),原因是在连续读写的过程中,24C02的地址不是从05H自动的加1直到加到16H,而是05H->06H->...->15H->00H。

 

 

其他

 

没有应答

1.      地址错误

2.      复位脚可能要拉高。

3.      看电压是否正常,芯片是否工作。

4.      供电不足

 

通过I2C读函数读同一个寄存器为什么每次读取的数据不一样?是I2C的时序有问题吗?(比较难发现的问题)

概述
I2C
兼容2线接口是功能强大的总线机制,用于连接微控制器或微处理器与低速外设,例如:集成了模/数转换器(ADC)的外设。基于该总线的最基本的通信方式(即,写入/读取从机寄存器的一个字节)非常直观。但是,如果因为这种方法简单而掉以轻心,则会导致严重的系统错误。

单字节通道传送2字节数据
任何连接外设(尤其是传感器)的数字接口,都需要确保从器件的内部寄存器正确读取数据,尤其是在读取寄存器的过程中数据发生变化的情况下。数据传输过程中,如果ADC执行转换操作并更新寄存器的内容,数据则会发生改变。许多器件带有内部缓存器(通常不能从外部访问),用来存放最新转换结果。当I2C总线处于空闲状态时,更新所谓的“用户可访问”寄存器内容。

2C
协议每次只传送1个字节的数据。因此,如果有效数据字长超过8位,并且没有合理处置传输操作,则会引发问题。我们不能通过I2C直接读取所有数据ALSDATA[13:0],需要首先读取寄存器0x04的内容,然后读取寄存器0x05的内容,再把这些数据合并到一个至少16位的寄存器内。因此,在读取这些数据时需要特别谨慎。通过两次简单的单字节读操作(利用STOP (P)条件终止)完成数据读取。
 
这种方法存在致命缺陷,确切地说,向器件发送STOP条件,返回“用户可见”的寄存器内容。由此,从寄存器0x04读取数据后,实际的14位数据可能在读取0x05寄存器之前已经更新。

这个问题很容易通过一次读取2字节数据来避免,如图3所示。具体操作是,读取第一个数据字节后,发送REPEATED START (而不是STOP)进行操作,操作非常简单。通过读取2个字节,尽管在两个器件之间发送完全相同的位数,却可避免器件不恰当地更新I2C寄存器的内容。

 

EEPROM中写入数据函数中,你没有释放数据总线,以至于下次写不进去数据。

 

追加:1.  Failed to register i2c client mma845x at 0x1c
                地址冲突,有另一个设备的地址也是0x1c

 

 

 

抱歉!评论已关闭.