【嵌入式面试】I2C 高频面试题
【嵌入式面试】I2C 高频面试题
I2C(Inter-Integrated Circuit)是嵌入式开发中最常用的板级串行总线之一,也是面试中出现频率最高的通信协议考点。本文整理 I2C 从物理层到协议层的高频面试题与参考答案,覆盖总线构成、时序、仲裁、速率模式与工程实践,帮助你快速通关。
时序图
起始位是始终是高电平的时候,把数据线拉低
ACK就是在时钟为高电平的时候,把这个数据线拉低
NACK是在时钟为高电平的时候,这个数据线是高电平,就是从机没有操作这个数据线
7位的地址位加上一位的读写位,8位
第9个时钟沿就是我们的ACK/NACK反馈信号


一、总线构成与物理层
I2C 总线由哪几根线组成?为什么采用开漏输出加外部上拉的结构?
I2C 总线由 SCL(时钟线) 和 SDA(数据线) 两根线组成,均为双向。两根线都采用开漏(Open-Drain)输出并外接上拉电阻到电源;开漏结构使多个器件可以"线与"共享总线——任何器件都能把线拉低,而高电平由上拉电阻提供,从而天然支持多主机仲裁和从机时钟拉伸。
为什么 I2C 需要上拉电阻?阻值怎么选?
因为开漏输出只能拉低、不能主动输出高电平,高电平必须靠上拉电阻把 SDA/SCL 拉到电源。阻值影响上升沿时间与功耗:阻值越小上升沿越陡、支持更高速率,但灌电流/功耗越大;阻值越大越省电,但上升沿变缓,限制了速率和总线电容。工程上常用 4.7kΩ(标准模式 100kHz)、2.2kΩ~3.3kΩ(快速模式 400kHz),具体按总线电容和速率计算。
总线空闲时 SCL 和 SDA 处于什么电平?总线上可以挂多少设备?
空闲时两根线都被上拉电阻拉到高电平。7 位地址理论上可挂 128 个地址,但其中 16 个为保留地址(如广播地址 0x00、10 位寻址前缀 0x78/0x79 等),实际可用约 112 个;地址由器件引脚或配置决定,多个器件地址冲突时需改地址或换用不同器件。
二、协议时序
I2C 的起始条件(START)和停止条件(STOP)是什么?
起始条件:SCL 为高电平时,SDA 发生高→低跳变,由主机产生,标志一次传输开始;停止条件:SCL 为高电平时,SDA 发生低→高跳变,标志传输结束。只有主机可以发起 START/STOP;数据传输期间 SDA 只能在 SCL 低电平期间变化,SCL 高电平期间 SDA 必须保持稳定,这是数据有效的规则。
I2C 的应答机制(ACK/NACK)是怎样的?什么情况下出现 NACK?
每传输 8 位数据后,第 9 个时钟周期为应答位:接收方把 SDA 拉低表示 ACK(应答),保持高电平表示 NACK(非应答)。主机发送完从机地址后从机不应答,表示无此地址设备或设备忙;主机读操作读完最后一个字节时发 NACK 通知从机停止发送,随后产生 STOP。主机在收到 NACK 后应停止本次传输并做异常处理(如重试)。
I2C 一次完整的写操作时序是怎样的?
主机发 START → 发送 7 位从机地址 + 写位(0) → 等待从机 ACK → 发送寄存器/子地址 → 等待 ACK → 连续发送数据字节(每字节后等 ACK)→ 发送 STOP。读操作类似,只是地址字节的 R/W 位为 1,且常在地址与数据之间插入重复起始条件(Repeated START),先写寄存器地址再切换为读。
三、主机从机与仲裁
I2C 的主机(Master)和从机(Slave)如何区分?
主机是产生时钟 SCL、发起起始/停止条件的一方,负责发起通信;从机被主机寻址后被动响应,接收主机时钟并在应答位拉低 SDA。同一时刻总线上只能有一个主机驱动 SCL,但可以存在多主机,通过仲裁决定谁接管总线。
多主机同时发起通信时如何仲裁?
I2C 采用逐位仲裁(Bit-wise Arbitration):多个主机同时拉低 SCL 后,在 SDA 上逐位比较,发送高电平但读到低电平的主机判定仲裁失败,立即退出并停止发送,而发送低电平(逻辑 0)的主机继续。由于开漏"线与"特性,低电平优先,仲裁过程不丢失数据、不破坏总线时序;失败方可在总线空闲后重试。
什么是时钟拉伸(Clock Stretching)?
时钟拉伸是从机通过拉低 SCL 来暂停主机时钟的机制:从机在准备数据或处理内部事务时把 SCL 拉低,主机检测到 SCL 被拉低后必须等待,直到从机释放 SCL 才继续。它用于慢速从机与主机之间的速率协调;软件模拟 I2C 时必须支持检测 SCL 电平,硬件 I2C 外设一般自动处理。
四、速率与对比
I2C 有哪几种速率模式?
I2C 规范定义了多种速率:标准模式(Standard)100kbit/s、快速模式(Fast)400kbit/s、快速模式+(Fast Mode Plus)1Mbit/s、高速模式(High-speed)3.4Mbit/s 以及超快速模式(仅写)。速率越高,对上拉电阻、总线电容、PCB 布线要求越严格,高速模式还要求主机提供电流提升源。
为什么 I2C 速率上不去?上拉电阻如何限制速率?
I2C 靠上拉电阻产生高电平,而总线上的分布电容使上升沿呈 RC 充电曲线,上升时间约为 0.85×R×C。速率越高,允许的上升时间越短,因此必须减小上拉电阻;但电阻过小又会导致低电平灌电流超限、功耗增大(器件 IOL 有最大电流限制)。这就是 I2C 速率受物理层制约、难以像 SPI 那样跑到几十 MHz 的原因。
I2C 与 SPI 相比有什么优缺点?什么场景选 I2C?
I2C 优点:只需 2 根线、多设备共享总线(靠地址区分)、有应答机制可确认通信是否成功、支持多主机。缺点:速率低(常规 100/400kbps)、时序复杂、每字节有 ACK 开销、半双工。适合低速、多设备、引脚紧张的场景(如传感器、EEPROM、RTC);需要高速或全双工时选 SPI。
五、软件模拟与工程实践
软件模拟 I2C(GPIO 模拟)有哪些要点?
要点:① GPIO 配置为开漏输出(或推挽+切换输入方向)以模拟"线与";② 严格按时序延时产生 SCL 高低电平,保证 SCL 高电平期间 SDA 稳定;③ 发送 START/STOP/ACK 时注意边沿先后顺序;④ 每收 8 位后释放 SDA(置输入或输出 1),再在第 9 个时钟读 SDA 判断 ACK;⑤ 支持时钟拉伸需在读 SCL 前先释放 SCL;⑥ 注意微秒级延时的准确性,避免时序违例。
软件模拟 I2C 时如何判断从机是否 ACK?
发送完 8 位数据后,主机先把 SDA 释放为高(配置为输入或输出 1),然后在第 9 个 SCL 高电平期间读取 SDA:读到低电平说明从机 ACK,读到高电平说明 NACK。注意读之前必须释放 SDA,否则开漏输出低电平会把 SDA 钳死,永远读不到从机的应答。
从机一直不应答(NACK 超时)怎么排查?
依次排查:① 地址是否正确(对照 datasheet,注意地址是否左移了一位);② 上拉电阻是否焊接/取值正确;③ SCL/SDA 是否接反;④ 从机供电与复位是否正常;⑤ 总线是否被其他器件拉死(SDA 常低);⑥ 时序是否满足从机要求(如时钟频率过高)。软件上可加超时重试机制。
I2C 的读操作中"重复起始条件"有什么用?
重复起始条件(Repeated START) 是在不释放总线的情况下,在一条传输中间再次发出 START:典型用于读寄存器场景,主机先写寄存器地址,然后不停止、直接发 Sr + 从机地址 + 读位,切换方向读取数据。好处是独占总线,避免其他主机在两条传输之间抢占,也省去 STOP/START 的时序开销。
硬件 I2C 外设和软件模拟 I2C 各有什么优缺点?
硬件 I2C 由外设自动产生时序、不占 CPU,但受引脚复用限制、时序固定,且部分 MCU 硬件 I2C 有坑(如总线忙标志卡死)需小心处理;软件模拟用 GPIO+延时实现,任意引脚可用、时序可控、调试直观,但占用 CPU、受中断影响时序不稳定。面试常考结论:工程中常用软件模拟以保证移植性和稳定性。
I2C 设备地址是 7 位还是 8 位?读写位怎么用?
I2C 标准支持 7 位和 10 位两种地址。7 位地址作为地址字节的高 7 位,最低位是 R/W 读写位(0=写、1=读),所以 7 位地址器件在总线上实际占用 8 位地址字节;10 位地址用第一个字节的前 5 位 11110 作为标志,剩余 2 位是 10 位地址的最高 2 位,第二个字节是地址低 8 位。10 位地址用于同一条总线上设备过多的场景。

