一、 工作原理:
I2C全称为 Inter-Integrated Circuit(内部集成电路),是一种串行总线的外设接口,采用同步方式串行接收或发送数据,两个设备在同一个时钟下工作。
- I2C总线只需要两根线:SDA-->串行数据线;SCL-->串行时钟线。
- I2C总线上可挂接的设备数量受总线的最大负载电容 400pF 限制,如果所挂接的是同种型号的器件,亦受器件地址位的限制。
- SDA线和SCL线都是双向 I/O线,接口电路为开漏输出,必须通过上拉电阻接到电源VCC,总线空闲时,两根线都是高电平。
这里阐明两个概念,解释为什么需要上拉电阻:
- 推挽输出结构是由两个MOS或者三极管互补输出组成,同一时刻,只有一个导通,另一个截止;推挽输出最大的优点是:可以真正的输出高电平和低电平,且在两种电平下都具有驱动能力。但一个缺点是:推挽输出不能实现“线与“。如果两个推挽输出结构相连在一起,比如A、B两个结构;A结构上面的MOS导通,下面的MOS截止;同时B结构上面的MOS截止,下面的MOS导通,那么电流会直接从VDD-->A结构上面的MOS-->B结构下面的MOS-->GND。整个通路电阻很小,会发生短路。
- 开漏输出最主要的特性是高电平没有驱动能力,需要借助外部上拉电阻接到高电平才能输出高电平。当MOS管截止,那么电流会从VDD-->MOS上拉电阻-->负载-->GND。这一特性可以实现”线与“功能。
- 线与即多个信号线直接连接在一起,只有当所有信号全部为高电平时,合在一起的总线才为高电平;只要任意一个或多个信号为低电平,则总线为低电平。
- 上拉电阻过大,驱动能力不足;上拉电阻过小,上拉过强,无法拉低。
二、协议信号
- 起始信号:当 SCL 线是高电平时 ,SDA 线从高电平向低电平切换。
- 停止信号:当 SCL 线是高电平时 ,SDA 线由低电平向高电平切换。
- 发送数据:8个数据位,先传最高位(MSB),然后释放SDA线(拉高电平)
SCL为低电平时(0),SDA可进行电平转换;
SCL为高电平时(1),SDA必须保持不变,接收设备(主设备或从设备)读取数据。 - 接收响应:ACK,在第九个周期(可以说是第九个数据位)
从机设备拉低SDA(0),这表示一个确认位(ACK),答复发送设备,接收完成;
如果从机保持SDA为高电平(1),主机认为从机没有确认(NACK)本次数据传输,多字节数据传输过程就会被中止。
I2C只有两根线(SCL和SDA),假设主设备A需要启动I2C,他需要在SCL高电平时,将SDA由高电平转换为低电平作为起始信号。主设备A在把SDA拉高后,它需要再检查一下SDA的电平。
SDA是高电平,说明主设备A可以占用总线,然后主设备A将SDA拉低,开始通信。
SDA是低电平,说明已经有其他主设备将SDA拉低了, 由于 1 & 0 = 0 ,那么主设备A在检查SDA电平时,会发现不是高电平,而是低电平,说明其他主设备抢占总线的时间比它早,主设备A只能放弃占用总线, 如果是高电平, 则可以占用。
三、传输内容和过程
- 内容:
地址帧(address frame):一旦主机产生一个起始信号,总线便不在空闲。主机接着发送包含7位从机地址和1位读写标志(R/W)共8个数据位。
数据帧(data frames):由master发往slave的数据(或由slave发往master),每一帧是8-bit的数据 - 过程:
现在的I2C应用里,在起始信号后要发2~3个地址,第1个是设备地址,第2个是设备内的地址(比如寄存器地址、存储空间地址),如果设备内部地址是16位,则发第3个地址,与第2个地址组合起来拼16位地址,然后才是读写数据操作。
四、读写数据步骤
1:写数据:
- 发送一个起始信号。
- 发送7bit从机地址,即接收设备地址。此处需要注意,发送数据时,无法发送7bit数据,此处需要发送bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。 (为从器件的的写地址-->Slaver_Addr | 0)
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答。
- 发送寄存器地址(想要写入的寄存器地址),8bit数据。
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答。
- 发送一个数据,8bit数据。
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答信号。
- 发送一个CRC校验码,此CRC校验值为2、4、6步数据产生的校验码。(可以不校验)
- 既可以发送一个应答信号,也可以发送一个无应答信号,均由从机器件产生。
- 发送一个停止信号。
2:读数据:
- 发送一个起始信号。
- 发送7bit从机地址,即接收设备地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。 (为从器件的的写地址-->Slaver_Addr | 0)
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答。
- 发送寄存器地址(想要读取的寄存器地址)。
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答。
- 再次发送一个起始信号。
- 发送7bit从机地址,即接收设备地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。 (为从器件的的读地址-->Slaver_Addr | 1)
- 产生一个ACK应答信号,此应答信号为从机器件产生的应答。
- 读取一个字节(8bit)的数据。
- 产生一个ACK应答信号,此应答信号为CPU产生。
- 读取一个CRC校验码。 (可以不校验)
- 产生一个NACK信号。此无应答信号由CPU产生。
- 产生一个停止信号。
五、附图:
1:I2C读取数据时序图
2:实测波形:
如图所示,C1为IIC_SDA,C2为IIC_SCK,在时钟上升沿读取数据。
3:I2C代码:见上传资源 赛元SC95F861X+日历芯片PCF8563_赛元-嵌入式文档类资源-CSDN下载https://download.csdn.net/download/VampireWolf/12587896