I2C通讯记录(基于BME280)调试
I2C物理层:
一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
I2C协议层:
将I2C的协议层分为读模式以及写模式,其中最大的区别就在于7位地址后的读写位,读写位为0则表示写操作,读写位为1则表示读操作。
写模式只需要按照图24-2,先发送开始信号,接着将7位I2C地址后增加多一个0,补齐8位I2C地址后发送。之后等待ACK信号。
读模式则一般无法直接按照图24-3进行数据读取操作,必须遵照图24-4中的I2C复合模式进行操作,首先发送一个开始信号,接着传输7位I2C地址(利用写模式,对从机起到一个唤醒的作用),之后等待应答后再传输需要读取的低地址位在从机应答之后,再重新产生一个开始信号,再重新传输SA(7位地址),读写位改为1(与SA补齐为8bit),之后不需要再传递低地址直接进行IO口输入输出反转开始读取数据。
I2C地址解析:
常用的I2C地址分为7bit地址以及8bit地址,其区别在于是否填充了读写位。大部分的使用手册上给出的地址称为SLAVE ADDRESS地址。这个地址(SA)也就是7bit地址。如果是在带操作系统的MCU中,则使用7bit地址和i2cget、i2cset命令即可(系统会自动补充读写位)。但是在例如stm32这些不带操作系统的MCU中则需要自己将7bit I2C地址填充读写位使之称为8bit I2C地址后才能使用。
模拟I2C信号:
I2C的起始信号:当SCL保持为高电平时,SDA总线由高拉低。
STM32模拟I2C具体代码示意:
void IIC_Start(void)
{
SDA_OUT(); //sda线输出,使用宏定义的out函数
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0; //START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0; //钳住I2C总线,准备发送或接收数据
}
I2C停止信号:当SCL保持为高电平时,SDA总线由低拉高。
STM32模拟I2C具体代码示意:
void IIC_Stop(void)
{
SDA_OUT(); //sda线输出
IIC_SCL=0;
IIC_SDA=0; //STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1; //发送I2C总线结束信号
delay_us(4);
}
I2C的数据接收信号时,当SCL为高电平时,才能有效读取SDA的信号。当SCL为低电平时,则SDA信号线可以进行高低电平转换以便下一次传输。每次传输是1个bit单位,但是通常一次传输都是传输1个byte搭配一个ack信号。
ack信号:当数据每传输8个bit之后,第九个bit则是ack信号,如果正常的ack信号则是SCL总线为高时,SDA输出低电平。nack信号则是SDA输出低电平。
STM32模拟I2C代码常用示例:
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;