USER GUIDE / PERIPHERALS / I2C / SLAVE MODE OPERATION

从机模式操作

本节包括以下过程:

  • “初始配置”
  • “单字节的从机发送器操作”
  • “单字节的从机接收器操作”
  • “批量传输的从机发送操作”

初始配置

使用 I2C 作为从机,请执行以下步骤:

  1. 通过将 0 写入 I2C_ENABLE 寄存器的 0 位来禁用 I2C。
  2. 写入 I2C_SAR 寄存器(9:0 位)来设置从机地址。这是 I2C 响应的地址。
  3. 写入 I2C_CON 寄存器以指定支持的寻址类型(通过第 3 位设置 7 或 10 位寻址)。通过将“0”写入第 6 位(I2C_SLAVE_DISABLE)和将“0”写入第 0 位(MASTER_MODE),在仅从机模式下启用 I2C。

从机和主机不必使用相同类型的寻址 7 或 10 位地址。例如,从机可以编程为 7 位寻址,主机可以编程为 10 位寻址,反之亦然。

  1. 通过将 1 写入 I2C_ENABLE 寄存器的 0 位来启用 I2C。

根据选择的复位值,可能不需要步骤 2 和步骤 3,因为可以配置复位值。例如,如果设备仅作为主机,则无需设置从机地址,因为可以将 I2C 配置为在复位后禁用从机,并在复位后启用主机。存储的值是静态的,如果禁用 I2C,则不需要重新编程。

单字节的从机发送器操作

当总线上的另一个 I2C 主设备寻址 I2C 并请求数据时,I2C 充当从机发送器,并发生以下步骤:

  1. 另一个 I2C 主设备使用与 I2C 的 I2C_SAR 寄存器中的从机地址匹配的地址启动 I2C 传输。
  2. I2C 响应发送的地址并识别传输方向,以表明它作为一个从机发送器。
  3. I2C 断言 RDREQ 中断(I2C_INTST 寄存器的第 5 位)并保持 SCL 为低电平。它处于等待状态,直到软件响应。

如果 RDREQ 中断已被屏蔽,由于 I2C_INTM[5] 寄存器(MRDREQ 位)被设置为 0,那么建议使用硬件和/或软件定时例程来指示 CPU 执行 I2C_INTST 寄存器的定期读取。

a 指示 I2C_INTST[5](RDREQ 位)设置为 1 的读取必须被视为等同于被断言的 RDREQ 中断。

b 然后软件必须采取行动以满足 I2C 传输。

c 使用的时间间隔应该是 I2C 能够处理最快 SCL 时钟周期的 10 倍。例如,对于 400kb/s,时间间隔为 25us。

此处建议值 10,因为这大约是在 I2C 总线上传输单个字节数据所需的时间量。

  1. 如果在接收到读请求之前,TX FIFO 中仍有数据,那么 I2C 会断言 TX_ABRT 中断(I2C_INTST 寄存器的第 6 位)以从 TX FIFO 中刷新旧数据。

由于每当 TX_ABRT 事件发生时,I2C 的 TX_FIFO 都会被强制进入刷新/复位状态,因此软件必须在尝试写入 TX_FIFO 之前,通过读取 I2C_CTXABT 寄存器来将 I2C 从该状态释放。有关更多细节,请参见 I2C_INST 寄存器。如果 TX_ABRT 中断已被屏蔽,由于 I2C_INTM[6] 寄存器(MTX_ABRT 位)被设置为 0,那么建议重新使用定时例程(如前一步的描述)或类似的例程用于读取 I2C_INST 寄存器。

a 指示第 6 位(TXABT)设置为 1 的读取必须被视为等同于被断言的 TX_ABRT 中断。

b 软件不需要进行进一步的操作。

c 所使用的时间间隔应该与上一步中为 I2C_INST[5] 寄存器所描述的类似。

  1. 软件将要写入的数据写入 I2C_DC 寄存器(通过在第 8 位中写‘0’)。
  2. 在继续之前,软件必须清除 I2C_INTST 寄存器的 RDREQ 和 TX_ABRT 中断(分别为第 5 位和第 6 位)。

如果 RDREQ 和/或 TX_ABRT 中断已被屏蔽,则当 RDREQ 或 TXABT 位被读取 1 时,将已经执行 I2C_INTST 寄存器的清除。

  1. I2C 释放 SCL 并传输该字节。
  2. 主机可以通过发出 RESTART 条件来保持 I2C 总线,或通过发出 STOP 条件来释放总线。

单字节的从机接收器操作

当总线上的另一个 I2C 主设备寻址 I2C 并发送数据时,I2C 充当从机接收器,并发生以下步骤:

  1. 另一个 I2C 主设备使用与 I2C 的 I2C_SAR 寄存器中的从机地址匹配的地址启动 I2C 传输。
  2. I2C 响应发送的地址并识别传输方向,以表明它作为一个从机接收器。
  3. I2C 接收传输的字节,并将其放入接收缓存中。

如果在推送一个字节时,RX FIFO 已完全充满数据,则会发生溢出,I2C 继续进行后续的 I2C 传输。由于没有生成 NACK,软件必须在 I2C(由 I2C_INTST 寄存器的 RXOF 位)指示时识别溢出,并采取适当的操作从丢失的数据中恢复。因此,在 RX FIFO 溢出之前,软件服务 RX FIFO 存在实时限制,因为无法向远程发送主机重新施加压力。必须选择足够深的 RX FIFO 深度以满足系统的中断服务间隔。

  1. I2C 断言 RX_FULL 中断(I2C_INTST[2] 寄存器)。

如果 RX_FULL 中断被屏蔽,由于将 I2C_INTM[2] 寄存器设置为 0 或将 I2C_TX_TL 设置为大于 0 的值,那么建议执行定时例程以定时读取 I2C_ST 寄存器。I2C_ST 寄存器的读取,第 3 位(RFNE)设置为 1 时,软件必须将其视为等同于断言的 RX_FULL 中断。

  1. 软件可以从 I2C_DC 寄存器(7:0 位)读取字节。
  2. 另一个主机可以通过发出 RESTART 条件来保持 I2C 总线,或通过发出 STOP 条件来释放总线。

批量传输的从机发送操作

在标准 I2C 协议中,所有传输都是单字节传输,程序员通过将一个字节写入从机的 TX FIFO 来响应远程主机的读取请求。

当从机(从机—发送器)收到远程主机(主机—接收器)的读请求(RDREQ)时,从机—发送器的 TX FIFO 中至少应该有一个数据。

I2C 被设计用于处理 TX FIFO 中更多的数据,以便后续读请求可以获取该数据,而无需触发中断来获取更多数据。最终,这消除了在 TX FIFO 中仅放置一个数据的限制下,每次触发数据中断之间产生重大延迟的可能性。

此模式仅在 I2C 作为从机—发送器时发生。如果远程主机响应从机—发送器发送的数据,并且从机的 TX FIFO 中没有数据,则 I2C 将 I2C SCL 线保持为低电平,同时触发读取请求中断(RDREQ)并等待数据写入 TX FIFO,然后才能发送到远程主机。

如果 RDREQ 中断被屏蔽,由于 I2C_INTST 寄存器的第 5 位(MRDREQ)设置为 0,则建议使用定时例程来激活对 I2C_INST 寄存器的定时读取。返回位 5(RDREQ)设置为 1 的 I2C_INTST 读取必须被视为等同于本节中提到的 RDREQ 中断。

RDREQ 中断在读取请求时触发,和中断一样,必须在退出中断服务处理例程时清除(ISR)。ISR 允许将一个字节或多个字节写入 TX FIFO。在将这些字节传输到主机期间,如果主机响应最后一个字节。然后从机必须再次触发 RDREQ,因为主机正在请求更多数据。