IIC 通信原理

基本介绍

点击跳转

原理介绍

Init

硬件层

​ 需要接上拉电阻(保证传输稳定性)

代码

1
2
3
4
void IIC_Init(){
IIC_SCL=1;
IIC_SDA=1;
}

Start

物理层

​ IIC总线的SCL保持高电平,SDA由高电平变为低电平后,延时(>4.7us),SCL变为低电平。

  • 步骤
  1. SCL 高
  2. SDA 高->低 + 延时(>4.7us)
  3. SCL 高->低

代码

1
2
3
4
5
6
7
8
9
void IIC_Start(){
IIC_SCL=1;
IIC_SDA=1;
delay_us(5);
IIC_SDA=0;
delay_us(5);
IIC_SCL=0;

}

Tramsmit Data

物理层

 传输时,SDA的宽度应该大于SCL的宽度,在SCL为高时读取SDA,SCL为低时改变SDA的电平。
 ==注意:==传输数据过程总不允许SDA变化(否则会被视为开始或停止信号)
  • 步骤
  1. 拉低SCL进行数据传输
  2. SDA传送高低电平(0或1)
  3. SCL在高电平时期读取SDA的数据
  4. 响应信号

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void IIC_Transmit(u8 data){
IIC_SCL=0; //
u8 i=0;
for(i=0;i<8;i++){
if(data & 0x80 ){
IIC_SDA=1; // transmit 1
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
else{
IIC_SDA=0; // tramsmit 0
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
data<<=1;
}

}


Stop

物理层

​ 与Start相反:SCL为高时SDA由低到高

  1. SCL = 1
  2. SDA = 0
  3. SDA = 1 + 延时(>4.7us)

代码

1
2
3
4
5
6
7
8
9
10
11
void IIC_Stop(void)
{

IIC_SCL=0;
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;
delay_us(4);
}

Response

物理层

​ 主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功
  1. IIC_SCL=0
  2. IIC_SDA=0
  3. IIC_SCL=1 读取ACK

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

void I2C_Ack(void)
{
IIC_SCL=0; //先拉低SCL,使得SDA数据可以发生改变
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}

void I2C_NAck(void)
{
IIC_SCL=0; //先拉低SCL,使得SDA数据可以发生改变
IIC_SDA=1; //拉高SDA,不产生应答信号
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}


一些问题

回答基于GPT

IIC通信是如何区分ACK和数据的?

在 I2C 通信中,数据传输包括两个方向:主设备向从设备发送数据(写操作),以及从设备向主设备发送数据(读操作)。在这两种情况下,都需要一种方法来区分 ACK(应答)和数据。

下面是 I2C 中如何区分 ACK 和数据的一般流程:

  1. 写操作
    • 主设备发送一个字节的数据给从设备。
    • 每当主设备发送完一个字节后,会释放 SDA 线并将其拉高,等待从设备的应答。
    • 如果从设备收到数据并且成功接收,它将拉低 SDA 线表示 ACK。
    • 如果从设备未成功接收数据(或者不接收),它将保持 SDA 线高电平,表示 NACK(非应答)。
  2. 读操作
    • 主设备向从设备发送一个读请求,并在准备接收数据时将 SDA 线拉高,进入接收模式。
    • 从设备在每个数据字节的发送后,会将 SDA 线拉低或保持低电平来表示 ACK。
    • 当从设备不再有数据发送时,它将保持 SDA 线高电平,表示 NACK。

在 I2C 中,ACK 和 NACK 的区别是在 SDA 线上的电平状态。ACK 是 SDA 线被拉低一段时间(通常是一个时钟周期),而 NACK 是 SDA 线保持高电平。

这种应答机制确保了数据的正确传输,并且主设备和从设备之间能够进行有效的通信。

IIC如何判断是否已经传输好了一个字节?否则会误判ACK信号吧

在 I2C 通信中,确实有一个机制来确保每个字节都被正确传输,以避免误判 ACK 信号。这个机制称为“时钟拉伸”(Clock Stretching)。

时钟拉伸是从设备(通常是从设备)可以通过拉低时钟线(SCL)来暂停主设备的时钟来延长传输时间的能力。当从设备需要更多时间来处理数据或准备发送应答时,它可以拉低 SCL 线来暂停时钟,从而保证数据传输的准确性。

在每个数据字节的传输中,主设备发送一个字节,并在每个时钟周期结束时等待从设备的应答。如果从设备需要额外时间,则可以拉伸时钟线。一旦从设备准备好应答,它就释放 SCL 线,使时钟继续,主设备就可以继续传输下一个字节或完成传输。

这种时钟拉伸的机制确保了主设备和从设备之间的同步,并且确保了每个字节都能够被正确传输。如果从设备在时钟拉伸期间没有完成数据的处理或准备应答,主设备会在检测到应答信号之前继续等待。

因此,在 I2C 通信中,即使有时钟拉伸,主设备仍能够正确判断 ACK 信号。

IIC如何判断是否已经传输好了一个字节?

在 I2C 中,主设备在发送每个字节时都会产生一个时钟脉冲(CLK)。这些时钟脉冲用于同步数据传输,并且在每个字节的传输之后,主设备需要知道何时应该停止发送数据并等待从设备的应答。

判断是否已经传输好了一个字节主要依赖于主设备的计数。主设备通常会发送8个时钟脉冲(对应一个字节的8位数据),然后等待从设备的应答。

具体的步骤如下:

  1. 主设备发送一个字节的数据。
  2. 主设备在发送每个位时都会产生一个时钟脉冲(CLK),总共8个脉冲。
  3. 在发送完最后一个位后,主设备停止产生时钟脉冲,并等待从设备的应答。

等待应答时,主设备可以通过检测SDA线上的电平来判断是否收到应答信号。如果从设备接收到了数据并正确处理,它会拉低SDA线(ACK),表示接收到数据并准备好接收下一个字节。如果从设备没有接收到数据或者出现错误,它会保持SDA线为高电平(NACK)。

通过这种方式,主设备可以判断是否已经传输好了一个字节,并且根据从设备的应答来进行相应的操作。

STM32 实现

标准库

hal库