一.什么是IIC?
IIC (Inter-Integrated Circuit)也称I2C,中文叫集成电路总线 。是一个多主从 的串行 总线,由飞利浦公司发明的通讯总线,属于半双工同步 传输类总线,仅由两条线就能完成多机通讯 ,一条SCL时钟线 ,另外一条双向数据线SDA,IIC总线要求每个设备SCL/SDA线都是漏极开路模式,因此必须带上拉电阻才能正常工作。I2C协议占用引脚少,硬件实现简单,可扩展性强,I2C数据传输速率有标准模式(100kbps)、快速模式(400kbps)和高速模式(3.4Mbps)。
IIC使用两根信号线进行通信:一根时钟线SCL,一根数据线SDA 。IIC将SCL处于高时SDA拉低的动作作为开始信号,SCL处于高时SDA拉高的动作作为结束信号 ;传输数据时,SDA在SCL低电平时改变数据,在SCL高电平时保持数据,每个SCL脉冲的高电平传递1位数据。
二.IIC硬件和时序分析
1.IIC总线物理接线
SDA 和SCL 都是双向线路,都通过一个电流源或上拉电阻连接到正的电源电压。当总线空闲时,这两条线路都是高电平。连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与的功能。
总线器件数目 :由于每一个IIC器件在IIC总线上都有一个确切的7位地址码,这也意味着一条IIC总线上最多可链接127(0X00位地址不使用)个地址互不相同的IIC器件 。但在单条IIC总线上链接不多与127个器件的同时,必须要满足总线电容不能超过400pF(协议规定),总线之所以规定电容大小是因为,IIC的OD要求外部有电阻上拉,电阻和总线电容产生了一个RC延时效应,电容越大信号的边沿就越缓,有可能带来信号质量风险。传输速度越快,信号的窗口就越小,上升沿下降沿时间要求更短更陡峭,所以RC乘积必须更小。实际设计中经验值大概是8个器件左右。
2.IIC总线时序
其时序图如下所示:
(1)数据有效性
IIC总线进行数据传送时,在SCL的每个时钟脉冲期间传输一个数据位,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有在时钟线SCL上的信号为低电平期间,数据线SDA上的高电平或低电平状态才允许变化,因为当SCL是高电平时,数据线SDA的变化被规定为控制命令(START或STOP,也就是起始信号和停止信号)。
(2)空闲状态(IDLE)
DLE表示总线空闲状态。此状态下时钟信号SCL和数据信号SDL均为高电 平,此时无I2C设备工作。时钟线(SCL)和数据线(SDA)接上拉电阻,默认高电平,就是为了表示总线是空闲状态。
(3) 起始信号(START)
表示起始状态。在空闲状态下,时钟信号SCL继续保持高电平,数据信号SDL出现由高电平转换为低电平的下降沿,此时产生一个起始信号,与总线相连的I2C设备检测到起始信号之后,进入起始状态等待控制字节的输入。
(4) 停止信号(STOP)
I2C通信的停止信号由主设备发出,SCL保持高电平,SDA由低电平跳变到高电平。
(5) 应答(ACK)与非应答(NACK)
应答信号接收端收到有效数据后需要向对方响应的信号,发送端每发送一个字节(8位)数据,在第9个时钟周期释放数据线去接收对方的应答。在第9个时钟周期:当SDA是低电平为有效应答(ACK),表示对方接收成功;当SDA是高电平为无效应答(NACK),表示对方没有接收成功。注意:数据发射端需要在第9个时钟周期等待接收端的应答信号。
(6) 数据读写操作
IIC协议的读写操作都是一字节大小,从高到低收发数据。
三.IIC主设备与从设备的通信过程
1.主设备给从设备发送/写入数据:
(1)主设备发送起始(START)信号。
(2)主设备发送设备地址到从设备。
(3)等待从设备响应(ACK)。
(4)主设备发送数据到从设备,一般发送的每个字节数据后会跟着等待接收来自从设备的响应(ACK)。
(5)数据发送完毕,主设备发送停止(STOP)信号终止传输。
2.主设备从从设备接收/读取数据
(1)设备发送起始(START)信号
(2)主设备发送设备地址到从设备
(3)等待从设备响应(ACK)
(4)主设备接收来自从设备的数据,一般接收的每个字节数据后会跟着向从设备发送一个响应(ACK)
(5)一般接收到最后一个数据后会发送一个无效响应(NACK),然后主设备发送停止(STOP)信号终止传输。
四.I2C的应用领域
1.传感器接口
I2C通信协议常用于与各种传感器进行接口通信,例如温度传感器、湿度传感器、光传感器等。通过I2C总线,主机设备可以读取传感器的数据,并进行相应的控制和处理。例如温度传感器和湿度传感器:用于测量环境温度和湿度。
2.存储器接口
许多存储器设备(如EEPROM、Flash存储器)也采用了I2C通信协议作为数据传输的接口。主机设备可以通过I2C总线与存储器设备进行数据的读写操作。例如EEPROM和存储器芯片:用于数据存储和读写操作。
3.显示设备接口
I2C通信协议也广泛用于与显示设备进行接口通信,如LCD显示屏、OLED显示屏等。通过I2C总线,主机设备可以向显示设备发送指令和图像数据,实现图形显示的功能。例如LCD显示屏和OLED显示屏:用于文本和图形显示。
4.扩展IO接口
除了传感器、存储器和显示设备接口外,I2C通信协议还被用作扩展IO接口的一种方案。通过连接扩展IO芯片,主机设备可以扩展更多的输入输出端口,实现与外部设备的连接和控制。例如扩展IO和控制芯片:用于扩展输入输出端口和外设控制。
通过使用I2C协议,各种外设可以通过简单的两根线进行连接,减少了硬件复杂性和引脚数量,提供了更灵活和简洁的系统设计方案。
五.实际代码示例
STM32 HAL库配置与使用:
cpp
// 包含必要头文件
#include "stm32f4xx_hal.h"
// 初始化I2C实例
void I2C_Init(I2C_HandleTypeDef *hi2c) {
hi2c->Instance = I2Cx; // 选择具体I2C接口,如I2C1
hi2c->Init.ClockSpeed = 100000; // 设置总线速度为100kHz
hi2c->Init.DutyCycle = I2C_DUTYCYCLE_2; // 时钟占空比
hi2c->Init.OwnAddress1 = 0x00; // 主机地址(如果适用)
hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 地址长度
hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 双地址模式禁用
hi2c->Init.OwnAddress2 = 0x00; // 第二个主机地址(如果适用)
hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 禁用一般调用
hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 启用时钟延展
HAL_I2C_Init(hi2c); // 调用HAL库函数完成初始化
}
// 发送数据到从设备
HAL_StatusTypeDef I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) {
return HAL_I2C_Master_Transmit(hi2c, DevAddress, pData, Size, Timeout);
}
// 接收数据(主接收模式)
HAL_StatusTypeDef I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) {
return HAL_I2C_Master_Receive(hi2c, DevAddress, pData, Size, Timeout);
}
// 或者在中断模式下处理接收
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
// 在这里处理接收到的数据
// ...
// 重新启动传输或者清除中断标志
// ...
}