发新帖我要提问
12
返回列表
打印

奇怪,AT24C02读后立即写写不进(附精美图)

[复制链接]
楼主: myfaith
手机看帖
扫描二维码
随时随地手机跟帖
21
864| | 2009-11-10 09:55 | 只看该作者 回帖奖励 |倒序浏览
我是来看图的

使用特权

评论回复
22
草履虫| | 2009-11-10 09:59 | 只看该作者
写数据的时候发完8个clk(clk为低)后,要将SDA和SCL都置高,这时再读到的ACK才是有效的。
我看图中的情况并非如此。
下面是读ACK的代码,看一看有没有帮助。
SET_SDA;                // release SDA for ACK polling
  TimeDelay2us();
  SET_SCL;                // start ACK polling
  TimeDelay2us();
  bBitMask = 200;                // time out protection
  do{
       TimeDelay2us();       
  }while(IIC_SDA && --bBitMask);// wait for ACK, SDA=0 or bitMask=0->jump to this loop
  CLR_SCL;

使用特权

评论回复
23
BLUE2008| | 2009-11-11 21:57 | 只看该作者
我发现我随机读可以,但连续读后,再重新开始连续读就不行了,也很郁闷!

使用特权

评论回复
24
草履虫| | 2009-11-11 22:50 | 只看该作者
LZ的答案呢?不会还没有解决吧。

使用特权

评论回复
25
myfaith|  楼主 | 2009-11-12 10:23 | 只看该作者
我的ACK没有问题,符合时序要求.在第9个时钟周期的低电平出现后,2402拉底SDA表示ACK,一直保持到第9个高电平结束.

使用特权

评论回复
26
草履虫| | 2009-11-12 11:19 | 只看该作者
我说的人家不信呀!

LZ我问你,你没有把SDA置高,何来保证ACK是2402发出的?
MCU的I/O本来就是低,与2402的SDA连接在一起,如果都是输出的话,那么是线与的关系。你要是清楚I2C和MCU接口的内部硬件的话,就很好理解。

你把可以做两实验,把两个I/O设置成输出后,接到一起,一个置低(MCU),一个置高(相当于2402的ACK),你看一下,测试结果肯定是0。这个能够说明有ACK吗?
所以,一定要先释放SDA(置成输入状态,拉高),然后再读。我说的够清楚了吧!

你没有真正的理解I2C。

即使你的程序免强写或读对了,也是不稳定的。

使用特权

评论回复
27
草履虫| | 2009-11-12 11:36 | 只看该作者
要不我换个老马甲(不比匠人的晚)再说。呵。。。

使用特权

评论回复
28
草履虫| | 2009-11-12 11:40 | 只看该作者
bool fgI2CStart(byte bDevice)
{
  SET_SDA;       // make sure SDA released
TimeDelay2us();
  SET_SCL;       // make sure SCL released
TimeDelay2us();
  CLR_SDA;       // start condition here
TimeDelay2us();
  CLR_SCL;       // ready for clocking
TimeDelay2us();
  return(fgI2CSend(bDevice));   // slave address & R/W transmission
}
void vI2CStop(void)
{
   CLR_SDA;       // ready for stop condition
  TimeDelay2us();
   SET_SCL;       // ready for stop condition
  TimeDelay2us();
   SET_SDA;       // stop condition here
  TimeDelay2us();
}
bool fgI2CSend(byte bValue)
{
  byte bBitMask = 0x80;
// step 1 : 8-bit data transmission
while(bBitMask){
  if(bBitMask & bValue){
     SET_SDA;
   }
   else{
    CLR_SDA;
   }
   TimeDelay2us();
   SET_SCL;      // data clock in
   TimeDelay2us();
   CLR_SCL;      // ready for next clock in
   TimeDelay2us();
   bBitMask = bBitMask >> 1;  // MSB first & timing delay
  }
  SET_SDA;       // release SDA for ACK polling
  TimeDelay2us();
  SET_SCL;       // start ACK polling
TimeDelay2us();
  bBitMask = 200;      // time out protection
  do{
  TimeDelay2us();
}while(IIC_SDA && --bBitMask);  // wait for ACK, SDA=0 or bitMask=0->jump to this loop
CLR_SCL;       // end ACK polling
TimeDelay2us();
  if(!bBitMask)
  return FALSE;   // return TRUE if ACK detected
return TRUE;      // return FALSE if time out
}

void vI2CRead(byte *prValue, bool fgSeq_Read)
{
byte bBitMask = 0x80;
*prValue = 0;                   // reset data buffer
SET_SDA;       // make sure SDA released
TimeDelay2us();
// step 1 : 8-bit data reception
while(bBitMask)
{
  SET_SCL;      // data clock out
     TimeDelay2us();
     if(IIC_SDA){
   *prValue = *prValue | bBitMask; // Get all data
     }        // non-zero bits to buffer
     CLR_SCL;      // ready for next clock out
     TimeDelay2us();
     bBitMask = bBitMask >> 1;  // shift bit mask & clock delay
}
// step 2 : acknowledgement to slave
if(fgSeq_Read){
     CLR_SDA;      // ACK here for Sequential Read
}
else{
  SET_SDA;      // NACK here (for single byte read)
}
TimeDelay2us();
SET_SCL;       // NACK clock out
TimeDelay2us();
   CLR_SCL;       // ready for next clock out
TimeDelay2us();
   SET_SDA;       // release SDA
TimeDelay2us();
}
bool fgI2C_Eeprom_Write(word wAddress, byte bDataCount, byte *pValue)
{
byte addr1,addr2;
addr1 = (byte)(wAddress & 0x00ff);
addr2 = (byte)(wAddress >> 8);
if(!fgI2CStart(EEPROM)) return FALSE;
if(!fgI2CSend(addr2)) return FALSE;
if(!fgI2CSend(addr1)) return FALSE;
do{
  if(!fgI2CSend(*pValue++)) return FALSE;
}while(--bDataCount);
vI2CStop();
return TRUE;
}
bool fgI2C_Eeprom_Read(word wAddress, byte bDataCount, byte *pValue)
{
byte addr1,addr2;
addr1 = (byte)(wAddress & 0x00ff);
addr2 = (byte)(wAddress >> 8);
if(!fgI2CStart(EEPROM)) return FALSE;
if(!fgI2CSend(addr2)) return FALSE;
if(!fgI2CSend(addr1)) return FALSE;
if(!fgI2CStart(EEPROM+1)) return FALSE;
do{
  if(bDataCount==1){vI2CRead(pValue++,FG_RANDREAD);}
  else{ vI2CRead(pValue++,FG_SEQREAD);}
}while(--bDataCount);
vI2CStop();
return TRUE;

}

使用特权

评论回复
29
yumeinian| | 2010-5-31 15:39 | 只看该作者
彩色的示波器?

使用特权

评论回复
30
wsxqazx| | 2010-6-1 10:51 | 只看该作者
时间间隔不够引起!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则