软件I2C的引脚配置问题

软件模拟I2C

在通过软件模拟I2C时,我们是选定任意引脚作为I2C的SDASCL,这个时候需要配置GPIO使其既能输入又能输出,这,推挽输出开漏输出都是可以的,以下将会对两者的配置进行详细介绍

开漏输出

引脚配置

这是最推荐的做法,也是I2C协议的要求将SDA和SCL引脚配置为上拉电阻(弱) + 开漏输出的模式,这样可以使主机只能输出低电平,避免了总线上一高一低造成的短路问题。

1.开漏输出:

保证IO只具备输出低电平的能力,完全避免电源短路的发生

2.上拉电阻:

通常使用外接4.7K上拉电阻,I2C通信的需要输出高电平的能力,由于开漏模式下不具备输出高电平的能力,需要外部加一个上拉电阻,使其具备输出高电平的能力

这样设计电路的好处:

1.避免电源短路,安全

2.避免推挽模式下的引脚频繁切换,同时具备输入和输出功能

3.这样的硬件设计,使开漏模式具备线与特性:任意设备输出低电平,总线就是低电平,所有设备高电平,总线才是高电平。利用这个特性执行多主机下的总线仲裁机制,始终同步

硬件原理

开漏模式的特性是由于硬件上决定的STM32的手册上对开漏输出的描述:

image-20250712182257884

开漏输出:

  • GPIO写入’0’,上面的P-MOS断开,下面的N-MOS导通,IO被下拉至低电平
  • GPIO写入’1’, 上面的P-MOS仍断开,下面的N-MOS也断开,IO处于高阻态,引脚状态由外部上下拉决定

推挽输出:

  • GPIO写入’0’,上面的P-MOS断开,下面的N-MOS导通,IO被下拉至低电平
  • GPIO写入’1’, 上面的P-MOS导通,下面的N-MOS断开,IO被上拉至高电平

开漏输出P-MOS的始终不能导通,由前面的输出控制电路决定的

输入输出能力

GPIO配置为开漏模式+上拉电阻的情况下,是同时具备输出输入能力的。

image-20250712190915022

输出能力

  • 低电平:N-MOS导通,P-MOS关闭,IO被拉低至低电平

  • 高电平: N-MOS关闭,P-MOS关闭,IO为高阻态,不主动输出电平,靠外部上拉电阻把IO拉高,形成高电平(弱上拉)

输入能力

TTL施密特触发器打开状态,可以直接读取,但是要先保证IO处于高阻态,即:先让IO(SDA引脚)输出高电平,让P-MOS和N-MOS都断开,处于高阻态,否则可能由于之前IO输出过低电平,N-MOS打开,导致IO口一直锁死在低电平的状态,因为这时候读取到的就是我们之前自己输出的低电平

推挽输出

短路问题

I2C在使用推挽输出模式,在通讯过程中,如果由于时序没有调整好,主机和从机在SDA总线上一个输出高电平、一个输出低电平就会导致短路,这样的后果很严重,所以我们一般都不会使用推挽输出作为I2C的SCLSDA引脚配置

引脚配置

非要使用(不推荐)

如果非要使用推挽输出进行I2C通信的话,我们需要处理引脚的配置,由于推挽输出的情况下,IO口没有高阻态,此时虽然也可以读取电平,但是读取到的其实是我们自己输出的电平,所以我们需要进行频繁的引脚切换

主机引脚在发送数据时(主机控制SDA)需要配置为推挽输出模式,主机引脚在接收数据时需要配置为输入模式

输出能力

输出能力:

  • 低电平:N-MOS导通,P-MOS关闭,IO被拉低至低电平

  • 高电平: N-MOS关闭,P-MOS开启,IO被VDD拉至高电平

输入能力(不具备):

推挽输出模式下,IO管脚的软件可以读取电平(有输入采样能力),但只能“IO自己输出的电平”,不能真正检测外部信号对管脚的影响。只有输入/开漏高阻态下,才可以真正感知外部信号。