I2C

示例列表

本章介绍 I2C 示例的详细信息。RTL87x2G 为 I2C 外设提供以下示例。

功能概述

I2C 总线是一种双线串行接口,由串行数据线( SDA )和串行时钟线( SCL )组成。 这2条线用于在连接到总线的设备之间传输信息。

I2C 总线上的每个设备都有一个唯一的地址,可以根据设备的功能作为发送器或接收器操作。

在进行数据传输时,设备也可以被视为主设备或从设备。 主设备负责总线上发起数据传输,并生成允许传输的时钟信号。 一旦主设备发起数据传输,任何被寻址的设备都被视为从设备。

特性列表

  • 支持最多 4 个 I2C。

  • 双线 I2C 串行接口:由串行数据线 (SDA) 和串行时钟 (SCL) 组成。

  • 支持主设备模式和从设备模式。

  • 支持 7/10 位寻址模式。

  • 支持 standard mode(0 到 100Kb/s)、fast mode(小于等于 400Kb/s)和 fast mode plus(小于等于 1000Kb/s)。

  • 支持 40MHz 时钟源。

  • 支持中断或轮询模式操作。

  • 发送 FIFO 深度:24。

  • 接收 FIFO 深度:24。

  • 支持 GDMA 传输。

系统框图

I2C 的体统框图如下图所示:

../../../../../_images/I2C_block_diagram.png

I2C 系统框图

通信协议

在 SDA 线上发送的每个字节必须为 8 位。 每次传输可以发送的字节数没有限制,每个字节后必须跟随一个响应位。 数据的最高有效位 (MSB) 最先传输。

如果从设备需要完成其他功能,如内部中断服务程序,它可以接收或发送下一个完整的数据字节。时钟线 SCL 可以保持低电平以迫使主设备进入等待状态。 当从设备准备好接收下一个数据字节并释放时钟线 SCL 时,数据传输继续。

../../../../../_images/Schematic_Diagram_of_I2C_Transmission_Protocol.jpg

I2C 传输协议原理图

I2C Command

当第一个数据写入到 I2C TX FIFO 中,传输开始,硬件会自动发送命令。传输将在主设备发出 STOP 信号后终止。 写入 I2C TX FIFO 的命令格式如下所示:

I2C Command Format

Function Description

BIT[31:11]

BIT[10]

BIT[9]

BIT[8]

BIT[7:0]

Command Format

Reserved

Restart

Stop

Command

Data

Write data

0

0

0

0

xxxxxxxx

Write the last data

0

0

1

0

xxxxxxxx

Read data

0

0

0

1

0

Read the last data

0

0

1

1

0

主设备通信模式

I2C 主设备支持如下通信模式:Master Write,Master Read 和 Master Repeat Read。 在 LoopBack 示例中,详细介绍了三种通信模式的示例程序。

用户可以通过将参数 I2C_InitTypeDef::I2C_DeviveMode 设置为 I2C_DeviveMode_Master 来将 I2C 设备模式设置为主设备,设置为 I2C_DeviveMode_Slave 来将 I2C 设备模式设置为从设备。

下面将介绍上述三种模式在 7-bit 地址和 10-bit 地址模式下的通信时序。

7-Bit 地址模式

Master Write

函数 I2C_MasterWrite() 实现了 I2C 主设备在轮询模式下写入数据的功能。

主设备通过 7 位从设备地址向从接收器传输数据。传输方向不变。 所有数据以字节格式传输,单次数据传输的字节数没有限制。 主设备发送地址和读/写位后,或主设备向从设备传输一个字节的数据后,从接收器必须响应确认信号。 当从接收器没有响应 ACK 脉冲时,主设备通过发出停止条件中止传输。 从设备必须保持 SDA 线为高电平,以便主设备中止传输。

../../../../../_images/Master_Write_in_7-bit_Addressing_Mode.jpg

7-Bit 地址模式下 Master Write 示意图

Master Read

函数 I2C_MasterRead() 实现了 I2C 主设备在轮询模式下读取数据的功能。

在第一次响应中,主设备-发送器变为主设备-接收器,从设备-接收器变为从设备-发送器,并且第一次响应仍由从设备生成。 如果主设备正在接收数据,主设备在接收到一个字节的数据后会向从设备-发送器发送一个确认脉冲,除了最后一个字节。 NACK 是主设备-接收器通知从设备-发送器这是最后一个字节的方式。 从设备-发送器在检测到无确认(NACK)后释放 SDA 线,以便主设备能够发出停止条件。

../../../../../_images/Master_Read_in_7-bit_Addressing_Mode.jpg

7-Bit 地址模式下 Master Read 示意图

Master Repeat Read

函数 I2C_RepeatRead() 实现了 I2C 主设备在轮询模式下先写入后读取数据的功能。

在执行写前读操作时,开始条件和从设备地址会被重复发送,但读/写位是相反的。

../../../../../_images/Master_Repeat_Read_in_7-bit_Addressing_Mode.jpg

7-Bit 地址模式下 Master Repeat Read 示意图

10-Bit 地址模式

Master Write

函数 I2C_MasterWrite() 实现了 I2C 主设备在轮询模式下写入数据的功能。

主设备发送器以 10 位从设备地址向从设备接收器发送数据。传输方向不变。

../../../../../_images/Master_Write_in_10-bit_Addressing_Mode.jpg

10-Bit 地址模式下 Master Write in 10-Bit Addressing Mode

Master Read

函数 I2C_MasterRead() 实现了 I2C 主设备在轮询模式下读取数据的功能。

主设备发送器以 10 位从设备地址向从设备接收器发送数据。 在第二个读/写位之后,传输方向发生变化,主设备发送器变为主设备接收器,从设备接收器变为从设备发送器。

../../../../../_images/Master_Read_in_10-bit_Addressing_Mode.jpg

10-Bit 地址模式下 Master Read 示意图

Master Repeat Read

函数 I2C_RepeatRead() 实现了 I2C 主设备在轮询模式下先写入后读取数据的功能。

主设备向从设备发送数据,然后从同一从设备读取数据。传输方向在第二个读/写位后发生改变。

../../../../../_images/Master_Repeat_Read_in_10-bit_Addressing_Mode.jpg

10-Bit 地址模式下 Master Repeat Read 示意图

I2C GDMA

I2C GDMA TX

在 I2C 传输过程中,当 TX FIFO 内数据的数量小于或等于初始化中设置的 I2C_InitTypeDef::I2C_TxWaterlevel 值时,会触发一次 GDMA burst 搬运。 GDMA 一次 burst 会将 GDMA_InitTypeDef::GDMA_DestinationMsize 个数据写入 I2C TX FIFO 中。

I2C GDMA TX 时,推荐设置 I2C_InitTypeDef::I2C_TxWaterlevel 的值为 I2C_TX_FIFO_SIZE - MSize

Here should be i2c tx dma diagram

I2C GDMA TX 示意图

I2C GDMA RX

在 I2C 传输过程中,当 RX FIFO 内数据的数量大于或等于初始化中设置的 I2C_InitTypeDef::I2C_RxWaterlevel + 1 时,会触发一次 GDMA burst 搬运。 GDMA 一次 burst 会从 I2C RX FIFO 中获取 GDMA_InitTypeDef::GDMA_SourceMsize 个数据。

I2C GDMA RX 时,推荐设置 I2C_InitTypeDef::I2C_RxWaterlevel 的值为 MSize - 1

Here should be i2c rx dma diagram

I2C GDMA RX 示意图

常见问题

时钟速度配置说明

I2C 时钟速度与 SCL 上升时间有关,该时间受上拉电阻和电容影响。 用户可以配置变量 I2C_InitTypeDef::I2C_RisingTimeNs 来校准 I2C 时钟速度。I2C_InitTypeDef::I2C_RisingTimeNs 的默认值为 50。 以下示例演示了 I2C 时钟速度的校准方法,以 I2C 的时钟源 40 MHz 为例:

  1. 将变量 I2C_InitTypeDef::I2C_RisingTimeNs 设置为 100。

  2. 测量 I2C 时钟速度。例如,如果实际测得的频率为 411 KHz,则周期为:1/411 KHz = 2433 ns。

  3. 计算 I2C_InitTypeDef::I2C_RisingTimeNs 的实际值。

    1. SCL Low Time = SCL Low Period - SCL Falling Time + SCL Rising Time.

    2. SCL High Time = SCL High Period + SCL Falling Time.

    3. SCL Frequency = 1 / (SCL High Time + SCL Low Time).

    4. 根据公式 a 到 c,SCL Period = SCL Low Period + SCL High Period + SCL Rising Time.

    5. SCL Low Period (ns) + SCL High Period (ns) = SCL Period (ns) - APP 中配置的 I2C_InitTypeDef::I2C_RisingTimeNs = 2500 - 100 = 2400.

    6. 实际 I2C_InitTypeDef::I2C_RisingTimeNs 值 = 实际周期 - (SCL Low Period + SCL High Period) = 2433 - 2400 = 33。

    7. 因为 I2C 的时钟源设置为 40MHz,I2C 时钟的精度为 25ns。因此,设置 I2C_InitTypeDef::I2C_RisingTimeNs 需要对齐到 25ns。