STM32F1与STM32CubeIDE快速入门I2C概述
STM32F1与STM32CubeIDE快速入门-I2C概述
I2C概述
1、什么是I2C
I2C (i-square-c) 是“Inter-Integrated-Circuit”的首字母缩写词,最初由飞利浦半导体(现为 NXP)于 1982 年创建。I2CTM 是其各自所有者的注册商标,也许这就是他们的原因 在某些微控制器(如 Atmel AVR)中将其称为“双线接口 (TWI)”。 I2C 是一种多主、多从、同步、双向、半双工串行通信总线。 它广泛用于在短距离板内通信中将低速外围 IC 连接到处理器和微控制器。
1.1 I2C 模式和总线速度
最初,I2C 总线仅限于 100 kbit/s 的操作。 随着时间的推移,规范中增加了一些内容,因此现在有五个运行速度类别。 标准模式、快速模式 (Fm)、快速模式 Plus (Fm+) 和高速模式 (Hs 模式) 设备向下兼容。 这意味着任何设备都可以以较低的总线速度运行。 由于总线是单向的,因此超快速模式设备与以前的版本不兼容。
1)双向总线:
- 标准模式 (Sm),比特率高达 100 kbit/s
- 快速模式 (Fm),比特率高达 400 kbit/s
- Fast-Mode Plus (Fm+),比特率高达 1 Mbit/s
- 高速模式(Hs-mode),比特率高达 3.4 Mbit/s。
2)单向总线:
- 超快速模式 (UFm),比特率高达 5 Mbit/s
注意:必须参考特定器件的数据手册,以检查实际已在片上实现的 i2c 硬件规范的典型详细信息。
1.2 I2C 物理层(硬件)
I2C 总线为 SDA 和 SCL 线使用所谓的开漏(集电极开路)输出驱动器。 顾名思义,就是将每个 IO 引脚在内部连接到输出驱动晶体管的集电极,同时通过一个电阻器将其永久上拉到 Vcc。 这就是为什么当开漏驱动器关闭时每条线的默认 (IDLE) 状态为高电平的原因。 但是,如果我们打开输出驱动器,则输出驱动器晶体管将 IO 引脚驱动为低电平至地,如下图所示。

I2C 总线是“开漏”双向引脚,非常适合多主多从类型的通信,没有任何冲突风险。 这是因为在多个主节点同时发起交易的情况下,所谓的“总线仲裁”。
任何一个先写0,而另一个写1,将赢得仲裁并继续发送消息,另一个主站将停止等待直到结束。 这是因为“开漏”输出的性质。 要写入 0,我们打开输出驱动器以将信号线拉至低电平。 要写入 1,我们关闭输出驱动器,该线将通过外部电阻器的作用被拉高至高电平。 这就是为什么总线仲裁是 I2C 通信的一个非常强大的功能。
1.3 SDA & SCL,数据有效性
SDA 和 SCL 都是双向线路,通过电流源或上拉电阻连接到正电源电压。 当公共汽车空闲时,两条线路都是高电平。 连接到总线的设备的输出级必须具有漏极开路或集电极开路才能执行线与功能。
由于可以连接到 I2C 总线的不同技术设备(CMOS、NMOS、双极)的多样性,逻辑“0”(低)和“1”(高)的电平不是固定的,取决于$ V_{DD}$ 的相关电平。 输入参考电平设置为 $ V_{DD}$的 30% 和 70%;
V
I
L
V_{IL}
VIL 为 0.3$ V_{DD}
,
,
,V_{IH}$ 为 0.7$ V_{DD}$。 在时钟的高电平期间,SDA 线上的数据必须是稳定的。 数据线的HIGH或LOW状态只有在SCL线上的时钟信号为LOW时才能改变。 每传输一个数据位都会产生一个时钟脉冲。

1.4 I2C 通信事务的元素
典型的 I2C 消息由一些在 I2C 总线上顺序发生的基本元素(条件)组成,并且它始终以启动条件开始。 后跟所需的从设备地址(7 位或 10 位),然后是 R/W 位,以确定主设备(发起 S 条件进行通信)是否要读取或写入具有该地址的从设备。 然后如果从设备存在并且工作正常,它将通过发送一个确认位 ACK 向主设备进行确认,否则,它被认为是一个否定确认 NACK。 之后,发送数据字节,然后是从机的确认。 最后,主机可以通过发送停止条件 § 序列来终止通信。

我们可以将 I2C 总线信号的这些条件(要素)总结如下:
- 启动条件 (S)
- 停止条件 §
- 重复启动 (Restart) 条件 (Sr)
- 确认 ACK (A)
- 不确认 NACK (~A)
- 地址 + 读/写
- 数据字节
I2C 操作机制的其他主题和细节将在下面的文章中详细讨论。 包括 I2C 时钟同步、拉伸、I2C 总线仲裁、寻址、I2C 总线条件等。
2、SMT32中的I2C硬件
2.1 STM32 I2C 硬件概述
I2C(内部集成电路)总线接口用作微控制器和串行 I2C 总线之间的接口。 它提供多主机功能并控制所有 I2C 总线特定的排序、协议、仲裁和时序。 它支持标准模式(Sm,最高 100 kHz)和 Fm 模式(Fm,最高 400 kHz)。
它可用于多种用途,包括 CRC 生成和验证、SMBus(系统管理总线)和 PMBus(电源管理总线)。 根据特定的设备实现,DMA 功能可用于减少 CPU 过载。
2.2 STM32 I2C 主要特性
- 多主控能力:同一个接口可以作为主控或从控
- I2C 主控特性:[时钟生成 - 启动和停止生成]
- I2C 从机特性:[可编程 I2C 地址检测 - 确认 2 个从机地址的双寻址能力 - 停止位检测]
- 7位/10位寻址和广播呼叫的产生和检测
- 支持不同的通讯速度:
- – 标准速度(高达 100 kHz)
- – 速度快(高达 400 kHz)
- 模拟噪声滤波器
- 2 中断向量:
- – 1 成功地址/数据通信的中断
- – 1 错误条件中断
- 可选时钟扩展
- 具有 DMA 功能的 1 字节缓冲区
- 可配置的 PEC(数据包错误检查)生成或验证:
- SMBus 2.0 兼容性
- PMBus 兼容性
3、STM32 I2C 硬件功能
在本节中,我们将深入了解 STM32 I2C 模块硬件、其框图、功能、操作模式和数据接收/传输。
3.1 STM32 I2C框图

正如上面的 I2C 框图中所见,有主移位寄存器、缓冲寄存器和一些控制逻辑单元来处理所有 I2C 事务步骤。 就像地址匹配检查、生成时钟信号、过滤、错误检查等。
3.2 STM32 I2C 模式选择
该接口可以在以下四种模式之一下运行:
- 从属发射机
- 从接收器
- 主发射机
- 主接收器
默认情况下,它在从机模式下运行。 如果发生仲裁丢失或停止生成,接口会在产生 START 条件后自动从从设备切换到主设备,并从主设备切换到从设备,从而允许多主设备功能。 我们将创建一些示例项目,以在上述所有 4 种模式中的每一种模式下操作 I2C 外设。
3.3 STM32 I2C 的从机模式
默认情况下,I2C 接口工作在从机模式。 要从默认从机模式切换到主机模式,需要生成启动条件。 外设输入时钟必须在 I2C_CR2 寄存器中编程,以便生成正确的时序。 外设输入时钟频率必须至少为:
- Sm 模式下为 2 MHz
- Fm 模式下 4 MHz
一旦检测到启动条件,就会从 SDA 线接收地址并将其发送到移位寄存器。 然后与接口的地址进行比较。 在地址接收和清除 ADDR 之后,从器件通过内部移位寄存器从 SDA 线接收字节到 DR 寄存器。 在每个字节之后,如果设置了 ACK 位,接口会生成一个确认脉冲。
如果 RxNE 被设置并且在下一个数据接收结束之前没有读取 DR 寄存器中的数据,则 BTF 位被设置并且接口等待直到 BTF 通过从 I2C_SR1 读取然后从 I2C_DR 寄存器读取被清除, 拉伸 SCL 低。 时钟延长实质上是通过从设备将时钟线 SCL 保持为低电平,以防止 I2C 总线上的任何主设备启动任何新事务,直到该从设备再次释放 SCL。 这就是为什么在从设备中使用时钟拉伸时应该小心的原因。
传输最后一个数据字节后,主机会生成停止条件。 接口检测到这种情况并设置 STOPF 位,如果 ITEVFEN 位被设置,则产生中断。 STOPF 位通过读取 SR1 寄存器然后写入 CR1 寄存器来清除。
3.4 STM32 I2C 主机模式
在主机模式下,I2C 接口启动数据传输并生成时钟信号。 串行数据传输总是以启动条件开始,以停止条件结束。
一旦通过 START 位在总线上产生启动条件,就会选择主模式。 以下是主机模式下所需的序列。
- 在 I2C_CR2 寄存器中编程外设输入时钟以生成正确的时序
- 配置时钟控制寄存器
- 配置上升时间寄存器
- 编程 I2C_CR1 寄存器以启用外设
- 设置 I2C_CR1 寄存器中的 START 位以生成启动条件
外设输入时钟频率必须至少为:
- Sm 模式下为 2 MHz
- Fm 模式下 4 MHz
3.5 STM32 I2C PEC(数据包错误检查)
STMicroelectronics 在 I2C 硬件中实现了 PEC 计算器,以提高通信的可靠性。 PEC 是通过在每个位上串行使用 C(x) = x8 + x2 + x + 1 CRC-8 多项式来计算的。 通过启用 PEC,您可以对所有由硬件完成的大型数据包事务进行自动错误检查,而不会增加软件方面的任何开销。
但是,您还应该知道,如果主设备在任何情况下确实失去了“仲裁”,这都会破坏 PEC。 并且设备将重新设置为从模式并等待仲裁“获胜者”主设备完成其消息。 只有这样,您才能重新开始整个过程。
4、 STM32 I2C 错误条件
I2C 接口硬件可以检测到一些错误情况,以指示硬件级别的一些问题。 通过读取每个错误信号的相应标志位,软件可以轻松检测这些错误情况。 错误条件包括:
- **总线错误 (BERR)**——当 I2C 接口在地址或数据传输期间检测到外部停止或启动条件时,会发生此错误。
- 确认失败 (AF) – 当接口检测到非确认位时会发生此错误。
- 仲裁丢失 (ARLO) – 当 I2C 接口检测到仲裁丢失情况时会发生此错误。
- **溢出/欠载错误 (OVR)**——当时钟延长被禁用且 I2C 接口正在接收数据时,从属模式可能会发生溢出错误。 接口已经接收到一个字节,在接口接收到下一个字节之前,DR 中的数据还没有被读取。 当时钟延长被禁用并且 I2C 接口正在传输数据时,在从模式下可能会发生欠载错误。 在下一个字节的时钟到来之前,接口没有用下一个字节更新 DR。
5、 STM32 I2C 中断
I2C 中断事件连接到同一个中断向量。 因此 I2C 会触发单个中断信号,而不管它的来源如何。 该软件将必须检测到它。 如果相应的启用控制位被设置,这些事件会产生一个中断。

6、 STM32 I2C 主 – 从模式 TX & RX
在本节中,我将列出可以在固件应用程序中处理 I2C 事务的可能方法。
6.1 带轮询的 I2C
在嵌入式软件中做任何事情的第一个也是最简单的方法就是轮询硬件资源,直到它准备好进入程序指令的下一步。 然而,这是效率最低的做事方式,CPU 最终会在“忙等待”状态中浪费大量时间。
发送和接收都是一样的。 只需等到要传输当前字节的数据,然后就可以开始下一个字节,依此类推。
6.2 带中断的 I2C
但是,我们可以启用 I2C 中断并在它完成并准备好由 CPU 服务时发出信号。 对于已发送或已接收的数据。 这节省了大量时间,并且一直是处理此类事件的最佳方式。
然而,在一些“时间关键”的应用程序中,我们需要一切都尽可能地在时间上具有确定性。 中断的一个主要问题是我们无法预料它何时到达或在哪个任务期间到达。 这可能会破坏系统的计时行为。
6.3 带 DMA 的 I2C
为了以最大速度运行,需要向 I2C 馈送数据以进行传输,并且应读取在 Rx 缓冲区上接收到的数据以避免溢出。 为了便于传输,I2C 具有 DMA 功能,可实现简单的请求/确认协议。
DMA 请求是由数据寄存器在发送时变空和数据寄存器在接收时变满而产生的。 使用 DMA 还将使 CPU 免于执行“外设 <-> 内存”的数据传输。 这最终将节省大量时间,并且被认为是处理此外围设备到内存数据传输的最有效方法,反之亦然。
文章来源: https://iotsmart.blog.csdn.net/article/details/123588739