首页 > 其他 > 详细

IIC协议解释(转)

时间:2018-10-19 15:44:02      阅读:198      评论:0      收藏:0      [点我收藏+]

IIC协议解释

 推荐资源: http://m.elecfans.com/article/574049.html       and       https://blog.csdn.net/firefly_cjd/article/details/51921129  (动态图讲解)

(1)概述

I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。

经常IIC和SPI接口被认为指定是一种硬件设备,但其实这样的说法是不尽准确的,严格的说他们都是人们所定义的软硬结合体,分为物理层(四线结构)和协议层(主机,从机,时钟极性,时钟相位)。

IIC,SPI的区别不仅在与物理层,IIC比SPI有着一套更为复杂的协议层定义。下面来分别说明一下IIC的物理层和协议层。


 

(2)IIC的物理层

a.只要求两条总线线路,一条是串行数据线SDA,一条是串行时钟线SCL。(IIC是半双工,而不是全双工)。

b.每个连接到总线的器件都可以通过唯一的地址和其它器件通信,主机/从机角色和地址可配置,主机可以作为主机发送器和主机接收器。

c.IIC是真正的多主机总线,(而这个SPI在每次通信前都需要把主机定死,而IIC可以在通讯过程中,改变主机),如果两个或更多的主机同时请求总线,可以通过冲突检测和仲裁防止总线数据被破坏。

d.传输速率在标准模式下可以达到100kb/s,快速模式下可以达到400kb/s。

e.连接到总线的IC数量只是受到总线的最大负载电容400pf限制。

一个典型的IIC接口如下图(1)所示

技术分享图片

                                                                   图(1)


 

(3)IIC的协议层

IIC的协议层才是掌握IIC的关键。现在简单概括如下:

a.数据的有效性

在时钟的高电平周期内,SDA线上的数据必须保持稳定,数据线仅可以在时钟SCL为低电平时改变。除非作为起始/结束条件。

如图(2)所示:

技术分享图片

                                                                  图(2)

b.起始和结束条件

起始条件:当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件,结束条件:当SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件,要注意起始和终止信号都是由主机发出的,连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。总线在起始条件之后,视为忙状态,在停止条件之后被视为空闲状态,对起始条件和结束条件的描述如下图(3)所示。

技术分享图片

                                                                图(3)

c.应答

每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答,如图(4)所示。

技术分享图片

                                                               图(4)

d.数据帧格式

I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。
在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。{这里小编在驱动MPU6050模块的时候,就犯过这样的错误,它写的MPU6050从机地址是0x68,因为发送从机地址的时候,要加一位读写方向位,因为刚开始应该是向这个MPU6050里写从机里某个寄存器的地址,所以应该是7位地址   0x68(1101000)+二进制位0=11010000)也就是0xD0,表示要向该IIC设备里写东西,然后再紧接着写入IIC设备里的寄存器地址,而我直接写入了0x68,导致出错},每次数据传送总是由主机产生的终止信号来结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。
在总线的一次数据传输过程中,可以有以下几种组合方式:
 
[1] 主机向从机发送数据,数据传送方向在整个传送过程中不变:(写模式)
技术分享图片
注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送
    A表示应答(低电平), A非表示非应答(高电平)。S表示起始信号,P表示终止信号。
 
[2]主机在第一个字节后,立即从从机读数据:(读模式)
技术分享图片
 
[3]在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相:(读写切换模式)
技术分享图片
 注释: 读模式的结束时,不需要进应答。
 
一般情况下,[3]是比较常见的,比如MPU6050模块:
发送起始信号
等待从机应答(?需要么,查看下MPU6050 manual)
写一个从机地址+0(表示写),
等待从机应答
发送一个字节的MPU6050加速度存储寄存器地址,
等待从机应答
再发送一次起始信号
等待从机应答
写一个从机地址+1(表示读)
等待从机应答
读取MPU6050传感器数据
主机非应答
 
 
e.IIC信号的模拟
主机可以采用不带I2C总线接口的单片机,如80C51、AT89C2051等单片机,利用软件实现I2C总线的数据传送,即软件与硬件结合的信号模拟。即使是含有IIC硬件的单片机(如stm32 103系列)也有一定的缺陷,所以一般也会模拟IIC的时序。现将具体时间截图如下:
技术分享图片

 

IIC时钟频率:不高于400K

应答:当IIC主机(不一定是发送端还是接受端)将8位数据或命令传出后,会将SDA信号设置为输入,等待从机应答(等待SDA由高电平拉为低电平)

   若从机正确应答,表明数据或者命令传输成功,否则传输失败,注意,应答信号是数据接收方发送给数据发送方的。

IIC器件地址:每一个IIC器件都有一个器件地址,有的器件地址在出厂时地址就设定好了,用户不可以更改,比如OV7670的

      地址为0x42。有的器件例如EEPROM,前四个地址已经确定为1010,后三个地址是由硬件链接确定的,所以一

      个IIC总线最多能连8个EEPROM芯片。

技术分享图片

    图上开始信号之后,七位地址代表器件地址,第八位代表读或者写(0为写,1代表读),然后跟着响应位。

 IIC器件单字节写时序:

技术分享图片

IIC器件多字节地址写时序:多字节地址比单字节地址在时序上就多了一块写地址

技术分享图片

 

单字节器件读时序:注意最后产生无应答信号,另外多字节地址读时序跟单字节类似,只不过是多了几个地址字节而已。

技术分享图片

 三大串行总线:uart、spi、iic

同步:spi    异步 :iic,uart

同步和异步区别:采集数据是否用的是时钟的沿,如果是时钟沿采数据,同步传输,如果电平采集数据是异步

串口接受数据其实就是一个串转并的过程

 
 

 
具体的程序代码如下:
//产生起始信号
void I2C_Start(void)
{
    I2C_SDA_OUT();//配置一下引脚,引脚设置为输出
 
    I2C_SDA_H;//把数据线拉高
    I2C_SCL_H;//把时钟线拉高
    delay_us(5);//延时5微秒,要求大于4.7微秒
    I2C_SDA_L;  //拉低,产生下降沿
    delay_us(6);//这个过程大于4微秒
    I2C_SCL_L;//最后一定要把这个时钟线拉低,因为只有时钟线拉低的时候才允许数据        变化。
}
//产生停止信号
void I2C_Stop(void)
{
   I2C_SDA_OUT();
 
   I2C_SCL_L;
   I2C_SDA_L;
   I2C_SCL_H;
   delay_us(6);
   I2C_SDA_H;
   delay_us(6);
}
//主机产生应答信号ACK
void I2C_Ack(void)
{
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_L;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}
 
 
//主机不产生应答信号NACK
void I2C_NAck(void)
{
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_H;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}
//等待从机应答信号,我们只负责主机应答信号的产生,从机应答信号
//我们不控制。
//返回值:1 接收应答失败
//  0 接收应答成功
u8 I2C_Wait_Ack(void)
{
    u8 tempTime=0;
 
    I2C_SDA_IN(); //配置为上拉输入。
    I2C_SDA_H;  //主机释放数据总线,等待从机产生应答信号
    delay_us(1);
    I2C_SCL_H;
    delay_us(1);
    //等待从机对数据总线的操作。低电平代表应答
    while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
    {
        tempTime++;
        //这个属于软件延时,不一定准确。
        if(tempTime>250) //如果时间超时,没有应答就停止。
    {
        I2C_Stop();
        return 1;  //没有响应的话返回1.
    } 
}
    I2C_SCL_L;
    return 0; //如果有响应的话就返回0.
}
    
针对于不同的IIC设备,IIC协议可能会有一定的区别,有的地址需要左移一位,把最低位腾出来做读写位。
 
 
参考:
 
https://www.cnblogs.com/zhangjiansheng/p/7738390.html
https://www.cnblogs.com/bixiaopengblog/p/7469536.html
 
 
 
 
 
 

IIC协议解释(转)

原文:https://www.cnblogs.com/limanjihe/p/9816655.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!