I2C总线详细介绍
- 人工智能
- 2025-09-12 14:39:02

目录 I2C 总线介绍1. I2C 的原理(1) 双线通信(2) 主从结构(3) 多设备通信(4) 硬件连接 2. I2C 的特性(1) 双向通信(2) 多主设备(3) 速度支持(4) 硬件简单(5) 地址区分 3. I2C 的协议(1) 起始条件(Start Condition)(2) 地址传输(3) 数据传输(4) 应答信号(ACK/NACK)(5) 停止条件(Stop Condition) 4. 配置与使用(1) 配置 I2C 外设使能 I2C 外设时钟配置 GPIO 为 I2C 功能配置 I2C 参数 (2) 发送数据(3) 接收数据 5. 实例代码6. 常见问题(1) 总线冲突(2) 上拉电阻配置(3) 从设备应答丢失(4) 时钟速度设置 7. 应用场景(1) 传感器数据采集(2) EEPROM 存储(3) 显示屏控制(4) 电机控制(5) 无线模块 8. 总结
I2C 总线介绍
I2C(Inter-Integrated Circuit,集成电路总线) 是一种串行通信协议,广泛应用于嵌入式系统和电子设备中,用于在微控制器与外围设备(如传感器、EEPROM、显示屏等)之间进行低速数据通信。I2C 总线因其简单、高效和灵活的特点,成为许多设备的标配通信接口。
1. I2C 的原理 (1) 双线通信
I2C 总线由两根信号线组成:
SCL(Serial Clock Line,时钟线):由主设备(Master)产生时钟信号,用于同步数据传输。SDA(Serial Data Line,数据线):用于主设备与从设备(Slave)之间的双向数据传输。 (2) 主从结构 主设备(Master):控制总线的时钟和启动/停止数据传输。从设备(Slave):响应主设备的请求。 (3) 多设备通信I2C 总线支持多个主设备和从设备连接到同一条总线,通过地址区分不同的从设备。
(4) 硬件连接 I2C 总线通过上拉电阻(通常为 4.7 kΩ)连接到电源,确保空闲状态下 SDA 和 SCL 线为高电平。所有设备的 SDA 和 SCL 线分别连接到同一条总线。2. I2C 的特性 (1) 双向通信 数据线 SDA 支持双向数据传输,主设备和从设备都可以发送和接收数据。 (2) 多主设备 I2C 总线支持多个主设备同时工作,但需要总线仲裁机制避免冲突。 (3) 速度支持 标准模式:<= 100 kbps。快速模式:<= 400 kbps。高速模式:<= 3.4 Mbps。超快速模式:<= 5 Mbps(部分设备支持)。 (4) 硬件简单 只需两根信号线,降低了电路设计的复杂性。 (5) 地址区分 每个从设备都有唯一的 7 位或 10 位地址,主设备通过地址选择从设备。
3. I2C 的协议 (1) 起始条件(Start Condition) 主设备通过拉低 SDA 线,然后在 SCL 线拉低时发送起始信号。 (2) 地址传输 主设备发送 7 位或 10 位从设备地址,后面跟随读/写标志位(R/W): 0:写操作。1:读操作。 (3) 数据传输 在 SCL 的高电平期间,SDA 上的数据必须保持稳定。每个字节(8 位)传输后,接收方需要发送一个应答位(ACK)或非应答位(NACK)。 (4) 应答信号(ACK/NACK) ACK(应答):接收方在第 9 个时钟周期拉低 SDA 线,表示成功接收数据。NACK(非应答):接收方在第 9 个时钟周期保持 SDA 线高电平,表示接收失败或不需要更多数据。 (5) 停止条件(Stop Condition) 主设备在拉高 SCL 线后,再拉高 SDA 线,发送停止信号。
4. 配置与使用 (1) 配置 I2C 外设
在 STM32 微控制器中,I2C 外设的配置通常基于 HAL 库。
使能 I2C 外设时钟 __HAL_RCC_I2C1_CLK_ENABLE(); // 使能 I2C1 外设时钟 配置 GPIO 为 I2C 功能 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; // I2C1 的 SCL 和 SDA 引脚 GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 开漏输出 GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; // 复用功能 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉/下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // GPIOB 配置 配置 I2C 参数 I2C_HandleTypeDef hi2c1; hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; // 时钟频率 100 kHz hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 时钟占空比 hi2c1.Init.OwnAddress1 = 0x00; // 主设备地址(不需要) hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7 位地址模式 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 禁用双地址模式 hi2c1.Init.OwnAddress2 = 0x00; // 从设备地址(不需要) hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 禁用广播模式 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 禁用不拉伸模式 HAL_I2C_Init(&hi2c1); // 初始化 I2C (2) 发送数据 HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)0x50 << 1, data, sizeof(data), HAL_MAX_DELAY); 参数说明: 0x50:从设备的 7 位地址。data:要发送的数据。HAL_MAX_DELAY:阻塞等待,直到传输完成。 (3) 接收数据 HAL_I2C_Master_Receive(&hi2c1, (uint16_t)0x50 << 1, data, sizeof(data), HAL_MAX_DELAY); 参数说明: 0x50:从设备的 7 位地址。data:接收数据的缓冲区。HAL_MAX_DELAY:阻塞等待,直到接收完成。5. 实例代码
以下是一个完整的示例,配置 I2C1 并与从设备 0x50 通信:
void I2C_Config(void) { // 使能 I2C1 外设时钟 __HAL_RCC_I2C1_CLK_ENABLE(); // 配置 GPIO 为 I2C 功能 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; // I2C1 的 SCL 和 SDA 引脚 GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 开漏输出 GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; // 复用功能 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉/下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // GPIOB 配置 // 配置 I2C 参数 I2C_HandleTypeDef hi2c1; hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; // 时钟频率 100 kHz hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 时钟占空比 hi2c1.Init.OwnAddress1 = 0x00; // 主设备地址(不需要) hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7 位地址模式 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 禁用双地址模式 hi2c1.Init.OwnAddress2 = 0x00; // 从设备地址(不需要) hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 禁用广播模式 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 禁用不拉伸模式 HAL_I2C_Init(&hi2c1); // 初始化 I2C // 发送数据到从设备 0x50 uint8_t data[] = {0x01, 0x02, 0x03}; HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)0x50 << 1, data, sizeof(data), HAL_MAX_DELAY); }6. 常见问题 (1) 总线冲突 如果多个主设备同时尝试控制总线,可能会导致总线冲突。解决方法:硬件设计时避免多个主设备同时操作。 (2) 上拉电阻配置 I2C 总线需要外部上拉电阻,通常为 4.7 kΩ。检查电路设计是否正确接线。 (3) 从设备应答丢失 可能是从设备地址错误或设备未上电。解决方法:检查从设备地址和供电情况。 (4) 时钟速度设置 根据设备的要求设置合适的时钟速度。例如,EEPROM 通常支持 100 kHz,而某些传感器可能支持 400 kHz。
7. 应用场景 (1) 传感器数据采集 如温度传感器(LM75)、加速度传感器(MPU6050)等。 (2) EEPROM 存储 如 24C02 EEPROM,用于存储设备配置信息。 (3) 显示屏控制 如 OLED 显示屏(SSD1306)通过 I2C 接口进行通信。 (4) 电机控制 如步进电机驱动器(L298N)通过 I2C 总线进行控制。 (5) 无线模块 如蓝牙模块(HM-10)通过 I2C 与主控通信。
8. 总结
I2C 是一种简单高效的串行通信协议,适用于嵌入式系统中的多设备通信。通过配置 STM32 的 I2C 外设,可以实现与各种外围设备的低速数据传输。其主要特点包括:
双线通信:仅需 SCL 和 SDA 两根信号线。主从结构:支持主设备与从设备通信。多设备支持:通过地址区分不同的从设备。硬件简单:仅需上拉电阻,设计成本低。I2C 的应用场景广泛,从传感器数据采集到显示屏控制,再到电机驱动和无线通信,都可以通过 I2C 实现高效可靠的通信。