I3C 协议的介绍以及 在sensor 传感器中的应用和实战

本文将详细介绍I3C协议的基础概念及其在传感器领域的实际应用案例。通过本篇文章,读者可以了解到I3C协议如何提高传感器的数据传输效率及降低功耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     最近会更新一篇 关于 I3C 协议的介绍以及 在sensor 传感器中的应用和实战 的文章, 敬请期待。 
<think>我们正在讨论I2C通信的实际数据传输流程。根据引用[1][2],I2C是一种同步、串行、半双工通信协议,适用于短距离、低速设备间通信。下面将详细展示I2C通信在实际应用中的数据传输流程,包括主机发送主机接收两个主要场景。 ### I2C数据传输基本流程 I2C通信由主机(通常是微控制器)发起控制,传输过程遵循严格的时序。每个数据包传输包含以下阶段: 1. **起始条件(Start Condition)** 2. **从机地址传输(Slave Address Transmission)** 3. **读写位(Read/Write Bit)** 4. **应答(ACK/NACK)** 5. **数据传输(Data Transmission)** 6. **停止条件(Stop Condition)** 下面以主机向从机写入数据(主机发送模式)主机从从机读取数据(主机接收模式)为例详细说明。 --- ### 场景1:主机向从机写入数据(主机发送模式) 假设主机需要向地址为`0x50`的EEPROM写入一个字节数据`0xAB`。流程如下: 1. **起始条件(S)** 主机拉低SDA线(数据线)的同时保持SCL(时钟线)为高电平,产生起始信号[^1][^2]。 $$SDA \downarrow \quad while \quad SCL = 1$$ 2. **发送从机地址 + 写位** 主机发送7位从机地址(`0x50`)1位写标志(`0`表示写操作): - 地址字节 = `0b10100000`(`0xA0`,其中高7位`1010000`是地址`0x50`,最低位`0`表示写) - 主机通过SCL时钟脉冲逐位发送该字节(MSB优先) 3. **从机应答(ACK)** 从机在第9个时钟周期拉低SDA线表示应答(ACK),主机检测到ACK后继续传输。 4. **发送数据字节** 主机发送待写入的数据字节(如`0xAB`): - 数据字节 = `0b10101011` - 同样通过8个SCL时钟脉冲逐位发送 5. **从机应答(ACK)** 从机再次在第9个时钟周期拉低SDA线表示成功接收数据。 6. **停止条件(P)** 主机在SCL高电平期间释放SDA线(拉高),产生停止信号[^1][^2]。 $$SDA \uparrow \quad while \quad SCL = 1$$ ```mermaid timeline title 主机写入流程(S:起始,P:停止) section 主机发送 S : 起始信号 地址+写位(0xA0) : 7位地址+1位写标志 ACK : 从机应答 数据(0xAB) : 8位数据 ACK : 从机应答 P : 停止信号 ``` --- ### 场景2:主机从从机读取数据(主机接收模式) 假设主机需要从地址为`0x50`的EEPROM读取一个字节数据。流程如下: 1. **起始条件(S)** 同写入模式。 2. **发送从机地址 + 读位** 主机发送7位从机地址(`0x50`)1位读标志(`1`表示读操作): - 地址字节 = `0b10100001`(`0xA1`) 3. **从机应答(ACK)** 从机拉低SDA线应答。 4. **接收数据字节** 主机释放SDA线控制权(设为高阻态),从机控制SDA线逐位发送数据(如`0xCD`): - 主机在SCL高电平时采样SDA线 - 8个时钟周期后完成一个字节接收 5. **主机应答(NACK)** 主机在第9个时钟周期拉高SDA线(NACK),表示这是最后一个字节[^1]。 6. **停止条件(P)** 主机产生停止信号。 ```mermaid timeline title 主机读取流程 section 主机发送 S : 起始信号 地址+读位(0xA1) : 7位地址+1位读标志 ACK : 从机应答 section 主机接收 数据(0xCD) : 从机发送8位数据 NACK : 主机不应答(结束读取) P : 停止信号 ``` --- ### 关键时序参数 实际应用中需严格遵循I2C时序规范[^1]: | **参数** | **典型值** | **说明** | |----------------|------------|-------------------------------| | $t_{SU;STA}$ | 4.7 μs | 起始条件建立时间 | | $t_{HD;STA}$ | 4.0 μs | 起始条件保持时间 | | $t_{SU;DAT}$ | 250 ns | 数据建立时间(SCL↑前) | | $t_{HD;DAT}$ | 0 ns | 数据保持时间(SCL↓后) | | $t_{SU;STO}$ | 4.0 μs | 停止条件建立时间 | > ⚠️ **注意事项** > 1. 主机在SCL低电平时改变SDA数据线,在SCL高电平时采样SDA线[^2]。 > 2. 从机可通过拉低SCL线实现时钟延展(Clock Stretching),以延长处理时间。 --- ### 实战案例:STM32读写EEPROM 以STM32F4系列MCU通过I2C1接口读写AT24C02 EEPROM为例: 1. **初始化配置** - 设置SCL引脚(PB6)SDA引脚(PB7)为开漏输出模式 - 配置I2C时钟频率为100 kHz(标准模式) - 使能I2C外设 2. **写入单字节流程(伪代码)** ```c void I2C_WriteByte(uint8_t devAddr, uint8_t data) { I2C_GenerateSTART(I2C1, ENABLE); // 发送起始信号 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Transmitter); // 发送地址+写位 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, data); // 发送数据 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); // 发送停止信号 } ``` 3. **读取单字节流程(伪代码)** ```c uint8_t I2C_ReadByte(uint8_t devAddr) { I2C_GenerateSTART(I2C1, ENABLE); // 起始信号 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Receiver); // 地址+读位 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); I2C_AcknowledgeConfig(I2C1, DISABLE); // 准备接收最后一个字节(发NACK) while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t data = I2C_ReceiveData(I2C1); // 读取数据 I2C_GenerateSTOP(I2C1, ENABLE); // 停止信号 return data; } ``` --- §§相关问题§§ 1. I2C通信中如何实现多主机仲裁? 2. 为什么I2C总线需要上拉电阻?如何计算其阻值? 3. I2C与SPI协议在传输效率上有何差异?</think>以下详细解析I2C通信在实际应用中的数据传输流程,结合硬件操作软件实现,重点展示主机与从机之间的交互过程: --- ### I2C数据传输全流程(以STM32读取温湿度传感器为例) #### **1. 初始化阶段** ```c // STM32硬件初始化代码 void I2C_Init() { GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; // 配置SCL(PB6)SDA(PB7)为开漏输出模式 GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 开漏输出[^1] GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉电阻(4.7kΩ) HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // I2C1外设配置 I2C_InitStruct.ClockSpeed = 100000; // 100kHz标准模式 I2C_InitStruct.DutyCycle = I2C_DUTYCYCLE_2; I2C_InitStruct.OwnAddress1 = 0; // 主机模式 I2C_InitStruct.AddressingMode = I2C_ADDRESSINGMODE_7BIT; HAL_I2C_Init(&hi2c1); // 初始化I2C1 } ``` **硬件要求**: - 上拉电阻:$R_{pull-up} = \frac{V_{DD}}{3mA}$(典型值3-10kΩ) - 总线电容:$C_{bus} < 400pF$(标准模式) --- #### **2. 主机发送请求流程(读取SHT30温湿度传感器)** ##### **步骤1: 起始条件(START)** - **硬件动作**:SCL高电平时SDA从高→低跳变 - **代码实现**: ```c HAL_I2C_Master_Transmit(&hi2c1, 0x44<<1, cmd, 2, 100); // 0x44为SHT30地址 ``` **时序要求**: $$t_{HD;STA} > 4.0\mu s \quad (\text{起始条件保持时间})$$ ##### **步骤2: 发送从机地址+写位** - **帧结构**: ``` ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ 1 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ 0 │ W │ → W=0(写操作) └───┴───┴───┴───┴───┴───┴───┴───┴───┘ MSB LSB R/W ``` - **地址计算**:7位地址`0x44`左移1位 + R/W位(0=写) ##### **步骤3: 从机应答(ACK)** - **硬件行为**:从机在第9个时钟周期拉低SDA - **超时处理**:若未收到ACK,主机触发Timeout错误 ##### **步骤4: 发送命令字** - **示例命令**:`0x2C06`(高精度测量命令) - **数据格式**: ```c uint8_t cmd[2] = {0x2C, 0x06}; // 测量命令 ``` ##### **步骤5: 停止条件(STOP)** - **硬件动作**:SCL高电平时SDA从低→高跳变 - **时序约束**: $$t_{SU;STO} > 4.7\mu s \quad (\text{停止条件建立时间})$$ --- #### **3. 主机接收数据流程** ##### **步骤1: 重复起始条件(Repeated START)** ```c HAL_I2C_Master_Receive(&hi2c1, 0x44<<1 | 0x01, data, 6, 100); // R/W=1(读) ``` ##### **步骤2: 发送从机地址+读位** - 地址帧:`0x44 << 1 | 0x01` → `0x89` (二进制`10001001`) ##### **步骤3: 接收数据帧(以温湿度数据为例)** - **数据结构**(6字节): ``` [温度MSB][温度LSB][CRC1][湿度MSB][湿度LSB][CRC2] ``` - **数据采样**:主机在SCL高电平时读取SDA $$t_{SU;DAT} > 250ns \quad (\text{数据建立时间})$$ ##### **步骤4: 主机应答机制** - **ACK**:前5个字节后发送ACK(SDA=0) - **NACK**:最后一个字节后发送NACK(SDA=1) ##### **步骤5: 停止条件** ```c // HAL库自动生成STOP信号 ``` --- ### 关键时序图示 ```mermaid sequenceDiagram participant Host as 主机(MCU) participant Sensor as 从机(SHT30) Note over Host: 1. 初始化I2C总线 Host->>Sensor: START条件 Host->>Sensor: 地址帧(0x44 + W) Sensor-->>Host: ACK Host->>Sensor: 命令字(0x2C06) Sensor-->>Host: ACK Host->>Sensor: STOP条件 Note over Host: 等待15ms测量 Host->>Sensor: START条件 Host->>Sensor: 地址帧(0x44 + R) Sensor-->>Host: ACK Sensor->>Host: 温度MSB Host-->>Sensor: ACK Sensor->>Host: 温度LSB Host-->>Sensor: ACK Sensor->>Host: CRC1 Host-->>Sensor: ACK Sensor->>Host: 湿度MSB Host-->>Sensor: ACK Sensor->>Host: 湿度LSB Host-->>Sensor: ACK Sensor->>Host: CRC2 Host-->>Sensor: NACK Host->>Sensor: STOP条件 ``` --- ### 错误处理机制 1. **总线冲突检测**: - 主机在发送时持续监测SDA线 - 若检测到实际电平与预期不符,立即终止传输 2. **时钟同步**: - 当从机需要更多处理时间时,可拉低SCL(时钟延展) $$t_{LOW;EXT} \leq 25ms \quad (\text{最大延展时间})$$ 3. **CRC校验**: ```c if(Verify_CRC(data[2], data[0], data[1]) != SUCCESS) { // 触发重传机制 } ``` --- ### 协议特性对比 | **特性** | I2C | SPI | UART | |----------------|------------------|-------------------|------------------| | **线数** | 2 (SDA+SCL) | 4 (MOSI+MISO+SCS+SCLK) | 2 (TX+RX) | | **速度** | 100kbps-3.4Mbps | 可达50Mbps | 通常≤115.2kbps | | **寻址方式** | 软件寻址 | 硬件片选 | 点对点 | | **典型应用** | 传感器/EEPROM | Flash存储器 | 调试接口 | > 注:I2C在多点连接功耗敏感场景优势明显[^2] ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值