当前位置: 首页 > news >正文

I2C控制器

目录

 I2C协议

起始信号

终止信号

应答信号

数据传输

单字节写时序

单字节读时序

I2C控制器

功能模式

引脚复用

 时钟源

 仲裁逻辑

仲裁方案

阶段一:  时钟同步(Clock Synchronization)

阶段二:数据仲裁(Data Arbitration)

中断

初始化顺序

生成起始信号

数据传输过程

生成终止信号

生成重启信号

I2C Memory Map

I2C寄存器

I2Cx_IADR寄存器

I2Cx_IFDR寄存器

I2Cx_I2CR寄存器

I2Cx_I2SR寄存器

I2Cx_I2DR寄存器


前言:

本文基于I.MX 6ULL处理器介绍I2C控制器,I2C控制器关键特征如下:

  • 与 I2C 总线标准兼容;
  • 多主机操作(支持多设备同时作为主机竞争总线);
  • 可通过软件编程选择 64 种不同的串行时钟频率之一(灵活适配不同通信速率需求);
  • 软件可配置的应答位(ACK/NACK 可按需设置);
  • 中断驱动的逐字节数据传输(每传输 1 字节触发一次中断,便于软件处理)
  • 仲裁丢失中断(多主机竞争总线失败时触发),并自动从主机模式切换为从机模式;
  • 寻址识别中断(从机被寻址时触发);
  • 启动(Start)和停止(Stop)信号的生成 / 检测;
  • 重复启动(Repeated Start)信号的生成;
  • 应答位(ACK)的生成 / 检测;
  • 总线繁忙检测(判断 I2C 总线是否被占用);

 I2C协议

I2C总线具有两根通信线,其中数据线SDA(Serial Data) 用于收发数据,时钟线SCL (Serial Clock) 用于通信双方时钟同步;

I2C总线为多主机总线,挂载于I2C总线的器件分为主机与从机,主机有权发起和结束一次通信,从机只能被主机呼叫;

    结论:

    1. 总线空闲时,SCL 与 SDA 皆为高电平;

    2. 挂载于I2C总线的设备具有唯一的地址;

    3. 任何时刻只能存在一个主机;
    4. 起始信号只能由主机产生;

    5. 终止信号只能由主机产生;

    线与逻辑

    • 总线电平为高电平,当且仅当所有设备都释放总线(输出高阻态,由上拉电阻拉至高电平);
    • 只要有一个设备拉低总线(输出低电平),总线电平为低电平;

    起始信号

    起始信号:SCL高电平期间,SDA从高电平切换到低电平;

    终止信号

    终止信号:SCL高电平期间,SDA从低电平切换到高电平;

    应答信号

    应答信号(ACK) : 在单字节数据传输后的第9个时钟周期内,SCL保持低电平期间,SDA线被接收设备主动拉低;

    数据传输

    • 当时钟线SCL低电平期间,允许数据线SDA上的信号发生变化,此时发送方可向数据线SDA写入一位数据;
    • 当时钟线SCL高电平期间,不允许数据线SDA上的信号发生变化,此时接收方从数据线SDA读取一位数据;

    单字节写时序



    1.  主机发送起始信号标志通信开始;

    2.  主机发送 I2C 设备地址,由于 I2C 器件具有唯一的设备地址,通过发送具体的设备地址来决定访问具体的I2C设备,主机发送 I2C 设备地址, 8 位数据中高 7 位是设备地址,最后 1 位是读写位,1 表示读操作,0 表示写操作;

    示例:假设从机地址为0x1E,二进制为 0001 1110,写操作最低位为0,则写操作的地址字节为:(0x1E << 1) | 0 = 0x3C,二进制为 0011 1100

    3.   WRITE代表读写位, 0 表示写操作,1 表示读操作;

    4.   从机发送应答信号ACK;

    5.   发送重复启动信号,若直接发送寄存器地址,导致从机无法区分寄存器地址 与 新的从机地址,从机的逻辑是只要总线被占用,主机可能随时发送新的从机地址来切换目标设备;

    例如:

    • 主机可能先和从机 A 通信(发 A 的地址),然后不释放总线,直接发从机 B 的地址(切换到 B);

    重复起始信号(Repeated Start) 的核心作用是 在不释放总线的前提下,切换到当前从机的下一个通信阶段,保证写操作的连续性与原子性;

    6.   发送待写入数据的寄存器地址,从机如何区分寄存器地址与数据,从机内部通过状态切换,结合已完成的通信阶段来解析字节意义,关键分为两步:

    一 从机地址(写) 被确认后,下一字节为寄存器地址

    • 主机先发送从机地址 + 写位(R/W=0):表示 主机要向该从机写入数据;
    • 从机若地址匹配,会返回ACK 应答,此时,从机内部状态机切换为 等待接收寄存器地址;
    • 因此,从机明确:在从机地址 ACK之后,主机发送的第一个字节必然是寄存器地址( I2C 写操作的协议约定);

    二 寄存器地址 被确认后,下一字节为待写入的数据

    • 主机发送寄存器地址,从机解析后返回ACK 应答,此时,从机内部状态机切换为 等待接收写入数据;
    • 因此,从机明确:在 寄存器地址 ACK之后,主机发送的下一个字节必然是要写入该寄存器的数据(I2C 写操作的协议约定);

    7.   从机发送的 ACK 应答信号;

    8.   发送要写入寄存器的数据;

    9.   从机发送应答信号ACK ;

    10.  主机发送停止信号;

    单字节读时序



    1. 主机发送起始信号;
    2. 主机发送要读取的 I2C 从设备地址。
    3. 读写控制位,因为向 I2C 从设备发送待读取的寄存器地址,所以该位为写信号;
    4. 从机发送的 ACK 应答信号;
    5. 重新发送 START 信号;
    6. 主机发送要读取的寄存器地址;
    7. 从机发送的 ACK 应答信号;
    8. 重新发送 START 信号;
    9. 重新发送要读取的 I2C 从设备地址;
    10. 读写控制位,因为下阶段为从 I2C 从设备寄存器中读取数据,所以该位为读信号;
    11. 从机发送的 ACK 应答信号;
    12. 从 I2C 从设备寄存器中读取的数据;
    13. 主机发出NACK信号,表示读取完成,从机不再发送数据;
    14. 主机发出 STOP 信号,停止 I2C 通信;

    若主机想读取从机某个特定寄存器的数据,必须先让从机知道 要读哪个寄存器, 但读操作的通信方向是 从机→主机,主机无法在 读请求 中直接传递寄存器地址,因此 I2C协议设计了先写后读 的流程:

    • 主机先发送 从机地址 + 写位(R/W=0):这一步骤为 伪写操作,目的是向从机传递要读取的寄存器地址;
    • 从机应答(ACK)后,主机发送目标寄存器地址,从机再次应答(ACK),此时从机已记录 主机要读 此寄存器;
    • 主机发送重复起始信号(Sr)(不释放总线,保持通信连续性);
    • 主机再次发送 从机地址 + 读位(R/W=1):这一步骤为实际的读请求,告诉从机现在要读取从机刚才记录的寄存器地址对应的数据;
    • 从机应答(ACK)后,开始通过 SDA 线输出目标寄存器的数据,主机接收数据;

    I2C控制器

    功能模式

    • 标准模式(Standard mode):最高速率 100 kbit/s,兼容性极佳(几乎所有 I2C 设备都支持),但速度较慢,适用于对吞吐量要求不高的场景;
    • 快速模式(Fast mode):最高速率 400 kbit/s,适用于对速度敏感的场景(如高速传感器、短距离高吞吐量通信),但需注意:快速模式对SDA/SCL 引脚的驱动能力要求更高,且必须确保从机设备支持快速模式,否则可能通信失败;

    引脚复用

     UART4_TX_DATA引脚可以复用为I2C1_SCL,UART4_RX_DATA引脚可以复用为I2C1_SDA引脚,配置引脚复用寄存器如下:

    IOMUXC_SW_MUX_CTL_PAD_UART4_TX_DATA寄存器

     IOMUXC_SW_MUX_CTL_PAD_UART4_RX_DATA寄存器

     时钟源

     

    假定CSCMR寄存器PERCLK_PODF位配置为1分频,则IPG_CLK_ROOT=PERCLK_CLK_ROOT=66MHz

     

    • Peripheral clock:用于外设总线寄存器的读写,当 CPU 要访问 I2C 外设的寄存器时,需要此时钟来同步操作,确保寄存器读写的正确性;

    • Module clock:I2C 的功能时钟。I2C 的SCL 的频率诞生于模块时钟,模块时钟和外设时钟是同步的,对于快速模式(400kbps),模块时钟的最小频率应该是 12.8MHz,这样才能实现 400kbit/s 的操作;

     仲裁逻辑

    I2C 总线为共享资源,若多个主设备同时驱动总线,会导致数据传输出错,但是I2C 总线支持多个设备可作为主机发起通信,当多个主设备同时尝试控制总线时,仲裁(Arbitration) 是解决冲突的机制:通过硬件逻辑决定 哪个主设备继续控制总线,哪个主设备放弃控制总线;

    仲裁方案

    I2C 仲裁分为时钟同步数据仲裁两个阶段,共同确保总线控制权的公平分配;

    阶段一:  时钟同步(Clock Synchronization)

    当多个主设备同时请求总线时,总线的 SCL 时钟由所有竞争设备的时钟协商生成:

    • 低电平时段:取所有设备中最长的低电平时段(因为 I2C 是开漏 / 开集电极输出,只要有一个设备拉低 SCL,总线就保持低电平。因此,低电平持续时间由 “最慢” 的设备决定)。
    • 高电平时段:取所有设备中最短的高电平时段(当所有设备释放 SCL,上拉电阻将总线拉至高。此时 “最快” 完成高电平计数的设备会先拉低 SCL,因此高电平持续时间由 “最快” 的设备决定)。

    时钟同步的本质是:让所有主设备的 SCL 时序 “对齐”,为后续数据传输提供统一的时钟基准。

    阶段二:数据仲裁(Data Arbitration)

    时钟同步后,主设备开始通过 SDA 传输数据,数据仲裁是逐位进行,核心逻辑是线与逻辑(开漏输出+ 上拉电阻)

    • 每个主设备在发送每一位时,会同时检测 SDA 的实际电平是否与自己发送的电平一致。
    • 若主设备 A 发送高电平,但检测到 SDA 实际是低电平(说明有其他主设备 B 发送了低电平),则主设备 A 失去仲裁权
    • 失去仲裁的设备会:
      • 立即切换为从机接收模式(停止主动驱动 SDA,改为被动接收);
      • 硬件设置状态寄存器的仲裁丢失标志,供软件查询;
      • 不生成停止条件(避免干扰总线,让胜利的主设备继续通信);

    中断

    I2C模块仅产生一个中断,可通过设置 I2C_I2CR 寄存器的 [IIEN] 位(中断使能位)来使能该中断,在以下任意一种情况下会触发中断:

    • 一个字节传输完成(中断在第 9 个时钟的下降沿被置位);
    • 在从机接收模式下,接收到与自身特定地址匹配的地址;
    • 失去仲裁权(Arbitration is lost);

    初始化顺序

    1. 设置数据采样率(配置 I2C_IFDR 寄存器的 [IC] 位),以从系统总线时钟生成 SCL 频率;
    2. 更新 I2C_IADR 寄存器中的地址,定义其从机地址(地址范围为 0 到 0x7F);
    3. 设置 I2C_I2CR 寄存器的 [IEN] 位(I2C 使能位),以启用 I2C 总线接口系统;
    4. 修改 I2C_I2CR 寄存器的位,选择主 / 从模式、发送 / 接收模式,以及是否使能中断;

    生成起始信号

    I2C 支持多主机共享总线,因此发送起始信号前必须检测总线状态:

    • I2C_I2SR[IBB](总线忙标志):IBB=1表示总线正被占用(其他主机在通信),IBB=0表示总线空闲;
    • 只有IBB=0时,当前主机才能发起始信号(Start), 否则强行发送会引发总线冲突,导致仲裁失败;
    • 终止信号(stop) 与下一个起始信号 (Start) 之间的空闲时间(Bus Free Time)由硬件自动生成,无需软件额外延时;
    • 发送设备地址时,主机将发送的数据(从机地址 + 读写位)需先写入I2C_I2DR寄存器;

    起始信号由硬件自动产生,触发条件是:

    1. 软件配置 I2C 为主机模式(通过 I2C_I2CR 的 MSTA 位置位);
    2. 总线空闲(IBB = 0);
    3. 软件向 I2C_I2DR 写入第一个字节(从机地址 + 读写位);

    数据传输过程

    传输完成的双重标志(ICF + IIF

    • ICF(数据传输位):单字节传输完成时硬件自动置位,表明一个字节的收发已完成,需通过读 / 写 I2C_I2DR 清除(接收时读、发送时写);
    • IIF(中断状态位):单字节传输完成时硬件自动置位,若 IIEN 使能则触发中断,需软件显式清除(写 0 到 I2C_I2SR[IIF]),否则中断会持续触发;

    主机发送模式→主机接收模式

    当主机读取从机的寄存器中的数据时,若从机已经获得主机要读取的寄存器地址,流程如下:

    1. 先发送读地址:主机需先发送 从机地址 + 读位(LSB=1),告诉从机读取数据—— 这一步必须工作在发送模式(MTX=1);
    2. 再接收从机数据:从机应答地址后,会开始向主机发送数据 —— 这一步主机必须切换到接收模式(MTX=0),接收模式仅通过输入电路采样 SDA 上的电平;

    当主机从发送模式切换到接收模式(MTX=0)后,硬件状态机处于 等待接收启动 的初始状态;此时:

    • 若不执行 "虚拟读取",硬件不会启动 "采样 SDA→锁存数据"的流程,从机发送的数据会被忽略。
    • 执行 "虚拟读取" 后,硬件会认为 "软件已准备好接收数据",从而激活采样逻辑,开始接收从机发送的第一个字节;

    当主机发送完从机地址 + 读位,主机需切换为接收模式并且进行虚拟读取,方案如下:

    • 清除 I2C_I2CR[MTX](改为接收模式);
    • 读取 I2C_I2DR(虚拟读取,触发接收数据);

    生成终止信号

    主机接收模式终止信号生成方案:

    假设主机需接收 3 个字节后终止传输,流程如下:

    1. 主机发送起始信号→发送从机地址 + 读位→从机 ACK→进入接收模式;
    2. 接收第 1 个字节→设置I2C_I2CR[TXAK] = 0发送ACK)→从机继续发送第 2 个字节;
    3. 接收第 2 个字节→设置 I2C_I2CR[TXAK] = 1(发送 NACK)→从机发送第 3 个字节;
    4. 接收第 3 个字节→硬件自动生成停止信号→从机检测到 NACK + 停止信号,终止发送;

    注意: 主机接收第 N-1 字节时,需提前配置 TXAK=1(NACK),让从机在发送第 N 字节后收到 NACK,从而停止发送;

    主机发送模式终止信号生成方案:

    假设主机发送一个字节后终止传输,流程如下:

    • 从机接收寄存器地址后,返回 ACK;
    • 硬件置位 ICF(地址传输完成),软件检测到 ICF=1 后,向 I2C_I2DR 写入单字节数据 0xAB(硬件自动清除 ICF);
    • 硬件逐位发送数据,从机接收后返回 ACK;
    • 硬件再次置位 ICF(数据传输完成);
    • 硬件检测到 ICF=1 (表示当前字节已发送完成且从机发送ACK)且 I2C_I2DR 寄存器在 ICF=1 后的一个 SCL 周期内未被软件写入新数据,硬件判定当前字节是最后一个字节;
    • 硬件自动生成停止信号(P);

    生成重启信号

    向I2C 控制寄存I2C_CR的 RSTA 位写 1,触发硬件自动生成重启信号;

    在设置 I2C_I2CR[RSTA] 位之后,且在写入 I2C_I2DR 寄存器之前,至少有两个模块时钟周期的延迟,该模块时钟的最大可能时钟周期为 78 ns;

    I2C Memory Map

    I2C寄存器

    I2Cx_IADR寄存器

    bit[7:1]: 存储I2C设备作为从机时的的响应地址,当总线上的主机发送地址时,从机将总线地址与 ADR 字段比较,若匹配则触发从机模式;

    I2Cx_IFDR寄存器

    I2C_IFDR(I2C Frequency Divider Register)是 I2C 时钟分频寄存器,通过配置其 IC 字段选择分频系数,将 PERCLK_ROOT(外设根时钟)分频为 I2C 模块的工作时钟,最终决定 SCL 频率;

    假设IPG_CLK_ROOT=PERCLK_ROOT=66MHz,选择通信速度为标准模式(100kbit/s),IC字段配置方案如下:

    1. 计算分频系数: 分频系数 = PERCLK_ROOT / SCL 频率 =66MHz/100kHz=660;

    2. 匹配分频系数与 IC 字段: 查阅 I2C_IFDR 分频表,找到最接近 660 的分频系数,表中 IC=0x15 对应分频系数 640(最接近 660);

    3. 验证实际 SCL 频率: 实际 SCL = 66MHz/640=103.125kHz,与 100kHz 的误差在 I2C 标准模式容差(±5%)范围内,可正常通信;

    I2Cx_I2CR寄存器

    bit7:IEN位,I2C 模块使能位 ,若配置为1表示使能 I2C 模块,同时控制模块的软件复位(写 0 会触发内部复位);若配置为0表示禁用 I2C 模块;

    bit6:IIEN(I2C Interrupt Enable),中断使能位,若配置为 1表示使能 I2C 中断,当状态寄存器 I2C_I2SR[IIF](中断标志)置 1 时,触发中断;若配置为 0表示禁用中断,但 I2C_I2SR[IIF] 仍会正常置 1(仅不触发中断);

    bit5:MSTA(Master/Slave Mode Select),主从模式选择位

    • 1:切换为主模式(Master Mode);
    • 置 0:切换为从模式(Slave Mode);

    bit4:  MTX(Transmit/Receive Mode Select),收发模式选择位,决定主机 / 从机模式下的传输方向;

    • 主机模式
      • 置 1:发送模式(Transmit,主机向从机写数据);
      • 置 0:接收模式(Receive,主机从从机读数据);
    • 从机模式
      • SRW=1(主机读从机):从机需发送数据,MTX=1(发送模式);
      • SRW=0(主机写从机):从机需接收数据,MTX=0(接收模式);

    bit3:TXAK(Transmit Acknowledge Enable),应答使能位,用于控制 I2C 总线在第 9 个时钟周期的 SDA 电平:

    • 置 0:发送应答(ACK)(SDA 拉低);
    • 置 1:发送非应答(NACK)(SDA 保持高);

    bit2: RSTA(Repeat Start),用于生成重复起始信号:

    • 置 1:生成重复起始信号(Repeated Start);
    • 置 0:无操作;

    I2Cx_I2SR寄存器

     bit7:ICF(Data Transferring Bit) ,数据传输完成标志

    • 功能:指示一个字节的传输状态
      • 0:传输进行中(字节未发送 / 接收完成);
      • 1:传输完成(最后一个字节的第 9 个时钟下降沿时置 1);

    bit6:IAAS(I2C Addressed as Slave Bit),从机寻址标志

    • 功能:指示 I2C 是否被寻址为从机
      • 0:未被寻址(总线无匹配自身地址的传输);
      • 1:被寻址为从机(自身地址 I2C_IADR 与主机发送的地址匹配);

     bit5:IBB(I2C Bus Busy Bit),总线忙闲标志

    • 功能:指示 I2C 总线的全局状态
      • 0:总线空闲(检测到 Stop 信号时清除);
      • 1:总线忙(检测到 Start 信号时置 1);

     bit4:IAL(Arbitration Lost),仲裁丢失标志

    • 功能:指示 I2C 总线仲裁竞争失败
      • 0:未丢失仲裁(总线控制权正常)。
      • 1:仲裁丢失(多主机竞争总线失败,需软件写 0 清除)

    bit2:SRW(Slave Read/Write), 从机读 / 写方向标志

    • 功能:仅当 IAAS=1(被寻址为从机)时有效,表示主机发送的地址中 R/W 位
      • 0:从机接收(主机写从机)。
      • 1:从机发送(主机读从机)

    bit1:IIF(I2C Interrupt),中断标志

    • 功能:指示 I2C 中断请求状态:
      • 0:无挂起中断;
      • 1:中断挂起(需软件写 0 清除);

    bit0:RXAK(Received Acknowledge), 接收应答标志

    • 功能:反馈总线应答阶段的结果:
      • 0:收到 ACK ;
      • 1:收到 NACK;

    I2Cx_I2DR寄存器

    http://www.dtcms.com/a/294000.html

    相关文章:

  • 传统RNN模型笔记:输入数据长度变化的结构解析
  • 通用图片 OCR 到 Word API 数据接口
  • 数据结构自学Day13 -- 快速排序--“前后指针法”
  • 显微科研中的关键选择:不同显微镜相机技术特性与应用适配性全面解析
  • SpringCloudGateWay 使用nacos网关自动负载均衡
  • nrm指南
  • Sklearn 机器学习 线性回归
  • 解决sparksql创建出来的数据库路径错误的问题
  • Docker Desktop 打包Unity WebGL 程序,在Docker 中运行Unity WebGL 程序
  • Unity国际版下载链接分享(非c1国内版)
  • Java面试题035:一文深入了解Docker
  • SQL基础⑧ | 表格篇
  • Android插件化实现方案深度分析
  • 智能小e-外联系统文档
  • CentOS 7 Linux 用 yum 安装 Docker,含 Docker 镜像无法拉取问题(即 docker pull 失败)的解决方案
  • 基于LNMP分布式个人云存储
  • 深入理解 Java Builder 设计模式:解决构造函数爆炸问题
  • 旧系统UI焕新陷阱:保留业务习惯与引入新交互的平衡点把控
  • JNPF组织权限,让企业权限体系更清晰高效​
  • TARA分析学习
  • 亚远景-传统功能安全VS AI安全:ISO 8800填补的标准空白与实施难点
  • Django 入门详解:从零开始构建你的第一个 Web 应用
  • YOLOv5模型剪枝实战教程
  • 从8h到40min的极致并行优化:Spark小数据集UDTF处理的深度实践与原理剖析
  • 分布式系统中的缓存设计与应用
  • 前端实现可编辑脑图的方案
  • 一洽客服系统:小程序接入功能说明
  • 关于单片机的无符号整型uint32_x
  • 代码随想录算法训练营第五十二天|图论part3
  • 使用 gh-pages 将 next.js15 静态项目部署到 github pages