欢迎光临
我们一直在努力

单片机/C/C++八股:(二十七)IIC 专题(I²C)---- 下集

上一篇下一篇
IIC 专题(I²C)—- 上集

目 录

    • 5)IIC 为什么要加上拉电阻
    • 6)IIC 器件为什么要设计为开漏输出(同上)
    • 7)IIC 如何实现多主机通信(仲裁)
      • 7.1)说明
      • 7.2)示例
    • 8)IIC 的时钟同步和时钟拉伸是什么
      • 8.1)时钟同步
      • 8.2)时钟拉伸
    • 9)IIC 通信中其他常见的问题及解决方案

5)IIC 为什么要加上拉电阻

参考视频:为什么为什么!IIC总线为什么加上拉电阻_哔哩哔哩_bilibili

本质上是为了配合IIC器件的开漏输出,来实现“线与”逻辑。具体如下:

  • 目标:实现“线与”逻辑
    • I²C 总线允许多个设备共享同一线路,为了避免两个设备同时一个输出高、一个输出低造成短路冲突,需要一种机制让所有设备只能“拉低”、不能“强制拉高”。这就是 线与 —— 任一设备输出低则总线为低,所有设备释放后总线才为高。
  • 手段:将引脚设计为开漏输出
    • 为了达到上述目标,I²C 器件的 SCL 和 SDA 引脚内部仅保留下拉驱动(开漏),移除主动上拉驱动(不使用推挽输出),确保设备之间不会因为输出相反电平而直接形成电源到地的电流通路。这样,无论多少个设备同时驱动,都不会发生硬件损坏。
  • 配套:外接上拉电阻来产生高电平
    • 由于开漏引脚只能主动输出低电平,无法主动输出高电平,因此必须通过外接上拉电阻连接到正电源。当所有设备都释放总线时,上拉电阻将总线拉到高电平;当任一设备开启下拉管时,总线被拉低。这样既保证了“线与”逻辑的正常工作,又为总线定义了明确的高电平状态。
  • 此外,开漏 + 上拉的组合还顺带解决了:

    • 多主机仲裁(后续会介绍):主机可以一边发送一边检测总线状态,发现总线被其他设备拉低时就自动退出,安全可靠。
    • 时钟拉伸(后续会介绍):从机可以直接把 SCL 拉低来强制主机等待。

    上拉电阻阻值选择:

    • 电阻过大 → 上升沿过慢,可能超出规格(如快速模式上升时间要求),导致数据误码。
    • 电阻过小 → 功耗增加,且设备下拉可能无法拉出有效低电平。
    • 常见阻值:
      • 最大范围:1 kΩ ~ 10 kΩ(实际常用 2.2 kΩ、4.7 kΩ)。
      • 低速应用:4.7kΩ-10kΩ
      • 标准速度:4.7kΩ
      • 快速模式:2.2kΩ-4.7kΩ
      • 高速模式:1kΩ-2.2kΩ

    ———————— 总结 ————————

    I²C 是一种多主机、多从机共享总线的通信协议,为了实现“线与”逻辑(保证任何设备都能安全地驱动总线而不会发生硬件冲突或短路:若两个设备分属主从,且为推挽输出,若恰好在同一时刻一个输出高、一个输出低,电源到地之间会形成 短路路径,引发大电流,烧毁器件。),所以 IIC 器件的引脚都设计成了开漏输出(只能输出低电平),所以才需要 IIC 总线加一个上拉电阻来输出高电平。


    6)IIC 器件为什么要设计为开漏输出(同上)

    上述最后的黄色总结字体


    7)IIC 如何实现多主机通信(仲裁)

    7.1)说明

    多主机仲裁有两种情况:

  • 情况一:在 SDA 空闲的情况下,哪个主机先将 SDA 拉低,谁就获得优先权
  • 情况二:在 SDA 空闲的情况下,多个主机同时将 SDA 拉低,分辨不出谁先拉低的,此时会根据时钟同步逐位对比 SDA 上的电平:
    • 首先所有主机会被动统一到同一个时钟节奏,也就是俗称的时钟同步,确保大家在同一个时钟沿上公平比较:
      • 这些主机在同时拉低 SDA 后,会立刻拉低 SCL(时钟信号的第一个下降沿),此时 SCL 处于低电平;由于 SCL 也是线与连接的,实际时钟由最慢的时钟源决定低电平持续时间(时钟频率越低,这个低电平就会持续越久,就会越晚释放 SCL);当大家都释放后,SCL 变高;接着时钟频率最快的主机先拉低 SCL,开始下一个周期。
      • 结果:所有主机的时钟被统一到同一个节奏,这是公平仲裁的基础,只不过这个时钟信号每个周期的高电平和低电平的持续时间不一定一致(大家自己拿一快一慢的主机举个例子画个图就知道了)。
    • 然后仲裁在 SDA 线上进行

      \\longrightarrow

      这些主机会在经过时钟同步后的 SCL 高电平期间发送自己的通讯地址并监视 SDA 线的电平,地址位上第一个出现“发 1 但看到 0”的主机退出,最后一个坚持发送并且地址没有被其他主机拉低的主机获胜。说白了就是:谁的地址二进制值更“低”(0 占比更多),谁就能坚持到最后(因为 0 会覆盖 1)。

  • 补充一句,这个仲裁和 CAN 总线的有些类似。

    7.2)示例

    假设三个主机 A、B、C 都检测到总线空闲,同时发起通信:

    第一步:产生 START 条件(同时拉低 SDA)

    • 三个主机都在 SCL 为高时,把 SDA 从高拉低。
    • 由于线与特性,SDA 立即变成低电平。
    • 所有主机都看到 SDA 变低,但无法区分是谁拉低的,因为开漏输出并联在一起。
    • 此时,A、B、C 都认为自己成功产生了 START 条件,都准备发送地址。

    第二步:时钟同步(SCL 线)

    • 每个主机都开始驱动 SCL 线,产生自己的时钟节奏。
    • 但由于 SCL 也是线与连接的,实际时钟由最慢的时钟源决定低电平持续时间:
      • 谁最后释放 SCL,谁决定低电平宽度(最慢的人拖着大家)
      • 当大家都释放后,SCL 变高;最快的人先拉低 SCL,开始下一个周期。
    • 结果:所有主机的时钟被 统一到同一个节奏,这是公平仲裁的基础。

    第三步:逐位仲裁(这才是关键!)

    在统一时钟的每个周期,所有主机在 SCL 低电平期间把各自的地址位放到 SDA 上:

    • 如果 A、B、C 都发送“0”(拉低 SDA):
      • SDA 为低,所有主机回读也是“0”,保持一致。
      • 这一位无法区分胜负,继续下一位。
    • 如果某一位上,A 发送“1”(释放 SDA),B 发送“0”(拉低 SDA):
      • A 期望 SDA 为高,但回读发现 SDA 被 B 拉低了。
      • A 立即意识到:有人和我冲突,我输掉了仲裁!
      • A 立即退出,切换为从机,不再驱动 SCL 和 SDA。
      • B 继续发送,甚至不知道 A 曾经存在。
    • 如果 A、B 都发送“0”,C 发送“1”:
      • C 回读发现 SDA 为低(被 A 和 B 拉低),C 退出。
      • A 和 B 继续竞争下一位。

    8)IIC 的时钟同步和时钟拉伸是什么

    8.1)时钟同步

    同上一个问题(已用黄色高亮)

    时钟同步发生于:多个主机在同一时间发起通信(都在总线空闲时产生 START 条件),仲裁阶段自动触发时钟同步。

    8.2)时钟拉伸

    时钟拉伸是 从设备 用来 延长总线时钟周期的机制 。从设备在主机释放 SCL(让 SCL 变高)后,故意将 SCL 继续拉低,阻止主机进入下一个时钟周期,直到从设备完成内部处理后释放 SCL,通信才继续。

    使用场景:

    • 从设备需要额外处理时间,例如:
      • 接收完一个字节后,需存入缓冲区或处理数据,来不及接收下一个字节。
      • 主机从从机读取数据,从机需要时间准备好要发送的数据。
    • 使慢速从设备能与快速主机正常通信,避免数据丢失。

    触发方式:

    • 主机往从机写数据:从设备在收到主机发出的第 8 个时钟脉冲后(即一个字节接收完成),若内部处理未完成,就在主机释放 SCL 后立即拉低 SCL,延长低电平。
    • 主机读取从机数据:从设备在主机读取数据时,在应答位之前或之后拉低 SCL 以换取准备时间。

    硬件IIC和软件模拟IIC的支持情况:

    • 硬件IIC:

      • 大多数现代 MCU 的 I²C 硬件模块都支持时钟拉伸的检测,可以从机模式下控制拉伸,从机模式下响应拉伸。

      • 当从机拉低 SCL 时,主机的硬件模块会自动插入等待周期,暂停状态机,直到 SCL 变为高再继续。软件不需要干预。

      • 但部分老旧或Simplified I²C 模块(如某些 I²C-Lite 模块)可能不支持时钟拉伸,或者需要特殊配置才能开启。

    • 软件模拟IIC:

      • 只要软件实现时加入了 SCL 低电平检测逻辑,模拟 I²C 即可完全支持时钟拉伸。
      • 典型实现:每次软件释放 SCL 后,轮询读取 SCL 引脚状态,若仍为低则一直等待,直到变高后再继续后续时序。

    9)IIC 通信中其他常见的问题及解决方案

  • 总线锁死

    • 现象:SDA 或 SCL 被某个设备一直拉低,总线无法恢复。

    • 解决方案:

      • 法1 – 软件复位:主机连续发送 9 个时钟脉冲,尝试完成被中断的传输,使从机释放总线。

      • 法2 – 硬件复位:对相关 I²C 设备进行硬件复位(如有复位引脚)。

      • 法3 – 电源循环:关闭再重新上电,强制重置所有设备。

  • 地址冲突

    • 现象:多个设备使用相同的 I²C 地址,导致通信混乱或设备无法区分。

    • 解决方案:

      • 法1 – 引脚选择:使用带有地址选择引脚(A0/A1/A2)的器件,通过硬件配置不同地址。

      • 法2 – 地址转换器:使用 I²C 地址转换芯片(如 PCA9547)将单一总线虚拟出多个独立地址段。

      • 法3 – 多总线设计:使用 MCU 的多组 I²C 接口,将冲突设备分散到不同总线上。

  • 时序问题

    • 现象:高速通信时数据错误、偶发失败,波形边沿过缓。

    • 解决方案:

      • 法1 – 减小上拉电阻:降低上升时间(但会增加功耗,需平衡)。

      • 法2 – 减少总线电容:缩短走线长度、减少从机数量、选用低电容器件。

      • 法3 – 降速:将通信速率降低到更稳定的档位(如从 400 kHz 降至 100 kHz)。

  • 噪声干扰

    • 现象:通信不稳定,偶发数据错误或挂死。

    • 解决方案:

      • 法1 – 屏蔽与隔离:使用屏蔽线缆,远离强干扰源。

      • 法2 – 增加滤波:在 SDA/SCL 线上对地加小电容(通常 100 pF 以下,避免影响上升时间)。

      • 法3 – PCB 布局:避免 I²C 走线与高速信号线(如 PWM、SPI)平行或靠近,用地线隔离


  • 赞(0)
    未经允许不得转载:171主机测评 » 单片机/C/C++八股:(二十七)IIC 专题(I²C)---- 下集
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址