I2C原理与寄存器配置

I2C通信:

1.使能:

使用stm32C8T6中的I2C2

第一步,时钟使能,GPIO使能

请添加图片描述

​ 由图时钟APB1可知,I2C1和2均挂载在时钟1上,

在这里插入图片描述

而GPIO挂载在时钟APB2上,所以这里我们就需要对两个时钟相应的位进行配置,使得I2C和GPIO能够工作。首先我们来使能I2C2:由上述第一张图可知,要使得I2C2工作,我们需要配置APB1时钟的22位,具体代码如下:

RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;

那么,这段代码在单片机中的运行逻辑是什么呢?请看下面这段话:

寄存器分组与指针

想象一下,单片机的内存就像一个巨大的数组,不同的功能(如GPIO控制、时钟配置等)被分配到了这个数组的不同部分。每个这样的“部分”可以看作是一个组,比如RCC组。RCC组有一个起始地址,即基地址0x40021000,它就像是这个组的入口点或起点。

使用指针操作寄存器

当您想要操作RCC组内的某个特定寄存器时,您可以将其视为通过基地址加上偏移量来定位到具体的元素(寄存器)。这与C语言中使用指针访问数组元素非常相似。

假设我们想操作RCC_APB1ENR寄存器,其相对于RCC基地址的偏移量为0x1C,如下图。

在这里插入图片描述

那么我们想要定位到该寄存器所在位置,只需要基地址 + 偏移地址即可。进一步,我们需要访问该寄存器中使能I2C2的具体的位,由上所述我们知道在22位,且知道默认地址位0x00000000.进一步阅读手册,如图:

在这里插入图片描述

该位置1表示I2C2时钟开启,所以便有了以下代码:(其中对于GPIOB的使能在APB2上挂载,方法亦同)

RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
/*其中RCC_APB1ENR_I2C2EN在寄存器库中定义为 ((uint32_t)0x00400000) 转为2进制数,正好位22为1,进行或运算,使得APB1 寄存器22位置1,实现I2C2使能*/
  1. 类比说明
  • 基地址 (0x40021000) 就像是一本书的目录页,告诉你各个章节(功能模块)的开始位置。
  • 偏移量 (0x1C) 是从该章节开始到你感兴趣的段落(特定寄存器)的距离。
    ——————————————————————————————————————————————————————

2.功能框图(各个寄存器之间是如何协同工作的)

在这里插入图片描述
————————————————————————————————————————————————————————

I²C功能框图的工作流程可分为以下几个关键步骤:


1. 通信基础:SDA与SCL控制

  • **SDA(数据线)SCL(时钟线)**是I²C总线的物理层信号。
  • 时钟控制模块管理SCL的时钟频率(由时钟控制寄存器CCR配置),确保主机与从机的同步。
  • 数据控制模块通过SDA线管理数据的发送与接收,包括起始条件、停止条件和数据位的时序。

2. 地址匹配与数据收发

  • 自身地址寄存器双地址寄存器存储从机设备的地址(可配置单/双地址模式)。
  • 当主设备发送地址帧时,比较器将接收到的地址与寄存器中的地址匹配。若匹配成功,从机响应ACK并进入通信状态。
  • 数据寄存器(DATA REGISTER)临时存储待发送或接收的完整字节数据,数据移位寄存器负责将数据逐位移至SDA线(发送)或从SDA线读取(接收)。

3. 错误校验与协议支持

  • 帧错误校验(PEC)计算模块对传输数据生成校验值(如CRC),确保数据完整性。
  • PEC寄存器存储校验值,供发送或接收时对比。若校验失败,会触发错误标志(通过状态寄存器SR1/SR2反映)。

4. 控制与状态管理

  • **控制寄存器(CR1/CR2)**配置I²C模式(主机/从机)、时钟速度、中断使能等。
  • **状态寄存器(SR1/SR2)**实时反映通信状态(如传输完成、地址匹配成功、总线错误等)。
  • 控制逻辑电路根据寄存器的配置和状态标志协调各模块工作,例如触发中断或DMA请求。

5. 中断与DMA

  • 中断模块在关键事件(如数据接收完成、地址匹配、校验错误)时触发中断,通知CPU处理。
  • DMA请求与响应模块支持直接内存访问,用于高效传输连续数据块,减少CPU开销。

6. SMBus扩展功能

  • SMBALERT信号(可选)用于SMBus的报警机制。若禁用SMBus模式,该功能不可用。
  • SMBus模式下,还需遵循额外的协议规则(如超时检测、PEC强制校验等)。

完整工作流程总结

  1. 主机初始化:通过CR1/CR2配置为主机模式,设置时钟频率(CCR)。
  2. 发送起始条件:控制逻辑拉低SDA和SCL,启动通信。
  3. 地址匹配:主机发送目标地址,从机的比较器检查匹配,返回ACK。
  4. 数据传输
    • 发送时,数据从数据寄存器经移位寄存器逐位输出。
    • 接收时,移位寄存器逐位读取SDA数据,存入数据寄存器。
  5. 错误校验:PEC模块计算校验值,与接收端对比,校验结果更新至状态寄存器。
  6. 结束通信:主机发送停止条件,状态寄存器更新传输完成标志,触发中断或DMA完成信号。

关键模块协作

  • 时钟控制确保SCL与数据同步。
  • 控制逻辑协调地址匹配、数据收发、校验和中断/DMA流程。
  • 状态寄存器提供实时反馈,供软件查询或触发后续操作。
    ——————————————————————————————————————————————————————

3. I2C时序(图片取自江科大课件ppt)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
————————————————————————————————————————————————————————
I²C成功通信的完整流程可分为以下几个关键步骤,需严格遵循时序和协议规则:


1. 总线初始化

  • 硬件准备:确保SDA和SCL线均通过上拉电阻连接到电源(典型值:4.7kΩ),保持总线空闲时高电平。
  • 主设备配置
    • 通过**控制寄存器(CR1/CR2)**设置为主机模式。
    • 配置**时钟控制寄存器(CCR)**定义SCL频率(标准模式100kHz,快速模式400kHz)。
  • 从设备配置
    • 将自身地址写入自身地址寄存器(支持7位或10位地址模式)。
    • 使能中断或DMA(若需异步处理数据)。

2. 启动通信

  • 起始条件:主设备拉低SDA线(保持SCL高电平),标志通信开始。
  • 总线仲裁:多主机场景下,需检测总线冲突(SDA与预期输出不一致时放弃控制权)。

3. 发送地址帧

  • 地址格式:发送7位/10位从机地址 + 1位读写方向(0:写,1:读)。
  • 地址匹配
    • 从机通过比较器检测地址是否与自身地址匹配。
    • 匹配成功后,从机拉低SDA(发送ACK信号)确认响应。
  • 无ACK处理:若未收到ACK,主设备需重试或终止通信(超时机制)。

4. 数据传输

  • 数据格式:每个字节(8位)后跟随1位ACK/NACK。
  • 发送数据(主机→从机)
    1. 主机将数据写入数据寄存器
    2. 数据移位寄存器逐位将数据移至SDA线,同步SCL时钟。
    3. 从机读取完8位后,发送ACK(拉低SDA)确认接收成功。
  • 接收数据(主机←从机)
    1. 主机释放SDA线(设为高电平),切换为接收模式。
    2. 从机控制SDA线逐位发送数据,主机通过数据移位寄存器读取。
    3. 主机在第9个时钟周期发送ACK(继续接收)或NACK(终止接收)。

5. 错误校验与恢复

  • PEC校验(可选):若启用帧错误校验,发送方在数据末尾附加PEC值(如CRC8),接收方验证校验值。
  • 状态监控:通过**状态寄存器(SR1/SR2)**检测总线错误(如仲裁丢失、NACK、超时等)。
  • 错误处理:复位总线、重发数据或触发中断报警。

6. 终止通信

  • 停止条件:主设备在SCL高电平时拉高SDA线,标志通信结束。
  • 总线释放:SDA和SCL恢复高电平,总线进入空闲状态。

关键成功条件

  1. 严格时序:起始/停止条件、数据位切换必须在SCL低电平时完成。
  2. ACK响应:每字节传输必须由接收方确认(ACK),否则视为失败。
  3. 地址唯一性:总线上每个从机地址必须唯一,避免冲突。

通信流程

  1. 主机写数据到从机
    START → 发送从机地址(写模式) → ACK → 发送数据字节 → ACK → … → STOP
  2. 主机从从机读取数据
    START → 发送从机地址(读模式) → ACK → 接收数据字节 → 发送ACK/NACK → … → STOP

4. 详细代码

以下是代码配置的详细理由及每一步的作用分析:


1. 开启时钟

RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;   // 使能I2C2时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;  // 使能GPIOB时钟
  • 理由
    • STM32外设需要时钟信号才能操作寄存器。I2C2挂载在APB1总线上,GPIOB挂载在APB2总线上。
    • 若未开启时钟,无法配置I2C或GPIO的寄存器,外设将无法工作。

2. 配置GPIO引脚模式

// 清除CNF位后,配置为复用开漏
GPIOB->CRH &= ~(GPIO_CRH_CNF10 | GPIO_CRH_CNF11);
GPIOB->CRH |= (0b10 << 22) | (0b10 << 26); // CNF=10(复用开漏)
  • 目标:将PB10(SCL)和PB11(SDA)设置为复用开漏模式。
  • 理由
    • 复用功能:I2C需要专用硬件控制SDA和SCL,而非普通GPIO输出。
    • 开漏输出(Open-Drain)
      • 支持I²C总线的“线与”逻辑,避免多个设备同时驱动总线时电平冲突。
      • 允许总线通过外部上拉电阻拉高,确保空闲时SDA和SCL为高电平。

3. 禁用SMBus模式

I2C2->CR1 &= ~I2C_CR1_SMBUS;  // 选择标准I²C模式
  • 理由
    • SMBus(System Management Bus)是I²C的子集,强制要求超时检测、特定电气特性等。
    • 若无需SMBus功能,禁用后可使用更通用的I²C协议,减少协议限制。

4. 设置APB1时钟频率

I2C2->CR2 |= 36 << 0;  // APB1时钟配置为36MHz
  • 理由
    • CR2[5:0](FREQ字段)需填入APB1总线实际频率(单位MHz)。
    • 后续计算CCR和TRISE值时依赖此参数,确保SCL频率和上升时间准确。

5. 选择标准模式(100kHz)

I2C2->CCR &= ~I2C_CCR_FS;  // 标准模式(FS=0)
  • 理由
    • 标准模式:SCL频率为100kHz,适用于大多数低速外设(如EEPROM、传感器)。
    • **快速模式(400kHz)**需设置FS=1,但对总线电容和走线长度要求更高。

6. 配置SCL时钟频率

I2C2->CCR |= 180 << 0;  // CCR=180(标准模式)
  • 公式
    • 标准模式下,CCR = APB1_CLK / (2 * SCL_FREQ)
    • 计算:36MHz / (2 * 100kHz) = 180
  • 作用
    • 定义SCL的占空比(高电平和低电平时间),确保时序符合I²C规范。

7. 设置SCL上升时间

I2C2->TRISE |= 37;  // TRISE=37(标准模式)
  • 公式
    • TRISE = (Max_SCL_Rise_Time / APB1_Period) + 1
    • 计算:
      • APB1周期 = 1/36MHz ≈ 27.78ns。
      • 标准模式最大上升时间要求1μs(1000ns)。
      • 1000ns / 27.78ns ≈ 36 → TRISE = 36 + 1 = 37
  • 作用
    • 控制SCL信号的上升斜率,防止因信号边沿过缓导致时序错误。

8. 使能I2C外设

I2C2->CR1 |= I2C_CR1_PE;  // 使能I2C2
  • 理由
    • STM32外设需在配置完成后显式使能,否则无法工作。
    • 使能后,I2C硬件开始响应总线事件(如起始条件、地址匹配)。

关键配置总结

配置项目标硬件要求
时钟使能激活I2C和GPIO功能必须开启时钟才能操作寄存器
GPIO复用开漏支持总线线与逻辑,避免冲突外部需接上拉电阻(通常4.7kΩ)
标准I²C模式遵循I²C协议,避免SMBus限制无需SMBus功能时适用
APB1时钟配置确保CCR和TRISE计算准确实际APB1频率需与代码一致
标准模式(100kHz)兼容低速设备,降低总线电容影响从设备需支持100kHz
CCR=180生成100kHz的SCL时钟公式依赖APB1频率和模式选择
TRISE=37满足标准模式的最大上升时间要求(1μs)防止信号边沿过缓
使能I2C外设启动I2C硬件功能必须最后一步执行

总结

上述配置通过精确设置时钟、GPIO模式、通信速率和时序参数,确保I2C总线在标准模式下稳定工作。每一步均基于I²C协议规范及STM32硬件特性设计,最终实现可靠的主从设备通信。

完整代码如下:

void Dri_I2C2_Init(void) {
    // 1. 开启时钟
    RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;   // I2C2时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;  // GPIOB时钟

    // 2. 配置GPIOB10(SCL)和PB11(SDA)为复用开漏
    // 清除MODE和CNF位
    GPIOB->CRH &= ~(GPIO_CRH_MODE10 | GPIO_CRH_MODE11 | GPIO_CRH_CNF10 | GPIO_CRH_CNF11);
    // 设置MODE=11(50MHz输出速度),CNF=10(复用开漏)
    GPIOB->CRH |= (0b11 << 20) | (0b11 << 24);   // MODE10和MODE11
    GPIOB->CRH |= (0b10 << 22) | (0b10 << 26);   // CNF10和CNF11

    // 3. 初始化I2C2配置
    I2C2->CR1 &= ~I2C_CR1_SMBUS;     // 禁用SMBus
    I2C2->CR2 = 36;                  // APB1时钟36MHz
    I2C2->CCR = 180;                 // 标准模式100kHz
    I2C2->TRISE = 37;                // 上升时间配置
    I2C2->CR1 |= I2C_CR1_PE;         // 使能I2C
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值