i2c spec :
The Acknowledge signal is defined as follows: the transmitter releases the SDA line (Wei: put SDA at 1 state)
during the acknowledge clock pulse so the receiver can pull the SDA line LOW and it
remains stable LOW during the HIGH period of this clock pulse (Wei: if the high of clock is hold on, SDA is kept at LOW!! )(see Figure 4). Set-up and
hold times (specified in Section 6) must also be taken into account.
When SDA remains HIGH during this ninth clock pulse, this is defined as the Not
Acknowledge signal.
我的波形:
80C51,NAK波形。
When SDA remains HIGH during this ninth clock pulse, this is defined as the Not
Acknowledge signal.
http://blog.csdn.net/smallmuou/article/details/7183656
最新在开发OLED屏驱动,需要用到I2C总线,下面大体上讲解一下I2C设备的调试及波形分析,为大家做一些参考,由于刚涉及这部分内容,因此有什么错误的,还请赐教~
一、概要
I2C总线只需要两条线,一条SDA数据线,一条SCL时钟线;根据这两条线的高低电平、上升沿、下降沿就可以实现主机与I2C设备的通讯;其中有:
(1)I2C总线相关
传输开始条件:SCL处于高电平,SDA下降沿时;
传输接收条件:SCL处于高电平,SDA上升沿时;
传输数据:开始传输后,SCL处于高电平时,SDA的数据为所传输的数据;
回应:当传输完一个字节后,I2C设备需要回应一个ACK,这样主机才继续发送;因此回应信号是在传输完8bit后的下一个数据位(SDA值),当SDA为0表示有回应,为1表示没回应;
正常I2C总线的数据是:Start + I2C devece id + R/W + ACK + Data(first byte)+ ACK + ... + Data(n)+ ACK + Stop
(2)I2C设备相关
设备地址:有7位和10位两种,具体见I2C设备芯片的DataSheet,由于目前用到的是7位,因此下面主要针对7位讲述;在讲I2C设备地址是有可能有两种说法,主要是用8位表示还是用7为表示,比如对于我的OLED来说,当用8位表示时则为0x78地址,当用7位时则为0x3c(即0x78右移1为),在驱动中用0x78还是用0x3c要看具体平台的I2C总线驱动,我在AMLOGIC平台上用的是0x78,而在MV平台上用的是0x3c;
寄存器reg:一般的I2C设备芯片都有带reg,一般在传输正式的数据之前需要先传输reg地址,比如我的OLED来说,在传控制命令时需要先发送0x00的reg地址,在传输数据时需要发送0x40的reg地址;
二、调试及波形分析
一般当我们拿到一个I2C设备时,就必须涉及到驱动的编写,就比如对于OLED来说,就要用编写OLED驱动,这样我们才能控制它,对于OLED屏来说,第一步也是最重要的一步就是点亮它;当我们做完这一步,那后面剩下的就只是细节问题了;”万事开头难“,这句话真的不假,对于OLED来说,如何才能点亮,我们该怎么调试呢?当我们写完OLED驱动,但OLED屏还是不亮,可能问题会出现在哪?是硬件问题还是软件问题?;若为软件问题,那会是I2C总线驱动问题,还是我们I2C设备驱动有问题?那么我们该如何判断问题出现位置呢?这就需要我们对I2C总线上的数据进行分析;那么下面我将详细讲述如何获取和分析I2C总线上的数据;
(1)示波器
对于I2C总线的数据,我们要用到示波器,这样我们才能抓取到信号,而且必须同时采集SDA和SCL的数据;该如何抓取呢?我这边的方式是将示波器调成边下降沿触发模式(因为开始信号是SDA下降沿),并且设置成单次模式(这样抓取完一次就会stop,便于我们数据分析);
(2)波形
由于我的OLED设备的地址是0x78(8位),而第一次我必须将OLED设置成off状态,通过命令表可以查到,必须发生0xAE,而刚刚有讲到在发送命令前必须先发送寄存器reg地址,即0x00;于是我发送的数据为0x78+0x00+0xAE;下面是我用示波器抓取到的波形:
分析(其中黄色的为SDA信号,浅蓝色为SCL信号):从上述波形中我们可以读取到数据依次是:01111000 0 00000000 101011100;即:0111100(7位OLED设备地址) + 0( 读写为,0为写,1为读)+0(ACK回应)+00000000(寄存器reg)+ 10101110(0xAE OLED off命令);(这里还有一点我还没弄明白就是reg后没有回应,还望大家不吝赐教)
下面当我来随便发送一个地址时,比如当我发送0x56(8位地址),测到的波形如下:
分析:从波形可看出数据依次为:010101101 即0101011(设备地址)+0(读写位)+1(NACK无应答),由于没有相应的I2C设备因此无应答ACK信号,于是就停止传输;
三、总结
由以上可知,可以通过查看I2C总线数据来确认跟踪I2C设备,已更好地确定是软件问题还是硬件问题;
I2C的概念原理网上都有就不说了,这里只把我把两个开发板通过I2C通讯的调试经验记录分享一下。
I2C要求要有一个主设备,负责发起请求和控制时钟;其它为从设备,通过设备ID地址来识别并响应主设备请求。主从设备要轮流控制SDA。一开始我没搞明白这一点,直接加了写I2C数据代码,然后用示波器在SDA和SCL脚测量,却只能找到些凌乱的波形,没有预期的效果。后来把从设备接上,两边写好代码,互相有了响应,这才在示波器上看到波形。
这里我找了一个主设备往从设备写数据的例子,代码如下:
接收端的代码比较简单,就不贴了。
将示波器的X和Y分别接到SDA和SCL,得到波形并分析如图:
从图中可知时序如下:
从图中可知,纵向一格是200mV,则SDA和SCL的电平大概就是350mV;由于信号笔上设置了信号x10,因此实际电平应该大概是3.5V(理论上应该是3.3V)。横向一格是25us,10个时钟周期大概用了4格,即4x25us=100us,平均每个时钟周期是10us,可算出传输频率为1/10us=100,000/s,即100k bps。
另外,对于读从设备内容,基本流程是主设备先往从设备写一个命令,然后再输出读取命令,然后才由从设备发送数据。过程类似,不再具体分析了。
下图示例中,主机先向从机写了一个地址命令,然后重新开始并进入读取周期。