精华内容
下载资源
问答
  • 2020-03-11 16:54:05
    IIC是当今嵌入式应用中最常见的串行通信协议之一。对比OneWire严苛的时序要求,SPI等更多的线缆要求,IIC处于一个折中的位置:不那么多的2根线缆的硬件要求,不那么复杂严苛的时序要求,便可进行多主多从的双向通信,小巧灵活方便,这使它广受欢迎。

    一、简介

      IIC(Inter-Integrated Circuit)是 IIC Bus 简称,中文叫集成电路总线。它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取I²C从属设备地址。
      IIC使用两根信号线进行通信:一根时钟线SCL,一根数据线SDA。IIC将SCL处于高时SDA拉低的动作作为开始信号,SCL处于高时SDA拉高的动作作为结束信号;传输数据时,SDA在SCL低电平时改变数据,在SCL高电平时保持数据,每个SCL脉冲的高电平传递1位数据。


    二、主要特性

    • IIC用2根信号线通信:串行数据线 SDA、串行时钟线 SCL
    • IIC总线上所有器件的SDA、SCL引脚输出驱动都为 开漏(OD) 结构,通过外接上拉电阻实现总线上所有节点SDA、SCL信号的线与逻辑关系;
    • 总线上的所有设备通过软件寻址且具有唯一的地址(7位或10位)。7位“从机专用地址码”,其高4位为由生产厂家制定的设备类型地址,低3位为器件引脚定义地址(由使用者定义);10位地址不常见;
    • 任何时刻都只存在简单的主从关系,按数据传输的方向,主机可以是主发送器或主接收器;
    • 支持多主机。在总线上存在多个主机时,通过冲突检测和仲裁机制防止多个主机同时发起数据传输时存在的冲突;
    • IIC总线上所有器件都具有“自动应答”功能,保证数据传输的正确性; 主机和从机的区别在于对SCL的发送权,只有主机才能发送SCL;
    • IIC总线允许挂载最多的设备数量取决于总线上最大电容值,一般为400pf(Hs模式100pf)
    • IIC总线不仅广泛应用于电路板级的内部通信,还可以通过I2C总线驱动器进行不同系统间的通信; 支持传输速率包括:
    模式速度
    标准模式(Standard Mode)100kb/s
    快速模式(Fast Mode)400kb/s
    增强快速模式(Fast Mode Plus)1Mb/s
    高速模式(High Speed Mode)3.4Mb/s
    极速模式(Ultra-FastMode)5Mb/s

    三、硬件结构

     1. 总线结构

      IIC使用两根信号线进行通信,要求两根线都使用 开漏输出接上拉电阻 的配置,以此实现总线上所有节点SDA、SCL信号的 线与 逻辑关系。
      Rp电阻的取值有一定的要求,太小会导致灌入电流过大,使’低’数据不稳定,甚至损坏端口;太大会导致信号上升缓慢,使得数据传输出错。在不同应用场景及供电电压下有不同的取值要求。

    在这里插入图片描述
      线与 逻辑使得总线上不会出现数据冲突,实现了总线的仲裁控制。总线的控制权会交给最后一个输出低电平的设备,其它设备(输出高)通过检测总线上的电平状态(状态低),对比与自己输出状态不一致,则自动退出对总线的控制请求,从而防止了总线上的数据冲突。
      漏极开路/集电极开路的缺点是对于一个距离长的数据线,信号传输速率得不到有效保证。更长的走线对于输出驱动器表现为更大的容性负载,等效容性负载C和信号线的上拉电阻R构成RC振荡器。RC越大,意味着反射和振荡越强,从而影响总线的信号完整性。这也是I2C规范对总线电容值约束在400pf以内的原因。高速模式对信号完整性的要求更高,协议有定义相关SDA/SCL处理办法,以保证在数据线够长、速率够高时,信号完整性也可以得到满足。


     2. 总线的拉高和拉低

      下图展示了IIC总线拉低和拉高的过程。

    • 拉低:设备的逻辑电路控制FET打开,总线通过导通的FET连接到GND从而被拉低
    • 拉高:设备的逻辑电路控制FET关闭,总线通过上拉电阻Rp连接到VDD从而被拉高
      总线变化

    四、工作时序

     1. 数据有效性

      IIC 的数据读取动作都在 SCL为高 时产生,SCL为低时是数据改变的时期,无论SDA如何变化都不影响读取。所以,传输数据的过程中,当SCL为高时,数据应当保持稳定,避免数据的采集出错。

    在这里插入图片描述


     2. 开始和结束信号

       开始信号(START/S): SCL为高时,SDA从高到低的跳变产生开始信号
       结束信号(STOP/P)  : SCL为高时,SDA从低到高的跳变产生结束信号
    在这里插入图片描述


     3. 重复开始信号

       重复开始信号(ReSTART/Sr): 在结束时不给出STOP信号,而以一个时钟周期内再次给出开始信号作为替代


     4. 字节格式

       SDA数据线上的每个字节必须是8位,对于每次传输的字节数没有限制。每个字节(8位)数据传送完后紧跟着应答信号(ACK,第9位)。数据的先后顺序为:高位在前

    在这里插入图片描述


     5. 应答信号

      协议规定数据传输过程必须包含应答(ACK)。接收器通过应答告知发送的字节已被成功接收,之后发送器可以进行下一个字节的传输。主机产生数据传输过程中的所有时钟,包括用于应答的第9个时钟。发送器在应答时钟周期内释放对SDA总线的控制,这样接收器可以通过将SDA线拉低告知发送器:数据已被成功接收。
      应答信号分为两种:
        1)当第9位(应答位)为 低电平 时,为 ACK  (Acknowledge)   信号
        2)当第9位(应答位)为 高电平 时,为 NACK(Not Acknowledge)信号
      主机发送数据,从机接收时,ACK信号由从机发出。当在SCL第9位时钟高电平信号期间,如果SDA仍然保持高电平,则主机可以直接产生STOP条件终止以后的传输或者继续ReSTART开始一个新的传输
      从机发送数据,主机读取数据时,ACK信号由主机给出。主机响应ACK表示还需要再接收数据,而当主机接收完想要的数据后,通过发送NACK告诉从机读取数据结束、释放总线。随后主机发送STOP命令,将总线释放,结束读操作。
    在这里插入图片描述


    五、7-bit 设备的数据传输

      一个完整的7-bit通信过程如图所示:

    在这里插入图片描述
      在START信号后的首字节由7位从机地址和1位读写位组成,结构如下图:
    在这里插入图片描述

      发送完这个字节之后,主机释放SDA总线等待从机给出ACK应答。如果从机给出了ACK应答,表示从机地址正确(有从机响应)并且已知晓是读还是写,便可以开始读写数据。如果从机没有给出ACK应答,则说明接收设备可能没有收到数据(如寻址的设备不存在或是设备正在忙碌)或无法解析收到的数据,如果是这样,则由master来决定如何处理(STOP或ReSTART)。


     1. 主机写-从机收,传输方向不变

      主机对从机发送数据时,主机对从机发送一个开始字节,然后即可一直发送数据。以示例来讲解,其第一帧数据为要操作的寄存器地址,所以为:“[1-Byte]开始字节(写) + [1-Byte]寄存器地址 + [1-Byte]寄存器数据”。

    请添加图片描述

     2. 主机读-从机发,传输方向改变

      主机对向从机读取数据时,方式同发送数据有所不同,要多一次通信过程。
      主机需要先向从机发送一次信号,告诉从机”我要读取数据“,然后重开一次通信,等待从机主动返回数据。以示例来讲解,发送 “[1-Byte]开始字节(写) + [1-Byte]要读取的寄存器的地址”,之后结束通信,或者重开始,来进入到第二次通信中,先发送 [1-Byte]开始字节(读),然后等待读取从机发送过来的 [1-Byte]数据 即可。

    请添加图片描述

    六、10-bit 设备的数据传输

      随着IIC设备日益增多,7位的从机地址逐渐不能满足使用,于是从机地址从7位扩充到了10位。7位和10位地址的设备可以共存于同一个I2C总线系统互不冲突,展现了良好的兼容性。
      10-bit 地址的IIC设备需要 2-Byte 来传输从设备地址信息,所以采用了这样的设计:第一个字节为 1111 0 + 地址高两位(第10、9bit) + 读写控制位,第二个字节为从设备地址低8位,除此之外与7-bit设备相同。因为 “1111 0xx” 为 IIC 中特地保留的16个特殊指令地址中的一个,所以7-bit设备不会响应该首字节的呼叫,只有10-bit设备会响应,从而实现良好兼容。

     1. 10-bit 设备的写

      10-bit设备的写过程如下图示例,除地址部分外与7-bit相同。

    请添加图片描述


     2. 10-bit 设备的读

      10-bit设备的读过程如下图示例,需注意的是,第二次通信过程无需再次发送第2Byte地址。

    请添加图片描述

    更多相关内容
  • I2C通信(简单入门)

    2017-03-15 15:56:57
    容易理解的I2C通信协议教程
  • I2C时序图的详细讲解

    2018-03-26 19:32:42
    I2C时序图的详细讲解,简易时序图,经典I2C测试讲解
  • I2C通信协议详解和通信流程分析

    千次阅读 2022-03-19 21:01:15
    1、I2C通信特征 1.1、物理接口:SCL + SDA 1.2、通信特征:串行、同步、非差分、低速率 1.3、通信模式:主设备+从设备 1.4、可以多个设备挂在一条总线上 1.5、主要用途 2、I2C控制器的结构框图 3、I2C控制器的模式 4...

    1、I2C通信特征

    1.1、物理接口:SCL + SDA

    (1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道。
    (2)SDA(serial data): 数据线,通信数据都通过SDA线传输

    1.2、通信特征:串行、同步、非差分、低速率

    串行:只有一根数据线,每次传输一个bit位;
    同步:主设备和从设备的工作时钟频率是一样的,主设备通过SCL时钟线给从设备提供时钟频率;
    非差分:因为I2C通信速率不高,而且通信双方距离很近,一般是板级通信,所以使用电平信号通信;
    低速率:I2C一般是用在同一个板子上的2个IC之间的通信,而且用来传输的数据量不大,所以本身通信速率很低。一般几百KHz,不同的I2C芯片的通信速率可能不同,具体在编程的时候要看自己所使用的设备允许的I2C通信最高速率,不能超过这个速率;

    1.3、通信模式:主设备+从设备

    (1)I2C通信时,通信设备之间的地位是平等的,分为主设备和从设备,其中主设备一个、从设备多个。主设备要主导整个通信过程,从设备根据I2C协议被动的响应主设备;
    (2)在I2C通信中,没有规定谁做主设备、谁做从设备,是通信双方自己协商的。一个设备在同一时间只能做主设备或者从设备,但是有的设备可以通过软件配置来决定在此次通信时做主设备还是从设备。

    1.4、可以多个设备挂在一条总线上

    在这里插入图片描述

    (1)I2C总线上可以挂载一个主设备和多个从设备,实现一对一(一个主设备 + 一个从设备)或者一对多(一个主设备 + 多个从设备)的通信;
    (2)主设备负责调度总线,决定某个时间和其中一个从设备通信。在同一时间,只有主设备和其中一个从设备通信,其余的从设备处于等待状态,等待主设备与其通信;
    (3)每个从设备在I2C总线上都有唯一的地址,主设备就是通过地址来区分不同的从设备,从而决定和哪一个从设备通信。

    1.5、I2C总线的状态

    空闲态:当SCL与SDA同时为高电平时,为空闲态;
    忙态:主设备和从设备正在通信;
    起始状态:当主设备在I2C总线上发出起始信号,开始一次通信;
    停止状态:当主设备在I2C总线上发出停止信号,停止本次通信;

    1.6、I2C总线协议

    (1)主设备发送一个起始信号;
    (2)主设备接着发送8bit数据,其中7位是从设备的地址,一位表示此次主设备是要读数据海思写数据;
    (3)和主设备发送的地址匹配的从设备发出一个ack响应信号;
    (4)主/从设备将数据发送到SDA总线上,每次传输都是8bit数据;
    (5)主/从设备从SDA线上接收数据,并发送一个ACK响应信号;
    (6)还可以接着n个发送和接收的过程;
    (7)主设备发送停止信号,停止本次通信;

    1.7、I2C从设备地址

    (1)I2C通信的每次有效数据都是8bit,从设备地址是7bit,但是I2C主设备发送从设备地址时还是发送的8bit;
    (2)在主设备发送从设备地址时,8bit数据中高7位是从设备地址,最低一位(LSB)是表示读写位;
    (3)举例:KXTE9芯片的I2C地址固定为0b0001111(0x0f),最低位是1表示主设备读从设备,最低位是0则表示主设备写从设备。主设备读从设备时SAD是0b00011111,主设备写从设备SAD应该是0b00011110。

    1.8、从设备地址知识补充

    (1)一般从设备的地址都是固定的,在数据手册里可以查到,这也就是意味着在同一条I2C总线上,不能有两个及以上的同款从设备,不然就无法通过从地址来区分这两个设备。大多数的从设备地址都是固定的,因为没有必要同时接两个,比如重力传感器,你接一个就可以测出重力加速度,何必接两个。但是也有些设备需要同时接多个,比如一块EEPROM芯片(I2C接口)的容量不够就可能接两个。对于这种情况,生成EEPROM的厂家是做了预留的,EEPROM芯片的从地址一部分是固定的,一部分是通过给EEPROM芯片的引脚接高低电平来决定的。
    (2)假设EEPROM芯片的7位地址,其中高5位是固定的0b111111,低两位是根据两个引脚的高低电平来确定,接高电平代表1,接低电平代表0。一块芯片把两个引脚接高电平,则从设备地址是0b11111111;另一块芯片把两个引脚把低电平,则从设备地址是0b111100。

    1.9、主要用途

    I2C通常是用在板级通信的,距离很近,Soc和各种外设的通信就是I2C通信方式,比如触摸屏、各种sensor等,外设的数据手册里会说明通信方式;

    2、I2C控制器的结构框图

    在这里插入图片描述

    (1)最左侧是I2C总线的时钟来源,来源是时钟系统的PCLK_PSYS,PCLK_PSYS经过分频后得到I2C总线的时钟频率,然后主设备会通过SCL线将时钟信号传给从设备;
    (2)I2C总线的控制单元,里面包含两个重要的寄存器:I2CCON和I2CSTAT寄存器。控制单元会对PCLK_PSYS时钟信号进行两级分频,产生通信需要的时序信号,配置I2C设备的主从模式等,具体细节看两个寄存器的说明;
    (3)Address Register和Comparator是当设备作为从设备时用到的,Address Register寄存器里保存的是自己作为从设备的地址,Comparator是比较器,比较此次从I2C设备收到的地址是否和自己的地址相等,如果相等则代表主设备要和自己通信,如果不相等,就不用对此次通信做任何处理。
    (3)Shift Register和I2CDS:I2CDS寄存器是保存接收/发送的数据,Shift Register是移位寄存器,负责将I2CDS寄存器里的数据一位一位的发送SDA总线上,或者将总线上的数据一位一位的存到I2CDS总线上,这要看当时是发送模式还是接收模式。

    3、I2C控制器的模式

    (1)主设备发送模式;
    (2)主设备接收模式;
    (3)从设备发送模式;
    (4)从设备接收模式;
    备注:设备可以是上面四个模式中的任意一种,但是同一时间只能是其中的一种,要么是作为主设备要么是作为从设备。

    4、I2C的时序分析

    4.1、时序介绍

    时序就是时间顺序,实际上在通信中时序就是通信线上按照时间顺序发生的电平变化,以及这些变化对通信的意义就叫时序,不对的通信的协议对时序的要求不同。

    4.2、通信起始条件和结束条件

    在这里插入图片描述

    起始信号:在SCL为高电平的时候,SDA产生一个下降沿;
    停止信号:在SCL为高电平的时候,SDA产生一个上升沿;

    4.3、数据有效性

    在这里插入图片描述

    (1)SDA 线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。SCL为高电平时表示有效数据,SDA为高电平表示“1”,低电平表示“0”;SCL为低电平时表示无效数据,此时SDA会进行电平切换,为下次数据表示做准备。
    (2)数据有效性:在I2C总线通信时,在总线上传输的数据并不都是有效数据。比如开始信号和停止信号,并不代表什么实际的含义,只是通信协议里规定的。正因为我们的有效数据应该在SCL为高电平时SDA保持稳定,所以才能区分出开始信号和停止信号。

    4.4、响应ACK

    在这里插入图片描述

    主/从设备在发送完一次数据后,需要一个ACK响应信号。每个通信周期传输8个数据,在第九个通信周期,发送端将SDA总线拉高,然后释放总线的控制权。如果接收端在第九个周期将SDA拉低,就是发出了ACK信号,如果在第几个周期SDA一直是高电平则代表没有发出ACK信号。

    4.5、空闲态

    在这里插入图片描述

    空闲态:在I2C总线上没有主、从设备进行通信,此时SCL和SDA一直保持高电平;

    5、I2C总线的读/写数据操作

    在这里插入图片描述

    5.1、写模式

    (1)主设备发送开始信号;
    (2)主设备接着发送8bit数据,其中7bit是从设备的地址,1bit表示此次主设备是要读数据还是写数据;
    (3)从设备发送ACK响应信号;
    (4)主设备将要写的数据每次发送8bit到SDA线上,从设备接收到发送ACK响应信号;
    (5)当主设备发送完数据后,发送一个停止信号;

    5.2、读模式

    (1)主设备发送开始信号;
    (2)主设备接着发送8bit数据,其中7bit是从设备的地址,1bit表示此次主设备是要读数据还是写数据;
    (3)从设备发送ACK响应信号;
    (4)从设备将数据每次发送8bit到SDA线上,主设备接收到发送ACK响应信号;
    (5)当主设备接收完数据后,发送一个停止信号;

    6、I2C的通信流程

    6.1、I2C通信的主设备发送流程

    在这里插入图片描述

    (1)通过操作I2CCON寄存器,将设备配置成主发送模式;
    (2)将从设备的地址写到I2CDS寄存器中;
    (3)往I2CSTAT寄存器写0xF0,让I2C控制器产生一个开始信号;
    (4)移位寄存器将I2CDS里的数据发送到SDA总线上;
    (5)在收到ACK信号后,中断被挂起,需要中断处理程序来处理;
    (6)中断处理程序判断是否是要结束本次通信;
    (7)如果不是结束本次通信,则将新的数据写到I2CDS寄存器中,然后清中断挂起标志,将数据发送到SDA总线上,等待ACK信号,进入下一次判断;
    (8)如果是要结束本次通信,则往I2CSTAT寄存器中写0xD0,产生一个停止信号,清中断挂起标志,等停止信号发送完毕则结束本次通信;

    6.2、I2C通信的主设备接收流程

    在这里插入图片描述

    (1)通过操作I2CCON寄存器,将设备配置成主接收模式;
    (2)将从设备的地址写到I2CDS寄存器中;
    (3)往I2CSTAT寄存器写0xB0,让I2C控制器产生一个开始信号;
    (4)移位寄存器将I2CDS里的数据发送到SDA总线上;
    (5)在收到ACK信号后,中断被挂起,需要中断处理程序来处理;
    (6)中断处理程序判断是否是要结束本次通信;
    (7)如果不是结束本次通信,则从I2CDS寄存器中读取数据,清中断挂起标志,移位器将SDA上的数据再存到I2CDS寄存器中,进入下一次循环判断;
    (8)如果是要结束本次通信,则往I2CSTAT寄存器中写0x90,产生一个停止信号,清中断挂起标志,等停止信号发送完毕则结束本次通信;

    6.3、I2C通信的从设备接收流程

    在这里插入图片描述

    (1)通过操作I2CCON寄存器,将设备配置成从接收模式;
    (2)在SDA总线上检测到开始信号,I2CDS寄存器接收到数据;
    (3)将I2CDS寄存器中接收到的数据和I2CADD寄存器中保存的地址进行比较;
    (4)判断是否匹配;
    (5)如果不匹配,则表示主设备不是和自己通信,不用再进行下面的步骤;
    (6)I2C地址匹配则中断产生,告诉设备主设备要和自己通信,并发送一个ACK信号;
    (7)从SDA总线上读取数据、处理数据,并发送一个ACK信号,然后清中断;
    (8)判断是否要停止本次通信,也就是有没有检测到主设备发送停止信号;
    (9)如果不停止通信,则再次从SDA总线上将数据读取到I2CDS寄存器中,然后产生中断,重复之前的步骤;
    (10)如果是停止本次通信,则不再做响应即可;

    6.4、I2C通信的从设备发送流程

    在这里插入图片描述

    (1)通过操作I2CCON寄存器,将设备配置成从发送模式;
    (2)在SDA总线上检测到开始信号,I2CDS寄存器接收到数据;
    (3)将I2CDS寄存器中接收到的数据和I2CADD寄存器中保存的地址进行比较;
    (4)判断是否匹配;
    (5)如果不匹配,则表示主设备不是和自己通信,不用再进行下面的步骤;
    (6)I2C地址匹配则中断产生,告诉设备主设备要和自己通信,并发送一个ACK信号;
    (7)写数据到I2CDS寄存器,然后清中断;
    (8)判断是否要停止本次通信,也就是有没有检测到主设备发送停止信号;
    (9)如果不停止通信,则将I2CDS寄存器中的数据发送到SDA总线上,然后产生中断,重复之前的步骤;
    (10)如果是停止本次通信,则不再做响应即可;

    7、I2CCON寄存器

    在这里插入图片描述>(1)bit0-3:配置I2C时钟信号的二级分频系数;
    (2)bit4:中断挂起标志;
    (3)bit5:I2C总线的发送/接收使能;
    (4)bit6:配置I2C时钟信号的一级分频系数;
    (5)bit7:配置I2C总线是否要在每次通信周期的末尾发送ACK响应信号;

    8、I2CSTAT寄存器

    在这里插入图片描述

    (1)bit0:判断上一次的通信周期是否收到ACK响应信号;
    (2)bit1:I2C总线的地址清零标志;
    (3)bit2:I2C总线从设备的地址标志位;
    (4)bit3:I2C的总线总裁标志位;
    (5)bit4:发送/接收使能位;
    (6)bit5:如果是读,0代表总线空闲,1代表总线忙;如果是写,写0则I2C控制器发出一个停止信号,写1则I2C控制器发出一个开始信号;
    (7)bit6-7:配置设备的模式;

    9、分析KXTF9-2050芯片的I2C通信协议

    参考博客:《通过KXTF9-2050芯片分析I2C协议》

    展开全文
  • I2C通信协议详细讲解

    千次阅读 多人点赞 2020-12-13 23:08:59
    I2C协议讲解讲解流程我们为什么要学习I2C通信I2C协议简介:I2C物理层特点I2C协议层写数据读数据读和写数据通讯的起始和停止信号地址及数据方向 讲解流程 我们为什么要学习I2C通信 Stm32的最常用的板间通信有很多,有...

    实验准备

    一块STM32最小系统板,BH1750模块,一块PCB转换板模块、串口TTL转USB模块
    图片:
    在这里插入图片描述
    在这里插入图片描述

    PCB转换板原理图及PCB电路图

    在这里插入图片描述
    在这里插入图片描述

    讲解流程

    我们为什么要学习I2C通信

    Stm32的最常用的板间通信有很多,有I2C、SPI、CAN;I2C通信协议是我们stm32板间通信比较常用的、也是比较简单的。

    I2C协议简介:

    I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、 CAN 等通讯协议的外部收发设备,所以被广泛使用。

    I2C物理层特点

    (1)它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
    (2)一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
    (3)每一个连接总线的设备都有一个独立的地址,主机可以通过这个地址进行选择连接总线的设备与之通信。
    (4)总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
    (5)多个主机同时使用总线时,为了防止多个设备发送数据冲突,会利用仲裁方式决定由哪个设备占用总线。
    (6) 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。
    (7) 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。
    备注:
    仲裁:SDA线的仲裁也是建立在总线具有线“与”逻辑功能(线与逻辑,即两个以上的输出端直接互连就可以实现“AND”的逻辑功能。两个一出一,一个一出零、没有一出零)的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,进行比较,输出低电平进行发送,输出高电平退出。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线。

    在这里插入图片描述

    I2C协议层

    在这里插入图片描述

    S:由主机的 I2C 接口产生的传输起始信号(S),这时连接到 I2C 总线上的所有从机都会接收到这个信号。
    SLAVE ADDRESS:从机地址信号。 在 I2C 总线上,每个设备的地址都是唯一的, 当主机广播的地址与某个设备地址相同时,这个设备就被选中了,没被选中的设备将会忽略之后的数据信号。从机地址一般是 7 位或 10 位。
    R/W:是传输方向的选择位,该位为 0 时,表示后面的数据传输方向是由主机传输至从机,即主机向从机写数据。该位为 1 时,则相反,即主机由从机读数据。
    A | A/:一个应答(ACK)或非应答(NACK)信号。
    P:停止传输信。
    图中背景有填充的矩形表示 数据由主机传输至从机

    写数据

    讲得简单一点,即主机发送信息、从机阅读信息。配置为方向为“写数据”方向,接受的数据包大小为8位(一个byte),主机每发送完一个字节数据,都要等待从机的应答信号(ACK),重复这个过程,数据的多少可以理论是可以随便的。当数据传输结束时,主机向从机发送一个停止传输信号§,表示不再传输数据。

    读数据

    讲得简单一点,即主机阅读信息、从机发送信息。若配置的方向传输位为“读数据”方向,发送的数据包大小也为 8 位,从机每发送完一个数据,都会等待主机的应答信号(ACK),重复这个过程,数据的多少可以理论也是可以随便的。当主机希望停止接收数据时,就向从机返回一个非应答信号(NACK),则从机自动停止数据传输。

    读和写数据

    除了基本的读写,I2C 通讯更常用的是复合格式,该传输过程有两次起始信号(S)。一般在第一次传输中,主机通过 SLAVE_ADDRESS 寻找到从设备后,发送一段“数据”,这段数据通常用于表示从设备内部的寄存器或存储器地址(注意区分它与 SLAVE_ADDRESS 的区别);在第二次的传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。

    通讯的起始和停止信号

    在这里插入图片描述

    当 SCL 线是高电平时 SDA 线从高电平向低电平切换,这个情况表示通讯的起始。当 SCL 是高电平时 SDA线由低电平向高电平切换,表示通讯的停止。起始和停止信号一般由主机产生。
    在这里插入图片描述

    I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。见图 24-6。 SDA数据线在 SCL 的每个时钟周期传输一位数据。传输时, SCL 为高电平的时候 SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL为低电平时, SDA 的数据无效,一般在这个时候 SDA 进行电平切换,为下一次表示数据做好准备。
    每次数据传输都以字节为单位,每次传输的字节数不受限制。

    地址及数据方向

    I2C 总线上的每个设备都有自己的独立地址,主机发起通讯时,通过 SDA 信号线发送设备地址(SLAVE_ADDRESS)来查找从机。 I2C 协议规定设备地址可以是 7 位或 10 位,实际中 7 位的地址应用比较广泛。紧跟设备地址的一个数据位用来表示数据传输方向,它是数据方向位(R/),第 8 位或第 11 位。数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
    在这里插入图片描述

    再提一嘴,读数据方向时,主机会释放对 SDA 信号线的控制,由从机控制 SDA 信号线,主机接收信号,写数据方向时, SDA 由主机控制,从机接收信号。切记,不要混淆。

    时钟控制逻辑

    SCL 线的时钟信号,由 I2C 接口根据时钟控制寄存器(CCR)控制,控制的参数主要为时
    钟频率。配置 I2C 的 CCR 寄存器可修改通讯速率相关的参数:

    • 可选择 I2C 通讯的“标准/快速”模式,这两个模式分别 I2C 对应 100/400Kbit/s 的
      通讯速率。

    • 在快速模式下可选择 SCL 时钟的占空比,可选 Tlow/Thigh=2 或 Tlow/Thigh=16/9
      模式,我们知道 I2C 协议在 SCL 高电平时对 SDA 信号采样, SCL 低电平时 SDA
      准备下一个数据,修改 SCL 的高低电平比会影响数据采样,但其实这两个模式的
      比例差别并不大,若不是要求非常严格,这里随便选就可以了。

    • CCR 寄存器中还有一个 12 位的配置因子 CCR,它与 I2C 外设的输入时钟源共同
      作用,产生 SCL 时钟, STM32 的 I2C 外设都挂载在 APB1 总线上,使用 APB1 的
      时钟源 PCLK1, SCL 信号线的输出时钟公式如下:

       	标准模式:
       	Thigh=CCR*TPCKL1
       	Tlow=CCR*TPCLK1
       	 
       	快速模式中 Tlow/Thigh=2 时:
       	Thigh = CCR*TPCKL1 
       	Tlow = 2*CCR*TPCKL1
       	
       	快速模式中 Tlow/Thigh=16/9 时:
       	Thigh = 9*CCR*TPCKL1 
       	Tlow = 16*CCR*TPCKL1
      

    例如,我们的 PCLK1=36MHz,想要配置 400Kbit/s 的速率,计算方式如下:
    PCLK 时钟周期: TPCLK1 = 1/36000000
    目标 SCL 时钟周期: TSCL = 1/400000
    SCL 时钟周期内的高电平时间: THIGH = TSCL/3
    SCL 时钟周期内的低电平时间: TLOW = 2*TSCL/3
    计算 CCR 的值: C C R = T H I G H T P C L K 1 = T S C L 3 1 36000000 = 1 400000 3 1 36000000 = 36000000 1200000 = 30 CCR ={THIGH\over TPCLK1} ={{TSCL\over 3}\over {1\over 36000000} }={{{1\over 400000}\over 3}\over {1\over 36000000} }={36000000\over 1200000}=30 CCR=TPCLK1THIGH=3600000013TSCL=36000000134000001=120000036000000=30

    注:计算结果得出 CCR 为 30,向该寄存器位写入此值则可以控制 IIC 的通讯速率为400KHz,其实即使配置出来的 SCL 时钟不完全等于标准的 400KHz,IIC 通讯的正确性也不会受到影响,因为所有数据通讯都是由 SCL 协调的,只要它的时钟频率不远高于标准即可。

    通讯过程

    使用 I2C 外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及 SR2)”的不同数
    据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。

    主发射器

    在这里插入图片描述

    主发送器发送流程及事件说明如下:

    1. 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对 SR1 寄
      存器的“SB”位置 1,表示起始信号已经发送;
    2. 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“ EV6”及
      “EV8”,这时 SR1 寄存器的“ADDR”位及“TXE”位被置 1, ADDR 为 1 表
      示地址已经发送, TXE 为 1 表示数据寄存器为空;
    3. 以上步骤正常执行并对 ADDR 位清零后,我们往 I2C 的“数据寄存器 DR”写入
      要发送的数据,这时 TXE 位会被重置 0,表示数据寄存器非空, I2C 外设通过
      SDA 信号线一位位把数据发送出去后,又会产生“EV8”事件,即 TXE 位被置 1,
      重复这个过程,就可以发送多个字节数据了;
    4. 当我们发送数据完成后,控制 I2C 设备产生一个停止信号§,这个时候会产生
      EV8_2 事件, SR1 的 TXE 位及 BTF 位都被置 1,表示通讯结束。

    假如我们使能了 I2C 中断,以上所有事件产生时,都会产生 I2C 中断信号,进入同一
    个中断服务函数,到 I2C 中断服务程序后,再通过检查寄存器位来判断是哪一个事件。

    主接收器

    在这里插入图片描述

    主接收器接收流程及事件说明如下:

    1. 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事
      件“EV5”,并会对 SR1 寄存器的“SB”位置 1,表示起始信号已经发送;
    2. 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“ EV6”这时
      SR1 寄存器的“ADDR”位被置 1,表示地址已经发送。
    3. 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产
      生“EV7”事件, SR1 寄存器的 RXNE 被置 1,表示接收数据寄存器非空,我们
      读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控
      制 I2C 发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收
      数据,若非应答,则停止传输;
    4. 发送非应答信号后,产生停止信号§,结束传输。

    在发送和接收过程中,有的事件不只是标志了我们上面提到的状态位,还可能同时标
    志主机状态之类的状态位,而且读了之后还需要清除标志位,比较复杂。我们可使用
    STM32 标准库函数来直接检测这些事件的复合标志,降低编程难度。

    通讯引脚

    引脚I2C1I2C2
    SCLPB5/PB8(重映射)PB10
    SDAPB6/PB9(重映射)PB11

    I2C程序讲解

    讲了怎么多的理论知识,相信大部分人都困了,对I2C通信还有诸多疑问,但没关系,看不懂可以多看几次就可以看懂了,或者通过一个程序理解。那么我们来写一个使用I2C通信的传感器设备BH1750。BH1750光强度传感器的介绍此传感器可以直接输出环境光强的数值(单位为lx),其内部有16位AD转换,即可表示1lx-65535lx,通过IIC输出其数值。此传感器有3种分辨率模式,他们的分辨率分别为:4lx,1lx和0.5lx。他们的测量时间分别为:16ms,120ms,120ms。如果对测量时间要求不高的话,建议使用0.5lx分辨率的。

    初始化BH1750光照度传感器的大致流程为:

    GPIO初始化
    发送打开模块等待测量指令0x01
    发送重置数据寄存器值0x07但仅在PowerOn模式下有效
    发送选择连续L分辨率模式指令0x13
    获取光照度并转发串口

    器件安装

    在这里插入图片描述

    程序源码

    看过了流程,那就将流程图转代码吧。

    main函数

    int main(void)
    {	
    	delay_init();	    	 //延时函数初始化
    	uart_init(115200);		 //串口函数初始化
    	Light_Init();		 	 //GPIO初始化
    	bh_data_send(BHPowOn);	 //发送打开模块等待测量指令0x01
    	bh_data_send(BHReset);	 //发送重置数据寄存器值0x07但仅在PowerOn模式下有效
    	bh_data_send(BHModeL);	 //发送选择连续L分辨率模式指令0x13
    	delay_ms(180);
    	
    	while(1)
    	{
    		printf("%d\r\n",bh_data_read()); //获取光照度并通过串口转发
    		delay_ms(100);
    	}
    }
    

    Light_Init函数:

    void Light_Init(void)
    {
    	GPIO_InitTypeDef  GPIO_InitStructure;
     	
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 	//使能A端口时钟
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	 	//设置PB6和PB7
     	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	//推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//速度50MHz
     	GPIO_Init(GPIOB, &GPIO_InitStructure);	 				    //初始化GPIOB6,7
     	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);	 				//设置PB6和PB7输出高电平
    
    	Single_Write_BH1750(0x01); 									//发送设备地址
    }
    
    //发送地址值函数
    void Single_Write_BH1750(uchar REG_Address)
    {
       IIC_Start();                  //起始信号
       IIC_Send_Byte(BHAddWrite);   //发送设备地址+写信号
       IIC_Send_Byte(REG_Address);    //内部寄存器地址,
      //  BH1750_SendByte(REG_data);       //内部寄存器数据,
       IIC_Stop();                   //发送停止信号
    }
    

    bh_data_send函数:

    void bh_data_send(u8 command)
    {
        do{
    		IIC_Start();                   //iic起始信号
    		IIC_Send_Byte(BHAddWrite);     //发送器件地址
        }while(IIC_Wait_Ack());            //等待从机应答
        IIC_Send_Byte(command);            //发送指令
        IIC_Wait_Ack();                    //等待从机应答
        IIC_Stop();                        //iic停止信号
    }
    

    看不懂这个函数为什么这么做,可以对照主发送器通讯过程
    在这里插入图片描述

    首先发送iic起始信号和器件地址,等待从机返回应答信号,然后发送指令,继续等待从机返回应答信号,如果没有指令要继续发送的话,那么可以发送iic停止信号而不发送指令。那么一个发送函数就算完成了。关于iic函数我会下面进行讲解的。

    bh_data_read函数:

    //读取传感器发送的数据,从而获取光照度函数
    u16 bh_data_read(void)
    {
    	u16 buf;
    	IIC_Start();                       //iic起始信号
    	IIC_Send_Byte(BHAddRead);         //发送器件地址+读标志位
    	IIC_Wait_Ack();                     //等待从机应答
    	buf=IIC_Read_Byte(1);              //读取数据
    	buf=buf<<8;                        //读取并保存高八位数据
    	buf+=0x00ff&IIC_Read_Byte(0);      //读取并保存低八位数据
    	IIC_Stop();                        //发送停止信号 
    	return buf; 
    }
    

    看不懂这个读取函数,同样可以对照主接受器接收过程
    在这里插入图片描述

    先声明一个无符号16位的buf变量准备存储数据,然后发送iic起始信号和器件地址,等待从机返回应答信号,然后将读取的高八位数据赋予给buf,因为是高八位数据,但buf里的数据并没有在高八位而在低八位,那么我们就要就数据左移八位将数据放在高八位,有了高八位数据但没有低八位数据怎么行,那么我们就在获取一次放在buf里就可以了,获取数据后,就没有其他事情干了,发送IIC停止信号就可以结束了。

    前面的发送函数和接收函数里发送和接收的原理还没有说呢,现在新建一个iic.c文件 和 iic.h文件,对照着下面的两张时序图去写代码。

    在这里插入图片描述
    在这里插入图片描述

    代码大致如下:
    iic.c文件

    #include "IIC.h"
    #include "sys.h"
    
    typedef   unsigned char BYTE;
    //BYTE    BUF[8];                         //接收数据缓存区   
    
    //产生IIC起始信号
    void IIC_Start(void)
    {
    	SDA_OUT();     //sda线输出
    	IIC_SDA=1;	  	  
    	IIC_SCL=1;
    	delay_us(4);
     	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    	delay_us(4);
    	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
    }	  
    //产生IIC停止信号
    void IIC_Stop(void)
    {
    	SDA_OUT();//sda线输出
    	IIC_SCL=0;
    	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
     	delay_us(4);
    	IIC_SCL=1; 
    	IIC_SDA=1;//发送I2C总线结束信号
    	delay_us(4);							   	
    }
    //等待应答信号到来
    //返回值:1,接收应答失败
    //        0,接收应答成功
    u8 IIC_Wait_Ack(void)
    {
    	u8 ucErrTime=0;
    	SDA_IN();      //SDA设置为输入  
    	IIC_SDA=1;delay_us(1);	   
    	IIC_SCL=1;delay_us(1);	 
    	while(READ_SDA)
    	{
    		ucErrTime++;
    		if(ucErrTime>250)
    		{
    			IIC_Stop();
    			return 1;
    		}
    	}
    	IIC_SCL=0;//时钟输出0 	   
    	return 0;  
    } 
    //产生ACK应答
    void IIC_Ack(void)
    {
    	IIC_SCL=0;
    	SDA_OUT();
    	IIC_SDA=0;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }
    //不产生ACK应答		    
    void IIC_NAck(void)
    {
    	IIC_SCL=0;
    	SDA_OUT();
    	IIC_SDA=1;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }					 				     
    //IIC发送一个字节
    //返回从机有无应答
    //1,有应答
    //0,无应答			  
    void IIC_Send_Byte(u8 txd)
    {                        
        u8 t;   
    	SDA_OUT(); 	    
        IIC_SCL=0;//拉低时钟开始数据传输
        for(t=0;t<8;t++)
        {              
            //IIC_SDA=(txd&0x80)>>7;
    		if((txd&0x80)>>7)
    			IIC_SDA=1;
    		else
    			IIC_SDA=0;
    		txd<<=1; 	  
    		delay_us(2);   //对TEA5767这三个延时都是必须的
    		IIC_SCL=1;
    		delay_us(2); 
    		IIC_SCL=0;	
    		delay_us(2);
        }	 
    } 	    
    //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
    u8 IIC_Read_Byte(unsigned char ack)
    {
    	unsigned char i,receive=0;
    	SDA_IN();//SDA设置为输入
        for(i=0;i<8;i++ )
    	{
            IIC_SCL=0; 
            delay_us(2);
    		IIC_SCL=1;
            receive<<=1;
            if(READ_SDA)receive++;   
    		delay_us(1); 
        }					 
        if (!ack)
            IIC_NAck();//发送nACK
        else
            IIC_Ack(); //发送ACK   
        return receive;
    }
    

    iic.h文件

    #ifndef __IIC_H
    #define __IIC_H
    
    //库名
    #include "stm32f10x.h"
    #include "delay.h"
    
    #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
    
    
    
    #define IIC_SCL    PBout(6) //SCL
    #define IIC_SDA    PBout(7) //SDA	 
    #define READ_SDA   PBin(7)  //输入SDA 
    #define ADDR 0x23//0100011
    #define uchar unsigned char 
    
    #define BHAddWrite     0x46      //从机地址+最后写方向位
    #define BHAddRead      0x47      //从机地址+最后读方向位
    #define BHPowDown      0x00      //关闭模块
    #define BHPowOn        0x01      //打开模块等待测量指令
    #define BHReset        0x07      //重置数据寄存器值在PowerOn模式下有效
    #define BHModeH1       0x10      //高分辨率 单位1lx 测量时间120ms
    #define BHModeH2       0x11      //高分辨率模式2 单位0.5lx 测量时间120ms
    #define BHModeL        0x13      //低分辨率 单位4lx 测量时间16ms
    #define BHSigModeH     0x20      //一次高分辨率 测量 测量后模块转到 PowerDown模式
    #define BHSigModeH2    0x21      //同上类似
    #define BHSigModeL     0x23      // 上类似
    
    //IIC所有操作函数
    void IIC_Init(void);                //初始化IIC的IO口				 
    void IIC_Start(void);				//发送IIC开始信号
    void IIC_Stop(void);	  			//发送IIC停止信号
    void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
    u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
    u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
    void IIC_Ack(void);					//IIC发送ACK信号
    void IIC_NAck(void);				//IIC不发送ACK信号	
    
    #endif 
    

    看了怎么多代码,相信还是懵懵懂懂,但只要多看几遍就会理解了的。

    展开全文
  • 一、I2C协议 I2C 也叫 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。 我们首先阅读以下这个例子,这会方便后面大家...

    一、I2C协议

    I2C 也叫 IIC(Inter-Integrated Circuit)总线,是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式

    我们首先阅读以下这个例子,这会方便后面大家进一步理解I2C协议:

    如图所示,老师(MCU)将球(数据)传给众多学生中的一个(众多外设设备中的一个)。

    首先老师将球踢给某学生,即主机发送数据给从机,步骤如下:

    ① 老师:开始了(start);
    ② 老师:A!我要发球给你!(地址/方向);
    ③ 学生A:到!(回应);
    ④ 老师把球发出去(传输);
    ⑤ A收到球之后,应该告诉老师一声(回应);
    ⑥ 老师:结束(停止);

    接着老师让学生把球传给自己,即从机发送数据给主机,步骤如下:

    ① 老师:开始了(start);
    ② 老师:B!把球发给我!(地址/方向);
    ③ 学生B:到!
    ④ B把球发给老师(传输);
    ⑤ 老师收到球之后,给B说一声,表示收到球了(回应);
    ⑥ 老师:结束(停止)。

    从上面的例子可知,都是老师(主机)主导传球,按照规范的流程(通信协议),以保证传球的准确性,
    收发球的流程总结如下:
    ① 老师说开始了,表示开始信号(start);
    ② 老师提醒某个学生要发球,表示发送地址和方向(address/read/write);
    ③ 该学生回应老师(ack);
    ④ 老师发球/接球,表示数据的传输;
    ⑤ 收到球要回应:回应信号(ACK);
    ⑥ 老师说结束,表示IIC传输结束。

    以上就是I2C的传输协议,如果是使用IO口来模拟I2C协议,那么就得需要依次实现上述每个步骤。

    二、I2C物理层

    这里提个小问题,什么是物理层?

    我们可以以分层的思想来理解,例如对于通信协议,我们可以把它分为物理层协议层

    物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。

    协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。

    简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。

    I2C通信设备物理层如图所示:


    I2C通信设备物理层的特点如下:

    ① I2C 是一个支持设备的总线。总线指多个设备共用的信号线。在一个I2C 通讯总线中,可连接多个I2C 通讯设备,支持多个通讯主机及多个通讯从机。

    ② 一个I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

    ③ 每个连接到总线的设备都有一个独立地址,主机可以利用这个地址进行不同设备之间的访问。

    ④ 总线通过上拉电阻接到电源。当I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。

    ⑤ 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。

    ⑥ 具有三种传输模式:标准模式传输速率为100kbit/s ,快速模式为400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多I2C 设备尚不支持高速模式。

    ⑦ 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。

    三、I2C协议层

    I2C 的协议定义了通信的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

    1、写操作

    刚开始主机要发出一个start信号,然后发出一个设备地址(用来确定是往哪一个从机写数据),方向(读/写,0表示写,1表示读)。

    回应(用来确定这个设备是否存在),然后就可以传输数据,传输数据之后,要有一个回应信号(确定数据是否接受完成),然后再传输下一个数据。

    每传输一个数据,接受方都会有一个回应信号,数据发送完之后,主机就会发送一个P停止信号。

    • 白色背景:主→从
    • 灰色背景:从→主

    2、读操作

    刚开始主机要发出一个start信号,然后发出一个设备地址(用来确定是从哪一个芯片读取数据),方向(读/写,0表示写,1表示读)。

    回应(用来确定这个设备是否存在),然后就可以传输数据,传输数据之后,要有一个回应信号(确定数据是否接受完成),然后在传输下一个数据。

    每传输一个数据,接受方都会有一个回应信号,数据发送完之后,主机就会发送一个P停止结束信号。

    • 白色背景:主→从
    • 灰色背景:从→主

    3、起始信号与停止信号

    起始信号S停止信号P是两种特殊的状态。

    当 SCL 线是高电平时 SDA 线从高电平向低电平切换,这个情况表示通信的起始。

    当 SCL 是高电平时 SDA 线由低电平向高电平切换,表示通信的停止。

    起始和停止信号一般由主机产生。

    4、设备地址与数据方向

    I2C 总线上的每个设备都有自己的独立地址,主机发起通信时,通过SDA 信号线发送设备地址(SLAVE_ADDRESS)来查找从机。

    I2C 协议规定设备地址可以是 7 位或 10 位,实际中 7 位的地址应用比较广泛。

    紧跟设备地址的一个数据位用来表示数据传输方向,它是数据方向位(R/W),第 8 位或第 11 位。

    数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。


    注意:读数据方向时,主机会释放对SDA 信号线的控制,由从机控制SDA 信号线,主机接收信号;写数据方向时,SDA 由主机控制,从机接收信号

    5、数据有效性

    I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。

    SDA线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。

    换言之,SCL为高电平时表示有效数据,SDA为高电平表示“1”,低电平表示“0”;SCL为低电平时表示无效数据,此时SDA会进行电平切换,为下次数据表示做准备。

    6、应答信号

    I2C 的数据和地址传输都带响应。

    响应包括“应答(ACK)”和“非应答(NACK)”两种信号。

    I2C每次传输的8位数据,每次传输后需要从机反馈一个应答位,以确认从机是否正常接收了数据。

    当主机发送了8位数据后,会再产生一个时钟,此时主机放开SDA的控制,读取SDA电平,在上拉电阻的影响下,此时SDA默认为高,必须从机拉低,以确认收到数据。

    作为数据接收端时,当设备(无论主从机)接收到I2C 传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答(ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号,发送方接收到该信号后会产生一个停止信号,结束信号传输。

    7、传输时序图


    从图中可以看出:

    ① SDA和SCL开始都为高电平,然后主机将SDA拉低,表示开始信号.

    ② 在接下来的8个时间周期里,主机控制SDA的高低,发送从机地址。其中第8位如果为0,表示接下来是写操作,即主机传输数据给从机;如果为1,表示接下来是读操作,即从机传输数据给主机;另外,数据传输是从最高位到最低位,因此传输方式为MSB(Most Significant Bit)

    ③ 总线中对应从机地址的设备,发出应答信号。

    ④ 在接下来的8个时间周期里,如果是写操作,则主机控制SDA的高低;如果是读操作,则从机控制SDA的高低。

    ⑤ 每次传输完成,接收数据的设备,都发出应答信号。

    ⑥ 最后,在SCL为高电平时,主机由低拉高SDA,表示停止信号,整个传输结束。

    8、一些疑问

    问题一:如何在SDA上实现双向传输?

    答:主芯片通过一根SDA线既可以把数据发给从设备,也可以从SDA上读取数据,连接SDA线的引脚里面必然有两个引脚(发送引脚/接受引脚)。

    问题二:主设备(从设备)发送数据时,从设备(主设备)的发送引脚,不影响数据的发送,怎么做到呢?

    答:里面放一个三极管,使用开极(极电集开发出去作为输出)电路,如下图

    下面画一个真值表:

    从真值表和电路图我们可以知道,当某一个芯片不行影响SDA线时,那就不驱动这个三极管。

    • 想输出高电平时;都不驱动(高电平就由上拉电阻决定)。
    • 想输出低电平,就驱动三极管。

    从下面的例子可以看看数据是怎么传的(实现双向传输),比如主设备发送(8bit)给从设备:
    ① 前8个clk,由主设备决定数据:从设备不驱动三极管;主设备决定数据;
    ② 第9个clk,由从设备决定数据:主设备不驱动三极管;从设备决定数据;

    从上面的例子,就可以知道,怎样在一条线上实现,双向传输的办法。
    这就是为什么在SDA,SCL上放上拉电阻的原因。

    在第9个时钟之后,如果有某一方处于繁忙状态,它可以一直把SCL拉低当SCL为低电平时候,大家都不应该使用IIC总线,只有当SCL从低电平变为高电平的时候,IIC总线才能被使用。

    从前图我们也可以知道ACK信号应该是低电平。主设备不驱动三极管,如果从设备不驱动三极端的化SDA应该是高电平,当从设备接收数据之后,发出回应信号的时候,就会驱动三极管,让SDA变为低电平。所以说:ACK信号是低电平。

    对于IIC协议它只能规定怎么传输数据,数据什么含义它完全不能够控制,数据的含义有从设备决定。

    四、E2PROM存储器(AT24Cxx)

    E2PROM的全称是“电可擦除可编程只读存储器”,即Electrically Erasable Programmable Read-Only Memory。

    1、与Flash的异同

    ① E2PROM和Flash的本质上是一样的,Flash包括MCU内部的Flash和外部扩展的Flash。

    ② 从功能上,Flash通常存放运行代码,运行过程中不会修改,而E2PROM存放用户数据,可能会反复修改。

    ③ 从结构上,Flash按扇区操作,E2PROM通常按字节操作。

    2、结构原理

    E2PROM存储器市面上各个品牌众多,但在学习中最经典就是AT24Cxx系列:


    从命名上看,AT24Cxx中xx的单位是K Bit,如AT24C08,其存储容量为8K Bit。对于AT24C02,其存储容量为2K Bit,2*1024=2048Bit。

    对于AT24C01/02,每页大小为8 Byte,对于AT24C04/08/16,每页大小为16 Byte。如图所示,AT24C02由32页(Page)组成,每一页由8个字节(Byte)组成,每个Byte由8位(Bit)组成,Bit为最小存储单位,存放1个0或1。

    3、设备地址

    I2C设备都会有一个设备地址,不同容量的AT24Cxx,设备地址定义会有所差异:

    例如AT24C02的容量为2K,对应上图中的第一行,高四位固定为“1010”,中间三位由A2、A1、A0引脚的电平决定,比如A2~A0引脚全接地,则值为“000”,最后的最低位为读写位,0代表写命令,1代表读命令。

    A2、A1、A0引脚电平需要由原理图决定,假设全接电源地,则如果需要向AT24C02写数据,则发送地址“1010 0000”,如果需要向AT24C02读数据,则发送地址“1010 0001”。

    假设开发板有多个AT24C02挂在同一I2C总线上,通过这个规则,只需设计电路时,让A2、A1、A0引脚电平不同,即可区分两个AT24C02。

    对于容量再大一点的AT24Cxx系列,比如AT24C04,器件地址由A2、A1引脚决定,数据空间有P0决定。比如对AT24C04的0-2K空间操作,则P0为0,对2K-4K空间操作,则P0为1。

    4、写操作

    AT24Cxx支持字节写模式页写模式

    字节写模式是一个地址一个数据的写;页写模式是连续写数据,一个地址多个数据的写,但是页写模式不能自动跨页,如果超出一页长度,超出的数据会覆盖原先写入的数据。

    如图所示,为AT24Cxx字节写模式的时序,在MCU发出开始信号(Start)后,发出8 Bit的设备地址信息(图中读写位为低电平,即写数据),待收到AT24Cxx应答信号后,再发出要写的数据地址,再次等待AT24Cxx应答,最后发出8 Bit数据写数据,待AT24Cxx应答后,发出停止信号(Stop),完成一次单字节写数据。

    AT24C02容量为2K,因此数据地址范围为0x00-0xFF,即0-255,每个数据地址每次写1Byte,即8bit,也就刚好2568=2048Bit。对于1K容量的产品,数据地址范围为0x00-0x7F,最高位不会用到,因此图中数据地址的最高位为*,意思是对于1K容量的产品,该位无需关心。

    上图为AT24Cxx的页写模式时序,与字节写模式的差异在于,不是只发送1Byte数据,而是任意多个。需要注意,该模式不能跨页写,遇到跨页时,需要重新发送完整的时序。

    值得一提的是,AT24Cxx每次写完之后,再到下次写之前,需要间隔5ms时间,以确保上次写操作在芯片内部完成,如图所示。

    5、读操作

    AT24Cxx支持当前地址读模式随机地址读模式顺序读模式

    当前地址读模式就是在上一次读/写操作之后的最后位置,继续读出数据,比如上次读/写在地址n,接下来可以直接从n+1处读出数据;随机地址读模式是指定数据地址,然后读出数据;顺序读模式是连续读出多个数据。

    在当前地址读模式下,无需发送数据地址,数据地址为上一次读/写操作之后的位置,时序如图所示,注意在结尾,主机接收数据后,无需产生应答信号。

    在随机地址读模式下,需要先发送设备地址,待读的数据地址,接着再重新发出开始信号,设备地址,读出数据,时序如图所示。

    在顺序读模式下,需要先从当前地址读模式或随机地址读模式启动,随后便可连续读多个数据,时序如图所示。

    展开全文
  • I2C通信全面解析

    万次阅读 多人点赞 2020-02-19 18:03:25
    1. 物理接口: SCL + SDA (1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主...(1)I2C属于串行通信,所有的数据以位为单位在SDA线上串行传输。 (2)同步通信就是通信双方工作在同一个时钟下,一般...
  • 本文重点还是想教你真正的理解了I2C通信的原理与编程,I2C通信一要掌握原理,二要自己真正的去编程实践,如果你看完本篇文章,你能自己编写一个软件模拟I2C驱动程序,你就真正的掌握了I2C通信原理。 2、I2C通...
  • STM32——I2C通信配置I2C的系统框架1、通讯引脚2、时钟控制逻辑3、数据控制逻辑4、整体控制逻辑I2C代码配置 既上一篇文章对I2C的理论分析、讲解。基本原理已经大致了解了。本文就以I2C在stm32上的系统框架图的分析、...
  • I2C通信详解介绍(初学,浅显易懂,基本知识)

    万次阅读 多人点赞 2021-10-07 13:45:03
    介绍:I2C通讯协议(Inter-Integrated Circuit)引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。 特点: 1.只需要一根数据线...
  • i2c时序图的详细讲解

    万次阅读 多人点赞 2018-04-25 21:25:22
    i2c简易时序图 启动信号: SCL为高电平的时候,SDA由高电平向低电平跳变。结束信号:SCL为高电平的时候,SDA由低电平向高电平跳变。 应答信号: I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节...
  • 讲解I2C总线通信原理通俗易懂,PPT展示非常详细
  • 什么是I2C通信

    千次阅读 2020-10-10 10:55:48
    ARM体系-I2C通信 一、什么是I2C 1、I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的设备之间传送信息。 2、主设备用于启动总线传送数据,并产生时钟以开放传送...
  • I2C读写串口与pc显示

    2018-09-19 20:06:17
    介绍I2C的工作原理,详细讲解I2C读写串口的原理并在pc上显示
  • STM32的I2C通信

    万次阅读 多人点赞 2017-08-07 12:49:35
    STM32的两个GPIO引脚,分别用于SCL和SDA,按照I2C规约的时序,像控制LED灯那样控制引脚输出,若是接收数据时则读取SDA线上的电平,那就可以实现I2C通信了,这也是我们在51单片机上的“软件模拟协议”做法。...
  • 网上有许多讲解单片机实现I2C主模式,但是从模式的很少。我现在就来讲讲PIC单片机使用MSSP模块实现I2C从模式。
  • 首先简单介绍I2C通信的基本特征,然后详细讲解I2C通信的时序图,并且通过I2C的时序图讲解了通信物理层的时序概念。之后介绍了S5PV210的I2C控制器、gsensor芯片的I2C通信流程图,后分析了相关的代码。本课程的目标...
  • I2C通信实现点亮一盏小灯实验报告,其中详细讲解了各个函数以及时序等等
  • I2C通信详解

    千次阅读 2018-10-04 15:28:31
    什么事I2C通信 物理接口:SCL+SDA SCL(serial clock ):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道。 SDA(serial data):数据线,通信数据都通过SDA线传输 通信特征:串行、同步、...
  • STM32的I2C通信实例

    2015-07-21 15:15:25
    STM32的I2C通信实例。支持8位数据读写、16位数据读写、32位数据读写。
  • I2C通信协议及STM32代码解释

    千次阅读 2020-10-07 22:45:29
    I2C通信协议及其在MPU6050中的应用 一:简介 IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和...
  • STM32学习笔记—I2C通信

    千次阅读 2021-12-06 16:30:39
    STM32的i2c学习笔记
  • 详细介绍GPIO、I2C、SPI通讯原理以及物理层原理

    千次阅读 多人点赞 2021-08-26 10:03:20
    针对GPIO、I2C、SPI的讲解,对这些通讯方式有个大致框架,对日后的开发会有帮助,了解因为所以然。 一. GPIO 1. 什么是GPIO? GPIO全拼叫General Purpose Input Output(通用输入输出)简称IO口也叫总线扩展器,...
  • I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线,主要用于近距离、低速的芯片之间的通信I2C总线有两根双向的信号线,一根数据线SDA用于收发数据,一根时钟线SCL用于通信双方时钟的同步;I2C总线...
  • GPIO模拟I2C通信协议(二)

    千次阅读 2018-11-08 14:48:58
    本博客是GPIO模拟I2C通信协议系列的第2篇,承接上一篇的内容,总结单片机通过用GPIO模拟的I2C和从设备E2PROM进行数据交换功能的实现。主要内容包括E2PROM简介、AT24C28的读写逻辑、实现代码和效果展示。其中AT24C28...
  • I2C通信时序图解析

    千次阅读 2019-05-18 11:55:13
    二、I2C协议标准代码 2.1 起始信号&停止信号   起始信号:当 SCL 线是高电平时 SDA 线从高电平向低电平切换。   停止信号:当 SCL 线是高电平时 SDA 线由低电平向高电平切换。 2.1.1 起始信号代码 1...
  • STM32——I2C通信理论硬件层协议层 前言:我们在学习stm32的时候,要想学得更好。i2c协议的学习是必不可少的。现在很多的硬件、传感器等都是用到i2c协议与MCU(stm32)进行通信的。因此i2c还是必不可少的一个重要知识...
  • 前后向通信构成双向的控制通道,从而有了本文中将要讨论的FPDLINK中I2C的巧妙设计问题。 FPDLINK在使用中都是一个serializer和deserializer配对使用,CPU可以连接到serializer,也可以连接到deserializer,取决于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,198
精华内容 55,279
关键字:

i2c通信的详细讲解