现象:单片机选用硬件i2c读取E2PROM,当单片机复位时,会有概率呈现再无法与E2PROM通讯,此刻SCL为高,SDA一向为低
原因:当单片机正在和E2PROM通讯,假如主正好发生计划发第9个时钟,此刻SCL为高,而从开端拉低SDA为低做预备(作为ACK信号),等候主SCL变低后,从再开释SDA为高。假如此刻正好单片机复位,主SCL还没来得及变低,直接变成高电平,此刻从还在等候SCL变低,所以一向拉低SDA;而主由于复位,发现SDA一向为低,也在等候从开释SDA为高。因而主从都进入一个彼此等候的死锁状况。
解决办法:最好的办法是选用模仿i2c. 但由于现已装备成硬件i2c,程序改为上电或复位改成发9个SCL时钟信号,使从好开释SDA。
最近发现单片机(硬件I2C完结)读取E2PROM时分,单片机复位或许会引起i2C死锁,表现为SCL为高,SDA一向为低,后发现是E2PROM从设备拉死i2c总线,从设备断电之后,SDA变高,上电后通讯正常。后来经过拉低SCL信号线,SDA就会主动变成高电平,i2c总线康复。后检查一篇文章,讲的不错,特摘抄如下:
在正常状况下,I2C总线协议可以确保总线正常的读写操作。可是,当I2C主设备反常复位时(看门狗动作,板上电源反常导致复位芯片动作,手动按钮复位等等)有或许导致I2C总线死锁发生。下面具体阐明一下总线死锁发生的原因。
在I2C主设备进行读写操作的进程中。主设备在开端信号后操控SCL发生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时分,从设备输出应对信号,将SDA信号拉为低电平。假如这个时分主设备反常复位,SCL就会被开释为高电平。此刻,假如从设备没有复位,就会持续I2C的应对,将SDA一向拉为低电平,直到SCL变为低电平,才会完毕应对信号。而关于I2C主设备来说。复位后检测SCL和SDA信号,假如发现SDA信号为低电平,则会以为I2C总线被占用,会一向等候SCL和SDA信号变为高电平。这样,I2C主设备等候从设备开释SDA信号,而一起I2C从设备又在等候主设备将SCL信号拉低以开释应对信号,两者彼此等候,I2C总线进人一种死锁状况。相同,当I2C进行读操作,I2C从设备应对后输出数据,假如在这个时刻I2C主设备反常复位而此刻I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状况。
SCL为高,SDA一向为低原因
从:正常时序下:SDA信号是在SCL为低的状况下改动,即从应对SDA为低电平时,此刻SCL应为为低电平(即从设备是先拉低SDA信号,等候主设备SCL由高变低,“取走”ACK信号后,从再开释SDA为高)。但假如此刻时序被打乱,例如单片机i2c通讯时忽然复位,SCL忽然变高,则从设备SDA一向为低,等候SCL变低。
主:SDA被从拉低,故主以为i2c总线占用,一向等候SDA变高这样主从进入一个彼此等候的死锁进程。
办法:
最好用模仿I2C完结,则不会死锁
(1)尽量选用带复位输人的I2C从器材。
(2)将一切的从I2C设备的电源衔接在一起,经过MOS管衔接到主电源,而MOS管的导通关断由I2C主设备来完结。
(3)在I2C从设备设计看门狗的功用。
(4)在I2C主设备中添加I2C总线康复程序。每次I2C主设备复位后,假如检测到SDA数据线被拉低,则操控I2C中的SCL时钟线发生9个时钟脉冲(针对8位数据的状况),这样I2C从设备就可以完结被挂起的读操作,从死锁状况中康复过来。这种办法有很大的局限性,由于大部分主设备的I2C模块由内置的硬件电路来完结,软件并不可以直接操控SCL信号模仿发生需求时钟脉冲。
(5)在I2C总线上添加一个额定的总线康复设备。这个设备监督I2C总线。当设备检测到SDA信号被拉低超越指定时刻时,就在SCL总线上发生9个时钟脉冲,使I2C从设备完结读操作,从死锁状况上康复出来。总线康复设备需求有具有编程功用,一般可以用单片机或CPLD完结这一功用。
(6)在I2C上串人一个具有死锁康复的I2C缓冲器,如Linear公司的LTC4307如图2所示:LTC4307是一个双向的I2C总线缓冲器,而且具有I2C总线死锁康复的功用。LTC4307总线输人侧衔接主设备,总线输出侧衔接一切从设备。当LTC4307检测到输出侧SDA或SCL信号被拉低30ms时,就主动断开I2C总线输人侧与输出侧的衔接。而且在输出侧SCL信号上发生16个时钟脉冲来开释总线。当总线成功康复后,LTC4307会再次衔接输人输出侧,使总线可以正常作业。