4、I2C工作模式详解:主机模式、从机模式、多主机模式下的仲裁与同步
I2C 总线协议定义了三种核心工作模式:主机模式(Master Mode)、从机模式(Slave Mode)以及多主机模式(Multi-Master Mode)。理解这三种模式的状态机、信号驱动方式以及总线冲突解决机制,是进行 XMC 系列 MCU 多设备调试的基础。
4.1 主机模式(Master Mode)
主机模式是 I2C 通信的发起方。在 XMC 系列中,主机负责产生串行时钟(SCL)、发起起始条件(S)、发送从机地址以及读/写位,并最终产生停止条件(P)。
| 主机职责 | 信号控制 | XMC 寄存器配置要点 |
|---|---|---|
| 时钟产生 | SCL 线由主机驱动高低电平 | 配置 CCR(时钟控制寄存器)设定标准模式(100kHz)或快速模式(400kHz) |
| 起始条件 | SCL 高电平时,SDA 由高变低 | 设置 I2C_CON 寄存器的 START 位 |
| 地址发送 | 发送 7 位地址 + R/W 位,等待 ACK | 写入 I2C_ADD 寄存器,检查 ACKSTAT |
| 数据传输 | 每字节后由从机产生 ACK | 使用 TX/RX FIFO 或中断方式处理 |
| 停止条件 | SCL 高电平时,SDA 由低变高 | 设置 I2C_CON 寄存器的 STOP 位 |
实战提示: 在 XMC 主机模式下,务必在发送起始条件前检查总线是否空闲(BUSY 标志位为 0)。若总线被占用,主机应等待或重试,避免破坏正在进行的通信。
4.2 从机模式(Slave Mode)
从机模式是被动响应模式。从机不产生时钟,而是监听 SCL 和 SDA 线。当检测到起始条件且接收到的地址与自身地址匹配时,从机参与通信。
- 地址识别: 从机将接收到的 7 位地址与自身地址寄存器(I2C_OWN_ADD)比较。XMC 支持多个自身地址,可用于多地址响应。
- ACK/NACK 响应: 地址匹配后,从机在第 9 个 SCL 周期拉低 SDA 产生 ACK;若不匹配或无法处理,则释放 SDA 产生 NACK。
- 数据收发: 根据 R/W 位,从机进入发送模式(将数据写入 SDA)或接收模式(从 SDA 读取数据)。
- 停止条件检测: 从机检测到停止条件后,复位内部状态机,等待下一次起始条件。
调试要点: 从机模式下常见的故障是地址不匹配。使用逻辑分析仪抓取 SDA 线上的地址字节,并与 XMC 的 I2C_OWN_ADD 寄存器值对比。注意 XMC 的地址寄存器默认左对齐,7 位地址需写入高 7 位。
4.3 多主机模式与仲裁(Arbitration)
多主机模式允许多个主机共享同一 I2C 总线。由于 SDA 和 SCL 是开漏结构,当两个主机同时尝试驱动总线时,必须通过仲裁机制决定谁获得总线控制权。
4.3.1 仲裁原理
仲裁发生在 SDA 线上。当多个主机同时发送起始条件并开始输出时钟时,它们会逐位比较 SDA 电平。如果某个主机试图输出高电平(释放 SDA),但检测到 SDA 被另一个主机拉低,则该主机失去仲裁并立即转为从机模式。
- 仲裁不丢失数据: 由于仲裁过程只比较地址和数据位,且未赢得仲裁的主机停止驱动 SDA,因此总线上的数据不会损坏。
- 时钟同步: 多个主机的 SCL 时钟会进行线与,最终 SCL 的低电平时间由最长的低电平决定,高电平时间由最短的高电平决定,实现时钟同步。
关键规则: 仲裁只能在 SDA 上进行,SCL 线不参与仲裁。主机必须在发送起始条件后的第一个字节(地址 + R/W)内完成仲裁。如果两个主机发送完全相同的地址和数据,则它们可以同时完成整个传输而不发生仲裁丢失。
4.3.2 时钟同步(Clock Synchronization)
时钟同步是多主机模式下保证数据完整性的基础。所有主机在 SCL 线上进行线与,使得 SCL 的低电平时间被拉长至所有主机中低电平时间最长的那个,高电平时间被缩短至所有主机中高电平时间最短的那个。
4.4 多主机模式下的状态切换与中断处理
在 XMC 系列中,多主机模式需要软件配合硬件状态机进行处理。当主机失去仲裁时,硬件会自动执行以下操作:
- 释放总线: 停止驱动 SDA 和 SCL,转为从机模式。
- 设置仲裁丢失标志: I2C_STATUS 寄存器中的 ARL(Arbitration Lost)位被置 1。
- 触发中断: 如果使能了仲裁丢失中断,CPU 会收到中断请求。
软件处理流程: 在中断服务函数中,检查 ARL 位。如果仲裁丢失,软件应清除 ARL 位,重置发送缓冲区指针,并等待总线空闲后重新尝试发送起始条件。切勿在仲裁丢失后继续发送数据,否则会破坏总线状态。
4.5 三种模式对比总结
| 特性 | 主机模式 | 从机模式 | 多主机模式 |
|---|---|---|---|
| 时钟产生 | 是 | 否 | 多个主机共同产生(线与) |
| 起始/停止条件 | 由主机产生 | 检测 | 由赢得仲裁的主机产生 |
| 地址发送 | 发送 | 接收并匹配 | 发送并参与仲裁 |
| 总线冲突 | 无(单主机) | 无 | 通过仲裁解决 |
| XMC 典型应用 | 读取传感器、控制外设 | 响应主机请求 | 多 MCU 数据交换 |
4.6 调试实战:多主机仲裁测试
在 XMC 开发板上进行多主机仲裁测试时,建议按以下步骤操作:
- 步骤 1: 将两块 XMC 开发板的 SDA 和 SCL 引脚短接,并各接 4.7kΩ 上拉电阻到 3.3V。
- 步骤 2: 配置两块板卡为主机模式,设置相同的时钟频率(如 100kHz)。
- 步骤 3: 编写测试代码,使两块板卡同时向同一从机地址(如 0x50)发送起始条件。
- 步骤 4: 使用逻辑分析仪抓取 SDA 和 SCL 波形,观察仲裁过程。
- 步骤 5: 检查两块板卡的 ARL 标志位,确认仲裁丢失的一方是否正确转为从机模式。
// XMC 多主机仲裁丢失中断处理示例
void I2C0_IRQHandler(void)
{
uint32_t status = I2C0->STATUS;
if (status & I2C_STATUS_ARL_MASK) {
// 仲裁丢失
I2C0->STATUS = I2C_STATUS_ARL_MASK; // 清除标志
I2C0->CON = 0; // 复位控制寄存器
// 等待总线空闲后重试
while (I2C0->STATUS & I2C_STATUS_BUSY_MASK);
I2C0->CON = I2C_CON_MASTER_MASK | I2C_CON_START_MASK;
}
// 其他中断处理...
}
经验总结: 多主机仲裁调试中,最容易忽略的是上拉电阻的匹配。如果两个主机的上拉电阻差异过大,会导致 SDA 上升沿时间不一致,增加仲裁失败的概率。建议使用相同阻值的上拉电阻,并确保总线电容在允许范围内。