目录

一、IIC协议

1.1 简介

1.2 I2C物理层

1.3 I2C主要特点

1.4 总结

二、I2C时序基本单元

2.1起始条件

2.2终止条件

2.3发送一个字节

2.4接收应答

2.5接收一个字节

2.6发送应答

三、I2C时序

3.1指定设备指定地址写

3.2指定设备当前地址读

3.3指定设备指定地址读


一、IIC协议

1.1 简介

        IIC通讯协议(Inter IC BUS,习惯叫I2C)是由Philip飞利浦公司开发的,由于它所需引脚少硬件实现简单可拓展性强,广泛用于系统内多个集成电路IC(芯片)间的通讯。        

df9a8a951b904a029d7cd3d33fdfdac8.png

这里对比一下串口通信:

  • 串口通信也是两根信号线,依靠异步通信实现了全双工(即设备之间约定好通信速度);I2C则是拿其中一根信号线用来同步时钟,实现了半双工
  • 异步的缺点是依赖硬件支持,数据传输出现暂停时,接收方是不知道的;而同步则相反,不依赖硬件(这也是大家喜欢模拟IIC的原因),数据传输可以暂停
  • 串口通信的收发设备双方在传输数据时彼此之间没有应答机制,均不知道对方是否收到了数据,I2C规定了应答
  • 串口通信没有主机从机的概念,因为绑定了传输数据的对象,I2C则是多主多从,只要是挂载到信号线上的设备,都可以实现通信
  • 比喻一下:串口通信传输数据的方式就像是不用言说、忠贞不渝的夫妻,I2C则是一个公共邮筒,需要通信的双方通过书信往来(当然会署名,收到才回信)

    1.2 I2C物理层

    111a03f31ee2404194c3f97f73cbb9c7.png

            

            它是一个支持多设备通信的总线。“总线”指多个设备共用的信号线,一条SDA(双向串行数据线)、一条SCL(串行时钟线)。数据线用来传输数据时钟线用来同步设备之间数据的收发。每个设备的数据线、时钟线都对应挂在总线上。

    1.3 I2C主要特点

            为了方便通常把I2C设备分为主设备和从设备,谁控制时钟线(即控制SCL的高低电平变换)谁就是主设备。

  • 每个连接到总线的设备都有自己唯一且独立地址,主设备可以利用这个地址进行不同设备直接的访问,就好比教室里上课的老师,点学生名字回答问题。
  • 支持一主多从、多主多从,每个设备都可以作为主设备给从设备发送数据或者接收从设备发送的数据,但同一时刻只能有一对主从设备通信。
  • 除起始/终止条件外,时钟线占用期间,数据线上的数据才允许翻转,时钟线释放期间,数据线上的数据不允许翻转
  • 主机一直控制时钟线(占用或释放)长时间控制数据线,当需要接收从机应答时会释放数据线(此时仅占用时钟线,等待从机控制数据线),然后释放时钟线,读取数据线(即读取应答)
  • 从机不允许控制时钟线,经主机释放后可以控制数据线(两种情况,一种是从机需要应答,另一种是从机需要发送数据给主机)
  • 支持不同速率通讯,有标准模式(100kb/s)和快速模式(400kb/s)
  • 只有一根数据线,所以是半双工 
  • SCL和SDA总线都需要接上拉电阻(阻值一般为4.7Ω)来保证数据的稳定性,减少干扰
  • 设备的SCL和SDA均要配置成开漏输出模式才能执行线与的功能 
  •         这里涉及到「开漏输出」、「上拉电阻」和「线与」三个概念。这对于I2C总线协议绝对是关键所在。因为有那么多的设备,仅仅通过这两根总线来进行通信,哪个时刻谁发谁收,很容易乱。

    开漏输出和上拉电阻

            在芯片中,当输出为漏极开路(OD)或集电极开路(OC)时,简称开漏输出,它只能输出低电平和高阻态(可理解为开路,阻抗无穷大)。(这其实就避免了主从设备都输出高电平时导致短路的问题)

            正因此,开漏输出好比「要么拉低要么放手」,使得设备要想使用总线只能输出低电平来占用总线,从而实现了「线与」的功能,「线与」就是逻辑与,输入有若干个,这里想表达的意思是——当总线上只要有一个设备输出低电平(线与为0),总线便处于低电平状态,称为占用状态

            那高阻态有什么用呢?根据前面的分析,设备只能给总线输出低电平,怎么拉高呢?这时候,上拉电阻就起作用了,简单理解就是上拉电阻可以拉高引脚的电平。当设备输出高阻态,同时没有其他设备占用总线(拉低总线电平),即所有设备都输出高阻态,那么此时总线就会被上拉电阻上拉到高电平称为空闲状态,也实现了「线与」功能(全输入1,才输出1)。

    (不能用推挽输出吗?推挽输出不需要上拉电阻,但mos管阻抗小,容易造成短路,而且也实现不了线与)

    1.4 总结

         物理层上由两根总线SDA(传输数据)、SCL(同步数据收发)以及上拉电阻组成,每个设备的SDA、SCL都挂载在对应总线上。通过默认配置各设备的SDA、SCL为开漏输出,加上上拉电阻,实现了逻辑线与功能。设备要想使用总线,需要输出低电平。当所有设备都输出高电平,总线才表现为高电平。控制占用时钟线的设备为主设备。

    二、I2C时序基本单元

    2.1起始条件

    SCL高电平期间(空闲状态),SDA从高电平切换到低电平,随后,SCL切换到低电平(表示主机开始占用)

    2.2终止条件

    SCL高电平期间(空闲状态),SDA从低电平切换到高电平


    2.3发送一个字节

    主机占用SCL主机依次将数据位放到SDA线上高位先行),然后主机释放SCL从机会在SCL高电平期间读取数据位,循环此过程8次,即可发送一个字节数据,

    2.4接收应答

    主机发送完一个字节后(主机继续占用时钟线),主机释放SDA(等待且允许从机控制数据线),然后主机释放SCL,读取一位数据,用于判断从机是否应答(即是否收到数据),数据0表示应答,数据1表示非应答

    (形象地说就是:主机发送完一个字节,问”有没有人收到?我现在松开数据线了哈!如果有人收到,就把数据线拽下来“。接着主机松开时钟线读取SDA。如果主机发现自己松手后,数据线没变化还是高电平,说明从机没收到数据,反之说明从机收到了数据)


    2.5接收一个字节

    主机占用SCL主机释放数据线从机将数据位依次放到SDA线上高位先行),然后主机释放SCL主机将在SCL高电平期间读取数据位,循环此过程8次,即可接收一个字节数据

    (图中实线代表主机控制,虚线代表从机控制)

    2.6发送应答

    主机接收完一个字节后(主机继续占用SCL),主机发送一位数据(数据数据0表示应答,数据1表示非应答),主机释放SCL,等待从机读走数据线。如果从机读到了主机的应答,它可以接着向主机发送数据;如果没得到应答,会以为主机接收失败或者主机不需要接收了,这两种情况都需要交出数据线的控制权,对于主机接收失败,主机会重新开始和从机通信;而对于不需要接收了,主机可能会向从机发送其他数据了。


    三、I2C时序

    主机在和从机通信前,需要进行”点名“,所有从机都会收到第一个字节,这个字节就是某个从设备的地址,所有从设备都会将其和自己的名字进行比较,确认是在叫自己后,该从设备就响应之后主机的读写操作。

    有关从机设备的地址,I2C协议标准里分为7位和10位地址(7位地址较为普遍)。

            为什么是7位?因为还有1位用来确认主机是要读/写从机。0表示主机将向从机发送数据,1表示主机将向从机接收数据。

            每个I2C设备出厂时,厂商都会分配一个默认的7位地址(具体需要查芯片手册),比如某个型号的MPU6050的是1101000,为什么说某个型号呢?因为同一型号的一般来说地址默认的都是一样的,如果实在需要挂载在同一I2C总线下,也有办法解决:7位地址中存在可变部分(具体地以芯片手册为准)。仍以MPU6050为例,最后一位可由模块的AD0引脚确定,当它接低电平时,地址为1101000,接高电平时,1101001

    3.1指定设备指定地址写

    起始条件后,主机控制时钟线,发送第一个字节用于指定设备+指定写,接收应答,再发送一个字节指定地址(从机内部寄存器的地址),接收应答

    主机发送N字节+接收N应答
    终止条件

     

    3.2指定设备当前地址读

    起始条件后,主机控制时钟线,发送第一个字节用于指定设备+指定读,接收应答

    从当前地址开始读N字节,接收N应答

    终止条件

    当前地址读?哪个当前地址?(因为指定设备时如果指定读,主机就不能再控制数据线,写入要读的地址了)

    实际上,从机内部所有的寄存器都被分配到了一个线性区域(可以简单理解成一个线性数组),并且,有一个单独的指针变量,指着其中一个寄存器(其中一个数组元素),这个指针就称为当前地址指针,它上电默认指定数组[0]。每写入一个字节或读出一个字节后,指针会自增一次, 指向下一个寄存器。

    比如以3.1中的图片时序为例,在0x19地址下写入了一个字节,如果调用指定设备当前地址读时序,就会读出0x1A的数据,再接着读,读出0x1B的数据……

    3.3指定设备指定地址读

    3.2的操作虽然有些麻烦,而且通常我们也不这么用,但是!如果只是指定了地址,不写入字节,那么!接下来就可以指定地址连续读!

    这就是指定设备指定地址读的思路,一般也称这种时序为复合格式。

     起始条件后,主机控制时钟线,发送第一个字节用于指定设备+指定写,接收应答,再发送一个字节指定地址(从机内部寄存器的地址),接收应答(当前地址指针已指向准备写入的寄存器地址)

    不发送要写入的字节,转而再发送起始条件,发送第一个字节用于指定设备+指定读,接收应答

    往后就可以连续读出N字节数据,发送N字节应答

    终止条件(这里需要注意,不打算接着读,在此前要发送非应答,这样从机才知道主机不接着读了!!!)

      

    作者:LateBloomer777

    物联沃分享整理
    物联沃-IOTWORD物联网 » 学习笔记–stm32I2C通信

    发表回复