一、物理结构
I2C是一种同步半双工的通信协议,同一时刻只能向一个方向传送数据。I2C总线由SCL时钟线和SDA数据线组成,时钟线控制收发数据的频率。
Fig1.I2C 系统结构
1、每个I2C设备都有一个独立的地址,主机可以利用这个地址和不同设备通信,地址共有7bits和10bits两种。
2、总线通过上拉电阻接到电源,当I2C设备空闲时,MOSFET关断,输出高阻态。
3、Cbus电容(总线负载电容)决定了外接设备的数量,原因见Fig2。Cbus电容并非实实在在的一个电容,而是连接到I2C总线上设备的等效容性负载。
Fig2.容抗对I2C电平的影响
I2C在高电平时读取数据,当总线上的电容过大时,影响SDA总线的充电时间,造成bit位的错误读取。
4、标准协议中I2C共有标准、快速、快速+、高速、超高速5种工作速率。
Fig3.五种传输速率比较
二、传输协议
Fig4.协议传输格式
1、开始位/重复开始位(S-Start/Sr-Repeated Start):当SCL为高电平时,SDA由高电平切换为低电平,此时通信开始。
Fig5.开始位和停止位
总线空闲状态:SDA和SCL均为高电平。
2、数据传输:主机(Master)或从机(Slaver)在SCL高电平(上升沿)时读取SDA上的信号,在SCL低电平是,SDA完成传输位信号的改变。数据传输时,高位先进行传输(MSB),一次传输的最大传输Byte位数无限制。
Fig6.数据变化均发生在时钟低电平,有些可能需要数据建立时间,在时钟变成高电平前完成数据位的变化
3、应答位/非应答为(ACK/NACK):每8个bit位后会跟随一个ACK位。
ACK:发送设备释放SDA,接收设备控制SDA低电平。
NACK:发送设备释放SDA,接收设备控制SDA高电平。
NACK发生的情况:
①无:没有主机访问地址的slave
②忙:slave忙碌,无法开始数据传输
③错:接收到错误的数据
④停:通知Slave-Transmitter停止发送数据
4、时钟拉伸(clock Stretching):①ACK和NACK的时间拉长,增加Receiver的处理时间②如果收发设备处理数据性能有差异,传输每个bit位的时钟低电平时间可拉长,但传输频率会降低。
5、停止位:当SCL为高电平时,SDA由低电平向高电平切换,表示通信停止。
6、时钟同步:同一总线上有多个主机同时访问从机时发生,采用SCL时钟(OC/OD)线与的结构,只有当CLK1和CLK2均为高电平时,SCL才表现为高电平,通信开始。超快速模式采用推挽式结构,不支持时钟同步。
Fig7.时钟同步
7、总线仲裁:同一总线上有多个主机同时访问从机时发生。从机不参与仲裁,由主机完成。仲裁按每个SDA数据bit位逐步进行。
Fig8.总线仲裁
利用时钟同步的SCL上升沿对SDA采样,如果DATA1和DATA2全程和SDA上一致,则双主机都能同时访问同一个从机;如果DATA1先和SDA不一致,则DATA2的Master获取主动权,继续完成相关操作,DATA1的主机丢失总线SDA的控制权,并关闭DATA1的输出。
三、从设备的地址
同一I2C总线上的多个Slave地址必须具有唯一性,不能相同。从设备的地址分为7bit位和10bit为两种。
Fig9. 7位从机地址+1位读写控制位
Fig10. 10位从机地址+1位读写控制位+11110固定编码,组成2个字节
四、I2C总线典型问题
Fig11.I2C总线常见问题
解决方案:
五、EEPROM AT24C02读写操作
Fig12. 芯片引脚定义
1、SCL时钟总线:SCL输入用于将正边缘时钟数据输入到每个EEPROM设备,并将负边缘时钟数据输出到每个设备。
2、SDA数据总线:SDA引脚是双向的,用于串行数据传输。
3、设备地址A2, A1, A0:A2、A1和AO引脚是硬接线AT24C02的设备地址输入,共有8种组合,即I2C总线最多接8个AT24C02。
4、写保护WP:AT24C02有一个写保护引脚,提供硬件数据保护。当连接到地(GND)时,写保护引脚允许正常读/写操作。当引脚连接到Vcc时,就会启用Write protection特性,不允许读写。
Fig13.读写时序(混合模式)
六、OLED屏显示
尺寸:0.96寸
分辨率:128*64
通信方式:I2C
显存芯片:SSD1315
管脚定义:GND、VCC、SCK、SDA
显示原理:SSD1315的SRAM,也称为GDDRAM(Graphic Display Data RAM),含128 × 64 个bit位,被分为8个 PAGE,每个page由8行×128列个bit位组成。当我们往这个RAM写入数据,就会显示特定内容。
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void OLED_I2C_Start(void)
{
OLED_W_SDA(1);
OLED_W_SCL(1);
OLED_W_SDA(0);
OLED_W_SCL(0);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void OLED_I2C_Stop(void)
{
OLED_W_SDA(0);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_SDA(Byte & (0x80 >> i));
OLED_W_SCL(1);
OLED_W_SCL(0);
}
OLED_W_SCL(1); //额外的一个时钟,不处理应答信号
OLED_W_SCL(0);
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCommand(uint8_t Command)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x00); //写命令
OLED_I2C_SendByte(Command);
OLED_I2C_Stop();
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x40); //写数据
OLED_I2C_SendByte(Data);
OLED_I2C_Stop();
}
七、STM32的I2C外设
STM32的I2C外设可用作通信的主机以及从机,支持100kbps和400kbps的速率,支持7位、10位设备地址,支持DMA数据传输,并且具有数据校验功能。
STM32的外设都挂载在APB1总线上,使用APB1的时钟源PCLK1。
其定义的结构体如下:
typedef struct
{
uint32_t I2C_ClockSpeed; /*!< Specifies the clock frequency.This parameter must
be set to a value lower than 400kHz */
uint16_t I2C_Mode; /*!< Specifies the I2C mode.
This parameter can be a value of @ref I2C_mode */
uint16_t I2C_DutyCycle; /*!< Specifies the I2C fast mode duty cycle.This
parameter can be a value of @ref
I2C_duty_cycle_in_fast_mode */
uint16_t I2C_OwnAddress1; /*!< Specifies the first device own address.
This parameter can be a 7-bit or 10-bit address.
*/
uint16_t I2C_Ack; /*!< Enables or disables the acknowledgement.
This parameter can be a value of @ref
I2C_acknowledgement */
uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is
acknowledged.This parameter can be a value of @ref
I2C_acknowledged_address */
}I2C_InitTypeDef;
1、I2C_ClockSpeed:设置I2C的传输速率。写入的参数不得高于400kHz。
2、I2C_Mode:选择I2C的使用方式。有I2C_Mode_I2C和I2C_Mode_SMBusHost、I2C_Mode_SMBusDevice,三种模式。直接设置I2C_Mode_I2C模式即可。
3、I2C_DutyCycle:是指SCL时钟的占空比。可选为(低电平:高电平=2:1)I2C_DutyCycle_2模式和16:9模式的I2C_DutyCycle_16_9,对要求不高的场合,可随便选。
4、I2C_OwnAddress1:配置STM32的I2C设备自己的地址。
5、I2C_ACK:配置应答信号,设置为I2C_ACK_Enable即可。
6、I2C_AcknowledgedAddress:选择I2C的寻址模式是7位还是10位。