1. 项目概述
I2C通讯作为嵌入式开发中最常用的总线协议之一,在STM32开发中扮演着重要角色。作为一名有十年嵌入式开发经验的工程师,我经常遇到初学者对I2C协议理解不透彻导致的各种通讯问题。这篇文章将从实际工程角度,带你深入理解I2C协议在STM32上的实现原理和应用技巧。
I2C(Inter-Integrated Circuit)是一种简单、高效的双向二线制同步串行总线,由Philips公司(现NXP)在1980年代开发。它只需要两根信号线(SDA和SCL)就能实现多设备间的通讯,在传感器、EEPROM、RTC等外设连接中广泛应用。STM32系列MCU都内置了硬件I2C控制器,大大简化了开发难度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. I2C协议基础解析
2.1 I2C物理层特性
I2C总线由两根线组成:
- SCL(Serial Clock):时钟线,由主设备产生
- SDA(Serial Data):数据线,双向传输
这两根线都需要通过上拉电阻连接到VCC(通常4.7kΩ)。这种开漏输出结构使得I2C具有"线与"特性,即任何设备拉低线路都会使整条线保持低电平。
在实际工程中,上拉电阻的选择很关键:
- 阻值过小:增加功耗,可能超出IO口驱动能力
- 阻值过大:上升沿变缓,可能影响高速通讯
- 常用范围:2.2kΩ-10kΩ,根据总线长度和速度调整
2.2 I2C协议帧结构
一个完整的I2C通讯包含以下几个部分:
- 起始条件(START):SCL高电平时SDA从高到低跳变
- 从机地址(7位或10位)+读写位(R/W#)
- 应答位(ACK/NACK)
- 数据字节(8位)
- 停止条件(STOP):SCL高电平时SDA从低到高跳变
注意:STM32的硬件I2C控制器会自动处理START/STOP条件和ACK/NACK,但理解这些底层时序对调试很有帮助。
2.3 I2C地址分配
I2C设备采用7位或10位地址寻址。7位地址是最常用的形式,理论上可以连接128个设备(实际很多地址被保留)。地址分配规则:
- 前4位通常由厂商固定
- 后3位可通过硬件引脚配置
- 地址0x00-0x07和0x78-0x7F为保留地址
常见设备地址示例:
- AT24Cxx EEPROM:0x50-0x57
- PCF8574 IO扩展:0x20-0x27
- BMP280气压传感器:0x76或0x77
3. STM32硬件I2C配置
3.1 时钟配置
STM32的I2C时钟源来自APB1总线(低速外设总线),配置步骤:
- 在RCC中使能I2C时钟
- 配置GPIO为复用开漏模式
- 设置I2C时钟频率(标准模式100kHz,快速模式400kHz)
- 配置I2C时序寄存器(关键!)
以STM32F103配置标准模式为例:
c复制// 使能I2C1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 配置GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // SCL PB6, SDA PB7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// I2C配置
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 主模式设为0
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000; // 100kHz
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENAB
