news 2026/6/15 6:26:10

STM32F103 学习笔记-24-I2C-读写EEPROM(第3节)-STM32的I2C框图详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103 学习笔记-24-I2C-读写EEPROM(第3节)-STM32的I2C框图详解

一、I2C 硬件外设概述

1.1 软件模拟 I2C 与硬件 I2C 的区别

I2C 协议的实现有两种方式:软件模拟硬件实现

软件模拟 I2C
  • 原理:直接使用 CPU 控制普通 GPIO 引脚的电平,按照 I2C 协议的时序要求,手动产生起始信号、停止信号、数据位和应答信号。

  • 优点:不占用特定硬件外设,引脚可以任意选择,兼容性好。

  • 缺点:全程占用 CPU 资源,传输速度慢,代码复杂度高。

生活类比:软件模拟 I2C 就像你自己手动包饺子,从擀皮到包馅都要自己一步步来,虽然灵活,但速度慢还累人。

硬件 I2C
  • 原理:STM32 芯片内部集成了专门的 I2C 硬件逻辑电路,我们只需要通过配置寄存器告诉它要做什么,它就会自动完成所有时序操作。

  • 优点:不占用 CPU 资源,传输速度快,代码简洁。

  • 缺点:只能使用特定的复用引脚,部分早期 STM32 芯片存在硬件 BUG。

生活类比:硬件 I2C 就像买了一台全自动包饺子机,你只要把面粉和馅料放进去,按下开关,它就会自动包好饺子,你可以同时去做其他事情。

1.2 STM32F103 的 I2C 资源

STM32F103 系列芯片内置2 个独立的 I2C 外设(I2C1 和 I2C2),完全兼容 I2C 协议标准,主要特性包括:

  • 支持标准模式(100 Kbit/s)和快速模式(400 Kbit/s)

  • 支持7 位10 位设备地址

  • 支持 DMA 数据传输

  • 支持数据包错误校验(PEC)

  • 兼容 SMBus 2.0 协议(主要用于电池管理)

二、I2C 外设硬件架构详解

STM32 的 I2C 外设主要由四个核心模块​ 组成:

2.1 通讯引脚模块

I2C 外设的信号通过特定的 GPIO 引脚引出,STM32F103 的 I2C 引脚映射如下:

I2C 外设默认引脚重映射引脚备注
I2C1

SCL: PB6

SDA: PB7

SCL: PB8

SDA: PB9

需启用 AFIO 重映射功能
调用GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE)
I2C2

SCL: PB10

SDA: PB11

不支持引脚重映射

重要说明:I2C 的 SCL 和 SDA 引脚必须配置为复用开漏输出模式,并且在硬件上必须连接上拉电阻(通常为 4.7 KΩ)。

为什么需要开漏输出?

I2C 是总线结构,多个设备连接在同一根线上。开漏输出可以实现"线与"功能:任何一个设备拉低总线,整个总线都会变成低电平;当所有设备都输出高阻态时,总线由上拉电阻拉为高电平。如果使用推挽输出,当两个设备同时输出不同电平时,会造成短路损坏芯片。

2.2 时钟控制逻辑

时钟控制逻辑负责产生 I2C 总线的 SCL 时钟信号,决定了通讯速率。核心是时钟控制寄存器 CCR(Clock Control Register)。

CCR 寄存器是一个 16 位寄存器,关键位定义如下:

  • 位 15(F/S):快速模式选择位

    • 0:标准模式(100 KHz)

    • 1:快速模式(400 KHz)

  • 位 14(DUTY):快速模式下的占空比选择位

    • 0:Tlow/Thigh = 2

    • 1:Tlow/Thigh = 16/9

  • 位 11:0(CCR[11:0]):时钟分频因子,用于计算 SCL 时钟周期

2.3 数据控制逻辑

数据控制逻辑负责处理 SDA 线上的数据收发,主要包含以下寄存器:

1. 数据寄存器 DR(Data Register)
  • 8 位数据寄存器,用于缓存要发送或刚接收的数据

  • 发送时:CPU 将数据写入 DR,硬件自动将其加载到移位寄存器

  • 接收时:移位寄存器接收到一个完整字节后,自动将数据存入 DR

2. 数据移位寄存器
  • 负责将并行数据转换为串行数据发送,或将串行数据转换为并行数据接收

  • I2C 协议采用高位先行(MSB First)​ 的传输方式

3. 自身地址寄存器 OAR1/OAR2
  • 用于配置 STM32 作为 I2C 从机时的设备地址

  • OAR1 支持 7 位或 10 位地址

  • OAR2 支持第二个 7 位地址,使 STM32 可以同时响应两个不同的从机地址

4. 比较器
  • 当 STM32 作为从机时,自动将接收到的地址与 OAR1/OAR2 中的地址进行比较

  • 如果匹配,则产生应答信号,准备接收或发送数据

5. PEC 寄存器
  • 用于数据包错误校验,主要在 SMBus 协议中使用,普通 I2C 通讯很少用到

2.4 整体控制逻辑

整体控制逻辑负责协调整个 I2C 外设的工作,主要包含控制寄存器和状态寄存器。

1. 控制寄存器 CR1(Control Register 1)

关键位定义:

  • 位 0(PE):I2C 外设使能位

    • 0:禁用 I2C 外设

    • 1:使能 I2C 外设

  • 位 8(START):起始信号生成位

    • 写 1:硬件自动产生起始信号

  • 位 9(STOP):停止信号生成位

    • 写 1:硬件自动产生停止信号

  • 位 10(ACK):应答使能位

    • 0:接收到数据后不产生应答

    • 1:接收到数据后自动产生应答

2. 状态寄存器 SR1(Status Register 1)

关键位定义:

  • 位 0(SB):起始位已发送标志

    • 1:起始信号已成功发送到总线

  • 位 1(ADDR):地址已发送标志

    • 1:从机地址已成功发送并收到应答

  • 位 2(BTF):字节传输完成标志

    • 1:一个字节的数据已成功传输

  • 位 6(TXE):发送数据寄存器为空标志

    • 1:DR 寄存器中的数据已被加载到移位寄存器,可以写入下一个数据

  • 位 7(RXNE):接收数据寄存器非空标志

    • 1:移位寄存器已接收到一个完整字节,可以从 DR 中读取数据

  • 位 10(AF):应答失败标志

    • 1:发送数据后没有收到从机的应答信号

3. 状态寄存器 SR2(Status Register 2)

关键位定义:

  • 位 1(BUSY):总线忙标志

    • 1:I2C 总线正在被占用

    • 0:I2C 总线空闲

三、I2C 时钟频率计算

I2C 外设挂载在APB1 总线上,默认时钟频率为36 MHz。SCL 时钟频率由 CCR 寄存器的值决定,不同模式下计算公式不同。

3.1 标准模式(100 KHz)

标准模式下,SCL 的高电平和低电平时间相等:

Thigh = CCR * TPCLK1 Tlow = CCR * TPCLK1 TSCL = Thigh + Tlow = 2 * CCR * TPCLK1

其中:

  • TPCLK1 = 1 / PCLK1 = 1 / 36000000 ≈ 27.78 ns

  • TSCL = 1 / 目标频率 = 1 / 100000 = 10000 ns

代入计算:

10000 = 2 * CCR * 27.78 CCR = 10000 / (2 * 27.78) ≈ 180

因此,标准模式下 CCR 寄存器应设置为180

3.2 快速模式(400 KHz)

快速模式下有两种占空比可选:

占空比 2:1(DUTY=0)
Thigh = CCR * TPCLK1 Tlow = 2 * CCR * TPCLK1 TSCL = 3 * CCR * TPCLK1

目标频率 400 KHz,TSCL = 1 / 400000 = 2500 ns:

2500 = 3 * CCR * 27.78 CCR = 2500 / (3 * 27.78) ≈ 30
占空比 16:9(DUTY=1)
Thigh = 9 * CCR * TPCLK1 Tlow = 16 * CCR * TPCLK1 TSCL = 25 * CCR * TPCLK1

代入计算:

2500 = 25 * CCR * 27.78 CCR = 2500 / (25 * 27.78) ≈ 3.6 → 取整为 4

注意:标准库会根据我们设置的目标波特率自动计算 CCR 的值,不需要手动计算。

四、标准库初始化流程

4.1 初始化步骤

  1. 开启 I2C 外设和对应 GPIO 的时钟

  2. 配置 GPIO 为复用开漏输出模式

  3. 配置 I2C 的工作参数

  4. 使能 I2C 外设

4.2 初始化代码示例

// bsp_i2c.c #include "bsp_i2c.h" /** * @brief I2C 初始化函数 * @param 无 * @retval 无 */ void I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; // 1. 开启时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启 GPIOB 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 开启 I2C1 时钟 // 2. 配置 GPIO 为复用开漏输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // I2C1_SCL(PB6) 和 I2C1_SDA(PB7) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏输出 GPIO_Init(GPIOB, &GPIO_InitStructure); // 3. 配置 I2C 参数 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C 模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 快速模式下占空比 2:1 I2C_InitStructure.I2C_OwnAddress1 = 0x0A; // STM32 作为从机时的地址 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 使能自动应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 位地址模式 I2C_InitStructure.I2C_ClockSpeed = 400000; // 通讯速率 400 KHz I2C_Init(I2C1, &I2C_InitStructure); // 4. 使能 I2C 外设 I2C_Cmd(I2C1, ENABLE); }

4.3 I2C_InitTypeDef 结构体成员详解

成员

描述

可选值

I2C_Mode

工作模式

I2C_Mode_I2C(标准 I2C 模式)
I2C_Mode_SMBusHost(SMBus 主机模式)
I2C_Mode_SMBusDevice(SMBus 从机模式)

I2C_DutyCycle

快速模式下的占空比

I2C_DutyCycle_2(Tlow/Thigh=2)
I2C_DutyCycle_16_9(Tlow/Thigh=16/9)

I2C_OwnAddress1

STM32 作为从机时的自身地址

7 位或 10 位地址

I2C_Ack

应答使能

I2C_Ack_Enable(使能自动应答)
I2C_Ack_Disable(禁用自动应答)

I2C_AcknowledgedAddress

地址长度

I2C_AcknowledgedAddress_7bit(7 位地址)
I2C_AcknowledgedAddress_10bit(10 位地址)

I2C_ClockSpeed

通讯速率

最大 400000(400 KHz)

五、避坑指南

  1. GPIO 模式配置错误

    • I2C 的 SCL 和 SDA 引脚必须配置为复用开漏输出,不能是推挽输出或普通输入。

    • 硬件上必须连接上拉电阻,否则总线会一直处于低电平。

  2. 时钟频率配置错误

    • I2C 外设挂载在 APB1 总线上,最大时钟频率为 36 MHz,不要使用 APB2 的 72 MHz 进行计算。

    • 快速模式下,确保从设备支持 400 KHz 速率,否则会出现通讯错误。

  3. 总线忙死锁问题

    • 如果程序异常退出,可能导致 I2C 总线被锁定在忙状态。

    • 解决方法:在初始化时先模拟产生几个时钟脉冲,释放总线。

  4. 硬件 I2C 的 BUG 问题

    • 部分 STM32F103 芯片的硬件 I2C 在某些情况下会出现死锁或数据错误。

    • 对于对稳定性要求极高的项目,可以考虑使用软件模拟 I2C。

    • 初学者建议先学习硬件 I2C 的原理,了解协议的底层机制。

参考出处

  1. 《零死角玩转 STM32F103 - 指南者》第 24 章 I2C - 读写 EEPROM

  2. STM32F10x 中文参考手册 第 24 章 I2C 接口

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 6:25:53

珠宝翡翠行业GEO优化公司找谁靠谱一个成都翡翠老板的真实选择之路

写在前面最近不少珠宝翡翠从业者在讨论同一个问题现在抖音越来越难做了听说GEO优化很火但市面上公司那么多到底该选哪家这已经成为行业的普遍困惑本文通过一个真实案例来深入分析成都锦江区一位经营翡翠玉石的王总是如何实现从不信任到真香的转变珠宝翡翠行业的获客困境先说说这…

作者头像 李华
网站建设 2026/6/15 6:24:31

别再手动改sshd_config了!一招搞定ganymed-ssh2连接Linux的算法协商失败

批量修复SSH算法协商失败:从单机到集群的工程化解决方案当你在凌晨三点被告警短信惊醒,发现自动化部署脚本因为SSH连接失败而全线崩溃时,那种绝望感每个运维工程师都深有体会。特别是当错误信息显示"Cannot negotiate, proposals do not…

作者头像 李华