I2C 从机开发:事务流程、数据组织与耗时应答

I2C 从机开发先掌握普通事务,再处理变长响应和耗时操作。

先记住四条规则

从机开发先关注三种事务:

写:      START → 地址+W → 请求 → STOP
读:      START → 地址+R → 响应 → STOP
写后读:  START → 地址+W → 请求 → RESTART → 地址+R → 响应 → STOP

从请求到响应

I2C 只定义传输,不定义字节含义。从机软件可按一条链路组织:

RX 回调 → 请求缓冲 → 业务执行 → 响应快照 → TX 回调

回调负责搬运数据和记录事件,耗时业务放在回调外。TX 始终读取一份稳定快照。写后读可能紧接 RESTART,来不及完成的请求先返回 BUSY

两种数据模型

I2C 从机主要使用寄存器模型和命令模型。命令通常采用二进制编码;文本命令属于自定义的应用层编码。

寄存器 二进制命令 文本命令(少见)
模型 寄存器模型 命令模型 命令模型
开头 寄存器地址 操作码 命令词
长度 由寄存器定义 定长或长度字段 写入可分隔,读取须约定
特点 适合配置和状态 紧凑、效率高 可读、便于调试

寄存器可由软件虚拟,也可包含命令寄存器。设备可混合使用寄存器和二进制命令。文本命令多用于 MCU 间自定义通信、调试或复用 UART 命令行。移植到 UART 或 SPI 时,帧边界和读写方向仍需适配。

特殊情况一:变长读取

I2C 读阶段没有从机发出的结束标记。多数主机 API 要求调用前给定字节数,通用方案是两次应用层读取:

读固定响应头 → 取得长度 N → 校验 N → 再读 N 字节

寄存器模型可提供长度寄存器和数据区,命令模型可返回响应头和载荷。实现时还要保证:

文本结束符只能标记内容结束,不能替主机结束 I2C 读取。

少数控制器支持读到长度后在同一事务中继续收取,具体取决于硬件和驱动。

特殊情况二:耗时操作

Flash 擦写、采样或电机动作不能立即完成时,可从以下方式中选择:

方式 含义 适用场景 限制
时钟拉伸 从机拉低 SCL 暂停时钟 很短且上限明确 占用总线,可能超时
状态轮询 主机反复读取状态 通用默认方案 增加轮询事务
地址 NACK 从机忙时拒绝地址访问 主从明确约定 无法区分忙、掉电或缺失
GPIO 通知 完成后改变 GPIO 电平 时间长或不确定 多占一个引脚

状态通过寄存器、命令或响应头返回 BUSY/DONE/ERROR。耗时很长时可增加 GPIO 通知。

STM32 实现提醒