嵌入式 I2C 通信全解析:从硬件原理到驱动实现

一、I2C 硬件基础:线与特性与电平驱动

理解 I2C 的硬件原理是掌握协议的第一步,其核心是 "线与" 逻辑和开漏输出设计,这决定了 I2C 的多设备通信能力。

1.1 线与(Wire-AND)特性

I2C 总线的核心电气特性是线与逻辑:总线上所有设备的 SDA/SCL 引脚均为开漏输出,总线电平由所有设备的输出共同决定。

chipA 输出 chipB 输出 实际总线电平
1(高阻态) 0(拉低) 0
0(拉低) 1(高阻态) 0
1(高阻态) 1(高阻态) 1(由上拉电阻决定)
0(拉低) 0(拉低) 0

核心原理:任何一个设备输出低电平,总线就会被拉低;只有所有设备都输出高阻态时,总线才会被上拉电阻拉到高电平。这一特性是 I2C 多设备通信的基础,也是 "仲裁" 和 "应答" 机制的硬件保障。

1.2 开漏输出与推挽输出的区别

I2C 设备的引脚必须配置为开漏输出模式,而常见的 GPIO 默认是推挽输出,两者的核心区别如下:

特性 开漏输出 推挽输出
驱动能力 仅能拉低总线,高电平依赖上拉电阻 可主动输出高 / 低电平
线与支持 支持,允许多设备并联 不支持,多设备并联会导致短路
应用场景 I2C、SMBus 等多设备总线 单设备 GPIO 输出、LED 驱动等

在 I2C 硬件设计中,SDA 和 SCL 线上必须外接4.7k~10kΩ 的上拉电阻,以保证总线在空闲时处于高电平状态。


二、I2C 时序协议:信号定义与通信流程

I2C 的通信完全由时序信号控制,掌握起始 / 停止信号、数据传输、应答机制是解析协议的核心。

2.1 核心时序信号定义

  • START(起始信号) :当 SCL 为高电平时,SDA 产生一个下降沿,表示通信开始。
  • STOP(停止信号) :当 SCL 为高电平时,SDA 产生一个上升沿,表示通信结束。
  • 数据传输:在 SCL 为低电平时,发送方可以改变 SDA 电平;在 SCL 为高电平时,SDA 电平必须保持稳定,接收方此时采样数据。
  • 应答(ACK/NACK) :接收方在接收到 1 字节数据后,在第 9 个时钟周期内拉低 SDA 表示ACK(应答) ,保持高电平表示NACK(非应答)

2.2 数据传输规则

  1. 字节序 :数据传输遵循MSB 优先原则,即每个字节的最高位最先发送。
  2. 时钟同步:SCL 由主机产生,但从设备可以通过拉低 SCL 实现 "时钟拉伸",以减慢通信速率,适配自身处理速度。
  3. 仲裁机制:当多个主机同时发送数据时,通过线与逻辑自动仲裁,首先发送低电平的主机获得总线控制权,避免数据冲突。

2.3 完整通信帧结构

一次典型的 I2C 通信分为 "主机写" 和 "主机读" 两种场景,帧结构如下:

(1)主机写数据到从设备

plaintext

复制代码
START → 从机地址(7位)+ 写标志(0)→ ACK → 寄存器地址 → ACK → 数据字节 → ACK → ... → STOP
(2)主机从设备读数据

plaintext

复制代码
START → 从机地址(7位)+ 写标志(0)→ ACK → 寄存器地址 → ACK → RESTART → 从机地址(7位)+ 读标志(1)→ ACK → 数据字节 → NACK → STOP

注:读操作需要先通过 "写" 操作指定寄存器地址,再发送重复起始信号(RESTART)切换为读模式。


三、I2C 驱动实现:从流程图到代码逻辑

I2C 驱动的开发核心是严格遵循时序协议,结合硬件寄存器配置实现完整的通信流程。下面结合你提供的流程图,解析 "主机写" 和 "主机读" 的驱动逻辑。

3.1 主机写驱动流程

  1. 初始化阶段:清除 I2C 状态寄存器的中断标志,配置为主机发送模式。
  2. 发送起始信号 :置位I2CR_MTX位产生 START 信号。
  3. 发送从机地址 :将从机地址 + 写标志写入数据寄存器I2DR,等待从机应答。
  4. 判断应答:若收到 NACK 则通信失败,直接发送 STOP 信号;若收到 ACK 则继续。
  5. 发送寄存器地址:写入目标寄存器地址,等待从机应答。
  6. 发送数据:依次发送数据字节,每发送 1 字节等待一次 ACK。
  7. 发送停止信号:所有数据发送完成后,产生 STOP 信号,释放总线。

3.2 主机读驱动流程

  1. 初始化与起始信号:与写流程一致,先发送起始信号和从机地址 + 写标志,指定寄存器地址。
  2. 重复起始信号:发送 RESTART 信号,切换为读模式。
  3. 发送从机地址 + 读标志:等待从机应答。
  4. 接收数据
    • 若接收长度 > 1,主机回复 ACK,继续接收下一字节;
    • 若接收最后 1 字节,主机回复 NACK,通知从机停止发送。
  5. 发送停止信号:接收完成后产生 STOP 信号。

3.3 关键寄存器说明

  • I2CR(控制寄存器):配置主机 / 从机模式、发送 / 接收模式,控制 START/STOP 信号。
  • I2SR(状态寄存器):指示中断标志、应答状态(RXAK位表示是否收到 ACK)、仲裁结果。
  • I2DR(数据寄存器):用于发送 / 接收数据字节。

四、开发避坑指南

  1. 上拉电阻选择:上拉电阻的阻值直接影响通信速率,4.7kΩ 适合 100kHz 标准模式,10kΩ 适合低速模式,阻值过大会导致信号上升沿过慢,影响稳定性。
  2. 时钟拉伸处理:从设备可能拉低 SCL 实现时钟拉伸,驱动中需检测 SCL 电平,等待从设备释放时钟后再继续传输。
  3. 应答检测:每发送 1 字节后必须检测从机的 ACK 信号,若未收到 ACK 需及时终止通信并处理错误。
  4. 总线冲突处理 :多主机场景下需处理仲裁失败的情况,通常通过检测I2SR_AL位(仲裁丢失标志)并重新发起通信。

五、总结

I2C 协议的核心是 "简洁高效":仅用两根线就实现了多设备组网,通过线与逻辑和应答机制保证了通信的可靠性。开发 I2C 驱动的关键在于:

  1. 理解硬件特性:开漏输出 + 上拉电阻的设计是 I2C 的物理基础。
  2. 严格遵循时序:起始 / 停止信号、数据采样、应答机制的时序必须精准。
  3. 健壮的错误处理:应答失败、仲裁丢失、时钟拉伸等异常场景需妥善处理。
相关推荐
恒锐丰-罗生19 分钟前
宽压降压电源新选择|CN8610 60V/1A 异步降压芯片,车载 / 工业 IoT 一站式解决方案
嵌入式硬件·硬件工程
恒锐丰-罗生20 分钟前
宽压降压新标杆!CN8810 4.5~100V 高压 DCM 异步降压芯片,车载 / 工业 IoT 全能电源方案
嵌入式硬件·硬件工程
@晓凡9 小时前
keil5找不到下载器
stm32
Devlab10 小时前
LVGL设计大师——网页版anyui来了!!
嵌入式硬件·物联网·低代码·ui·iot
Dr.kangder13 小时前
嵌入式面试总结(十五)——异常处理
单片机·面试·职场和发展·系统架构·嵌入式
zlinear数据采集卡15 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
ACP广源盛1392462567315 小时前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
Rocktech_ruixun17 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
振南的单片机世界17 小时前
SysTick硬核拆解:既是HAL_Delay的“心跳”,也是RTOS的“节拍器”
arm开发·stm32·单片机·嵌入式硬件
Lzh编程小栈18 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展