【知识分享】IIC协议详解
一、简介
I²C(Inter-Integrated Circuit,集成电路总线,也可以写成IIC)是一种由飞利浦公司开发的双向二线制串行通信总线,只通过一根串行数据线(SDA)和一根串行时钟线(SCL),就能让主板、外围设备(如传感器、存储器)等芯片之间实现数据传输,具有硬件结构简单、占用引脚少、支持多设备挂载和热插拔等特点,在嵌入式系统中应用广泛。
二、发展历史
起源与专利阶段(1982 年)
由荷兰飞利浦(Philips)公司于 1982 年开发,最初用于连接主板与外围芯片(如 EEPROM、传感器),解决多设备通信时引脚占用问题。
1980 年代至 2000 年,I²C 作为飞利浦专利技术,广泛应用于消费电子(如电视机、音响)和嵌入式系统。
标准化与开放(2000 年后)
2006 年,飞利浦将 I²C 技术贡献给 JEDEC(固态技术协会),成为开放式标准(JESD42-B),推动其在物联网、穿戴设备等领域普及。
技术迭代:从最初的标准模式(100kbps)发展出快速模式(400kbps)、高速模式(3.4Mbps)及超高速模式(5Mbps),满足不同场景需求。
三、内容详解
3.1 物理层特性
双线结构:
SDA(串行数据线):传输数据,双向通信。
SCL(串行时钟线):主机提供时钟信号,同步数据传输。
电气特性:
采用开漏输出,需外接上拉电阻(通常 4.7kΩ),默认高电平。
工作电压兼容 3.3V/5V 系统,传输距离通常 < 1 米(受电容负载限制)。
3.2 数据链路层协议
3.2.1 空闲状态
SCL与SDA均为高电平。
3.2.2 起始与结束
起始:SCL为高电平时,SDA由高变低,表示开始传输;
结束:SCL为高电平时,SDA由低变高,表示结束传输。
3.2.3 收发数据
从上文也可得知,正常收发数据时,SDA要翻只能在SCL为低的时候进行。当需要发送一个字节的数据时,先拉低SCL,根据要发送的第一位数据(高位优先)拉高/拉低SDA,然后拉高SCL,保持一段时间,完成第一位的发送,以此循环8次。
3.2.4 应答
在主机发送完一个字节的数据后,需要等待从机回复一个应答信号,正常做法是在第8个SCL高电平拉低后,释放SDA信号线(由外部上拉自行拉成高电平),然后拉高SCL,等待从机控制SDA线,如果在第9个SCL高电平保持期间,读取到SDA线为低电平,则认为接收到从机的应答;否则为无应答。
四、应用及对比
常见的串行通信有IIC、UART、SPI、CAN等,下面直接用一张表来展示各种串口的区别。
对比维度 | I²C | UART(串口) | SPI | CAN |
---|---|---|---|---|
引脚数量 | 2 根(SDA+SCL) | 2 根(TX+RX) | 4-5 根(MOSI+MISO+SCK+CS) | 2 根(CAN_H+CAN_L) |
传输模式 | 半双工(同一时刻单向传输) | 全双工(收发独立) | 全双工(同步收发) | 半双工(差分信号) |
最高速度 | 超高速模式 5Mbps | 通常 115.2kbps-4Mbps | 可达数十 Mbps(如 30Mbps) | 最高 1Mbps(高速 CAN) |
拓扑结构 | 多主多从(需仲裁机制) | 点对点 | 一主多从(需 CS 片选) | 总线型(多节点共享总线) |
地址寻址 | 7/10 位地址,自动寻址 | 无地址(需软件协议定义) | 靠 CS 片选指定从机 | 靠 ID 号仲裁(非地址寻址) |
典型应用 | 传感器、EEPROM、低速外设互联 | 串口通信、调试接口、Modem | 高速存储(SD 卡)、LCD 驱动 | 汽车总线、工业控制网络 |
优势 | 引脚少、多设备挂载简单 | 协议简单、传输距离较远(RS-485) | 速度快、全双工、时序灵活 | 抗干扰性强、支持长距离和多节点 |
劣势 | 速度受限、仲裁机制复杂 | 无硬件寻址、多设备需软件管理 | 引脚多、多从机需多 CS 线 | 协议复杂、成本高 |
核心差异总结
I²C 的独特价值:以最少引脚实现多设备互联,适合 “轻量级” 数据交互(如传感器配置、少量参数读写),在低功耗、小数据量场景中不可替代。
与 SPI 的对比:SPI 速度更快但引脚多,适合高速批量数据传输(如 LCD 图像数据);I²C 适合低速、多设备的 “碎片化” 通信。
与 UART 的对比:UART 无硬件寻址,多设备通信需额外协议设计,而 I²C 原生支持多从机自动寻址,硬件层面更简洁。
五、代码实现
用IO口模拟IIC协议,这里就不单独写,直接贴一份github上的代码,这里也不全贴,只贴出模拟IIC几个阶段的IO口翻转方式,想看完整的主从机模拟,可以去原路径观摩,原路径https://github.com/daimaCoder/IIC_MS。
#define IIC_SCL_H HAL_GPIO_WritePin(GPIOB, IIC_SCL_Pin, GPIO_PIN_SET)
#define IIC_SCL_L HAL_GPIO_WritePin(GPIOB, IIC_SCL_Pin, GPIO_PIN_RESET)
#define IIC_SDA_H HAL_GPIO_WritePin(GPIOB, IIC_SDA_Pin, GPIO_PIN_SET)
#define IIC_SDA_L HAL_GPIO_WritePin(GPIOB, IIC_SDA_Pin, GPIO_PIN_RESET)
#define READ_SDA HAL_GPIO_ReadPin(GPIOB, IIC_SDA_Pin)
#define READ_SCL HAL_GPIO_ReadPin(GPIOB, IIC_SCL_Pin)
#define IIC_Delay delay_us(4) //IIC使用的延时,可通过改变延时,改变IIC传输速率
#define Time_Count 250 //while等待超时计数,不可小于某个值, 最小值根据单片机时钟变化void IIC_Start(void) //发送IIC开始信号
{IIC_SCL_H;IIC_SDA_H;IIC_Delay;IIC_SDA_L;IIC_Delay;IIC_SCL_L;
}void IIC_Stop(void) //发送IIC停止信号
{IIC_SCL_L;IIC_SDA_L;IIC_Delay;IIC_SCL_H;IIC_Delay;IIC_SDA_H;
}void IIC_Ack(void) //IIC发送ACK信号
{IIC_SCL_L;IIC_SDA_L;IIC_Delay;IIC_SCL_H;IIC_Delay;IIC_SCL_L;IIC_SDA_H; //添加释放总线}void IIC_NAck(void) //IIC不产生ACK信号
{IIC_SCL_L;IIC_SDA_H;IIC_Delay;IIC_SCL_H;IIC_Delay;IIC_SCL_L;
}uint8_t IIC_Wait_Ack(void) //IIC等待ACK信号
{int time = 0;IIC_SDA_H;IIC_Delay;IIC_SCL_H;IIC_Delay;while(READ_SDA) //等待应答信号{time++;if(time>Time_Count) //等待时间过长,产生停止信号,返回1,表示接收应答失败{//IIC_Stop();return 1;}} IIC_SCL_L; //应答成功,则SCL变低return 0;
} void IIC_Send_Byte(uint8_t data) //IIC发送一个字节
{IIC_SCL_L;IIC_Delay;for(int i=0;i<8;i++) //从高位开始一位一位地传送{ //发数据放到数据线上if((data & 0x80)>0) //当前最高位为1IIC_SDA_H; //拉高数据线elseIIC_SDA_L;data<<=1; //数据左移一位IIC_Delay;IIC_SCL_H;IIC_Delay;IIC_SCL_L; //上一个数据发送完毕,为下一个数据发送准备IIC_Delay;}
} uint8_t IIC_Read_Byte(unsigned char ack) //IIC读取一个字节
{uint8_t read_Data = 0;
// IIC_SDA_H; //释放总线,此处不释放,另处释放for(int i=0;i<8;i++){IIC_SCL_L;IIC_Delay;IIC_Delay;IIC_SCL_H; //主机开始读数据,从机不能再改变数据了,即改变SDA的电平read_Data<<=1;if(READ_SDA)read_Data++;IIC_Delay;}if(ack==0) //说明主机不需要给从机应答IIC_NAck();elseIIC_Ack();return read_Data;
}
六、注意事项
1、因为IIC协议本身是不具备任何校验的,所以如果想要保证通信数据的准确性,可以主从机协定好每传输一段数据后带一个校验,以此来验证数据有效性。
2、IIC协议本身很简单,没有太多的约束,所以在跟各种设备通信时,需要注意各自的协议及时序要求。另外因为IIC本身并没有让同一总线上多个设备同步的机制,如果出现主机与从机两个设备通信过程中,因某种异常导致主机复位重启,此时从机还处于接收或发送的状态中,此时可以通过发送 9 个时钟脉冲(SCL高 - 低循环),强制从机释放总线;另外检测SDA线状态,若为低电平则判定总线被占用,继续发送脉冲直至释放。
七、相关链接
【工具使用】STM32CubeMX-硬件IIC配置-实现EEPROM读写功能