STM32 IIC通信(简单理解)
半双工通信。
-
一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
-
iic总线可以挂载多个从设备,每个从设备都有独立的地址。
-
具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。
-
连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。
以主机(MCU)发给从机(MPU)为例
1、S:代表起始信号。
2、发送从设备地址(是唯一,地址可以是7位和10位),与从设备匹配成功,主设备选中从设备,建立连接,该总线下的其他从设备会忽略之后的主设备发送的数据。
3、在发送地址之后,有一bit位是用于表示传输的方向(0写或1读),与地址一起发送过去。与从机建起连接后,主机会收到应答信号。
4、只有接收到应答信号后,主机才能继续发送或接收数据。
每建立一次数据传输,都需要一次起始信号,终止信号表示结束此次设备间的数据通信。
void I2CStart()
{
I2C_SDA = 1;
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 0;
}
void I2CStop()
{
I2C_SCL = 0;
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 1;
I2CDelay();
}
SDA数据线在 SCL 的每个时钟周期传输一位数据。传输时,SCL 为高电平的时候 SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL为低电平时,SDA 的数据无效,一般在这个时候 SDA 进行电平切换,为下一次表示数据做好准备。
主设备每发一个字节,就会释放SDA控制权,等待从设备发送应答信号(响应),主设备接收到“1”表示非应答,从设备接收数据失败(设备不存在/忙中);接收到“0”表示应答,从设备成功接收到一个字节数据。
同理,从设备发送数据,主设备接收数据,没接收一个数据,从设备也需要等待主设备的应答信号。
//主设备发送数据给从机,等待应答信号
bit I2CRecAck(){
bit ack; //用于暂存应答位的值
I2C_SDA = 1; //8位数据发送完后,主机释放SDA,以检测从机应答
I2CDelay();
I2C_SCL = 1; //拉高SCL
ack = I2C_SDA; //读取此时的SDA值,即为从机的应答值
I2CDelay();
I2C_SCL = 0; //再拉低SCL完成应答位,并保持住总线
return (~ack); //应答值取反以符合通常的逻辑:
//0=不存在或忙或写入失败,1=存在且空闲或写入成功
}
//主设备收到一个字节时,需要给从设备应答信号
void I2CReplyAck(){
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1;
I2CDelay();
I2C_SCL = 0;
}
void I2CReplyNak(){
I2C_SDA = 1;
I2CDelay();
I2C_SCL = 1;
I2CDelay();
I2C_SCL = 0;
}
强调 :主设备需要接收从设备数据过程,读取:1、发送起始信号,发送从设备地址+0.等待应答。2、写入你要读取寄存器地址。等待应答。3、这一步比较特殊,需要再次发起起始信号,发送从设备地址+1.等待应答。4、此时才可以读取从设备的地址。5、读取完一个字节,需要发送应答信号给主设备。需要继续读取数据,发送应答信号“0”;不想读取数据,发送非应答信号“1”,再发送终止信号。
bit MPU_Read_Byte(u8 reg)
{
bit res;
MPU_IIC_Start();
MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令
MPU_IIC_Wait_Ack(); //等待应答
MPU_IIC_Send_Byte(reg); //写寄存器地址
MPU_IIC_Wait_Ack(); //等待应答
MPU_IIC_Start();
MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令
MPU_IIC_Wait_Ack(); //等待应答
res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK
MPU_IIC_Stop(); //产生一个停止条件
return res;
}