前言
经常在论坛上看到有网友在咨询I2C的问题,这里就I2C总线做一个给比较全面的总结,感兴趣的网友可以耐心的看下去,相信对你会有帮助。
【1. 基础知识】
1.1. 关于口线电平
在I2C总线中有2个口线,SDA和SCL。这两个口线对为OC输出。什么是OC呢?相对OC还有什么输出呢?
OC就是开漏输出(Open Collector)的简称,有时候也叫OD输出(Open-Drain),OD是对mos管而言,OC是对双极型管而言,在用法上没啥区别。
相对于OC输出,另一种输出叫推挽输出(Push-Pull),一般的MCU管脚输出可以设置这两种模式。这里分别介绍下这两种输出的不同点。
推挽输出 : 可以输出高、低电平连接数字器件,推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止.
开漏输出 : 输出端相当于三极管的集电极未接任何电平, 要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。
对于MCU的开发者来讲,简单的这样理解就可以了。如果管脚设置成推挽输出模式,输出高时,IO口相当于VCC, 输出低时IO口相当于接地。如果管脚设置成开漏输出模式,输出高时,IO口的电平会和与其相连的口线进行与操作,如果都为高,才会被上拉拉成高电平,输出为低时,也相当于接地。
I2C总线要实现线与的功能,所以SDA和SCL口线都必须设置为开漏输出模式。我们使用MCU的硬件I2C接口时,口线会被自动设置成开漏。但有时候我们会使用IO口来模拟I2C总线,这个时候我们如何设置口线呢?
这里要分两种情况,如果MCU的口线支持开漏输出模式,则可以直接把SDA和SCL设置成开漏输出。例如Silicon 的C8051系列MCU,它的口线就支持开漏和推挽输出。如果MCU不支持开漏输出那怎么办呢?例如MSP430。在网上我们看到很多的例程代码都是直接设置IO口的高低电平,这样做其实是不太合理的。因为我们只满足了I2C总线在自己这端的时序要求。而没有考虑到连接在总线上的其他器件。如果总线上其他器件的电平和MCU输出的电平一致,这样做是没问题的,如果两边的电平不一致时,这样做就有一定风险造成IO的损坏。当你输出高时,相当于IO口连接到VCC,如果对方这是恰好输出的是低电平,那就相当于短路了。当然如果软件做的合理,是可以避免这样的事情的,但总线上的很多器件都不是由你能控制的,如何设计出更合理的软件来避免这样的问题发生呢?
对于不支持开漏输出MCU,我们最合理的做法是,当设置口线电平为高时,我们把口线设置成输入状态,然后利用口线上的上拉电阻来把口线拉高。这样即使是两边电平不一致时,也不会造成IO口的损坏。
。。。<未完待续>