3. MCU I2C 外设架构:模块内部框图与核心寄存器
I2C 外设并非简单的两根线(SCL、SDA)加一个状态机。在 MCU 内部,它由多个功能明确的硬件模块协同工作,理解这些模块的互联关系是进行寄存器级驱动开发的前提。本节将深入剖析 I2C 模块的内部框图、时钟发生器、数据移位寄存器以及控制寄存器概览。
3.1 I2C 模块内部框图
下图展示了典型 MCU 中 I2C 外设的核心架构。数据流从 CPU/内存经总线接口到达数据移位寄存器,再通过 SDA 引脚输出;时钟发生器独立产生 SCL 时钟,并受控制寄存器与状态寄存器协同管理。
3.2 时钟发生器:SCL 频率的硬件实现
时钟发生器是 I2C 外设的“心跳”。它从 MCU 系统时钟(如 AHB 时钟 HCLK 或 APB 时钟 PCLK)分频产生 SCL 时钟。分频系数由控制寄存器中的 CCR(Clock Control Register) 和 TRISE(Rise Time Register) 共同决定。
| 参数 | 标准模式 (100kHz) | 快速模式 (400kHz) | 说明 |
|---|---|---|---|
| SCL 频率 | 100 kHz | 400 kHz | 由 CCR 分频系数决定 |
| CCR 分频公式 | PCLK / (2 × CCR) | PCLK / (2 × CCR) | CCR 为 12 位无符号整数 |
| TRISE 配置 | PCLK 周期数 + 1 | PCLK 周期数 × 300ns | 用于 SCL/SDA 上升沿时间补偿 |
| 占空比 | 50% | 低电平时间可调 | 快速模式下可配置占空比 |
实战要点:配置时钟发生器时,务必先确认 MCU 的 APB 时钟频率。例如,PCLK=48MHz 时,标准模式 CCR=240,快速模式 CCR=60。TRISE 配置错误会导致 SCL 波形畸变,通信失败。
3.3 数据移位寄存器:串行与并行的桥梁
数据移位寄存器(DR)是 I2C 外设中唯一与 CPU 直接交互数据的寄存器。它负责将 CPU 写入的并行数据逐位串行输出到 SDA 线,或将 SDA 线上接收到的串行数据组装成并行字节供 CPU 读取。
- 发送流程:CPU 写 DR → 硬件自动将 8 位数据加载到移位器 → 每个 SCL 时钟周期移出 1 位(MSB 优先)→ 完成后置位 TXE(发送缓冲区空)标志。
- 接收流程:每个 SCL 时钟周期移入 1 位 → 8 位数据组装完成后自动复制到 DR → 置位 RXNE(接收缓冲区非空)标志 → CPU 读 DR。
- 双缓冲机制:DR 内部包含一个 8 位移位寄存器和一个 8 位数据缓冲寄存器。CPU 可以在移位寄存器正在发送/接收时,提前写入下一个字节或读取上一个字节,提高总线利用率。
3.4 控制寄存器概览
I2C 外设的控制寄存器是驱动开发的“操作面板”。下表列出了最核心的寄存器及其功能,后续章节将逐一深入配置。
| 寄存器 | 全称 | 核心位/功能 | 驱动用途 |
|---|---|---|---|
| CR1 | 控制寄存器 1 | PE(外设使能)、START(起始条件)、STOP(停止条件)、ACK(应答使能)、NOSTRETCH(时钟拉伸禁止) | 启动/停止通信、使能应答、控制时钟拉伸 |
| CR2 | 控制寄存器 2 | FREQ(外设时钟频率)、ITBUFEN(缓冲区中断使能)、ITEVTEN(事件中断使能)、ITERREN(错误中断使能) | 配置外设时钟、使能中断类型 |
| OAR1 | 自身地址寄存器 1 | ADD[9:0](7 位或 10 位地址)、ADDMODE(地址模式选择) | 配置从机地址(主模式时可选) |
| DR | 数据寄存器 | DR[7:0](8 位数据) | 发送/接收数据 |
| SR1 | 状态寄存器 1 | SB(起始条件已发送)、ADDR(地址已匹配/已发送)、TXE(发送缓冲区空)、RXNE(接收缓冲区非空)、BTF(字节传输完成)、AF(应答失败)、OVR(溢出错误) | 查询通信状态、判断中断源 |
| SR2 | 状态寄存器 2 | MSL(主/从模式标志)、BUSY(总线忙标志)、GEN CALL(通用呼叫标志) | 判断当前模式、总线占用状态 |
| CCR | 时钟控制寄存器 | CCR[11:0](分频系数)、F/S(快速/标准模式选择)、DUTY(快速模式占空比) | 设置 SCL 频率 |
| TRISE | 上升时间寄存器 | TRISE[5:0](最大上升时间,单位 PCLK 周期) | 补偿 SCL/SDA 上升沿 |
3.5 中断与轮询的硬件基础
I2C 外设的中断和轮询模式共享同一套状态标志位,区别仅在于 CPU 获取标志的方式:
- 轮询模式:CPU 在主循环中循环读取 SR1/SR2,检查 TXE、RXNE、BTF 等标志位,根据标志状态执行相应操作。优点是实现简单,缺点是 CPU 被占用。
- 中断模式:当 SR1 中的标志位被置位且 CR2 中对应的中断使能位被置 1 时,硬件自动向 NVIC(嵌套向量中断控制器)发送中断请求。CPU 暂停当前任务,跳转到 I2C 中断服务函数处理数据。优点是 CPU 利用率高,缺点是代码复杂度增加。
关键区别:中断模式需要配置 CR2 中的 ITBUFEN、ITEVTEN、ITERREN 三个使能位;轮询模式则只需关闭这些中断使能位(写 0),然后循环读取 SR1 即可。两种模式在硬件层面共享同一套数据路径和移位寄存器。
3.6 寄存器配置的通用步骤
无论是中断模式还是轮询模式,I2C 外设的初始化配置都遵循以下固定步骤。后续章节将在此基础上展开中断与轮询的差异化配置。
- 使能 I2C 时钟:在 RCC(复位与时钟控制)寄存器中使能对应 I2C 外设的时钟。
- 配置 GPIO 引脚:将 SCL 和 SDA 引脚设置为开漏输出/输入模式,并使能复用功能。
- 复位 I2C 外设:通过 CR1 的 SWRST 位复位 I2C 模块,确保所有寄存器回到默认状态。
- 配置 CR2:设置 FREQ 位域为 APB 时钟频率(MHz),使能或禁用中断位。
- 配置 CCR:根据目标 SCL 频率计算并写入分频系数,选择标准/快速模式。
- 配置 TRISE:根据 APB 时钟频率和 SCL 模式计算并写入上升时间值。
- 使能外设:设置 CR1 的 PE 位为 1,启动 I2C 模块。
常见错误:步骤 3(复位)容易被忽略。如果 MCU 在上次通信中发生了总线错误(如 SCL 被从机拉低),未复位直接重新配置会导致外设无法正常工作。建议在初始化函数开头执行一次软件复位。