i2c驱动eeprom,写入读出之间必须加上2ms延迟是怎么回事

发布: 2009-7-17 14:14 | 作者: memorable1999 | 来源: StmFans思蜕盟 OPELC 自由电子联盟

参考了lvhaian 的"STM32 硬件 I2C 驱动 AT24C08, AT24C64 程序"和豆皮的例程。
我能成功的对24C64进行读写了,但是在调试过程中,我发现在连续运行I2C_EE_MultiByteWrite和I2C_EE_MultiByteRead
这两个函数时,会运行不过去,但是在I2C_GenerateSTOP(I2C1, ENABLE);之后加上2ms左右的延迟,再进行度的操作就可以了
我看在我所参考的两个例程里都没有延迟这一步,那么我这里需要延迟应该是哪里的事呢?





void I2C_EE_MultiByteWrite(u8* pBuffer, u16 WriteAddr, u8 NumByteToWrite)
{
  u8 i = 0;
   //打开I2C,开始发送过程
  I2C_GenerateSTART(I2C1, ENABLE);
  //Uart1_PutString("I2C_GenerateSTART\r\n" , strlen("I2C_GenerateSTART\r\n"));

//设置主机模式
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  
//Uart1_PutString("I2C_CheckEvent_MASTER\r\n" , strlen("I2C_CheckEvent_MASTER\r\n"));

  //发送片选,选择哪一片区域写。i2C地址区分

  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  //Uart1_PutString("I2C_Send7bitAddress_I2C_Direction_Transmitter\r\n" , strlen("I2C_Send7bitAddress_I2C_Direction_Transmitter\r\n"));

  
//等待这次选择过程完成
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//  Uart1_PutString("I2C_CheckEvent_MASTER_TRANSMITTER\r\n" , strlen("I2C_GenerateSTART_MASTER_TRANSMITTER\r\n"));
   
  /* Send the EEPROM's internal address to write to */
   I2C_SendData(I2C1, (u8)WriteAddr>>8);       
  //Uart1_PutString("I2C_SendWriteAddrH\r\n" , strlen("I2C_SendWriteAddrH\r\n"));

//等待字节发送完成
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Uart1_PutString("I2C_CheckEvent_MASTER_BYTE_TRANSMITTED\r\n" , strlen("I2C_GenerateSTART_MASTER_BYTE_TRANSMITTED\r\n"));
  I2C_SendData(I2C1, (u8)WriteAddr);
// Uart1_PutString("I2C_SendWriteAddrL\r\n" , strlen("I2C_SendWriteAddrL\r\n"));

  //等待字节发送完成
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
Uart1_PutString("I2C_CheckEvent_MASTER_BYTE_TRANSMITTED\r\n" , strlen("I2C_GenerateSTART_MASTER_BYTE_TRANSMITTED\r\n"));

  for (i = 0; i < NumByteToWrite; i++,pBuffer++)
  {

      I2C_SendData(I2C1, *pBuffer);
     //Uart1_PutString("SendData\r\n" , strlen("SendData\r\n"));
     //Uart1_PutChar(*pBuffer);
      while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    //Uart1_PutString("I2C_CheckEvent_MASTER_BYTE_TRANSMITTED\r\n" , strlen("I2C_GenerateSTART_MASTER_BYTE_TRANSMITTED\r\n"));

  }
//过程结束
  I2C_GenerateSTOP(I2C1, ENABLE);
// Uart1_PutString("I2C_GenerateSTOP\r\n" , strlen("I2C_GenerateSTOP\r\n"));
  // msdelay();
  delaytime(25000)  ;
}


void I2C_EE_MultiByteRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead)
{  

  u8 i = 0;
//开始发送
  I2C_GenerateSTART(I2C1, ENABLE);

  //设置自己为主机
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  

//设置自己为发送
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  
//等待主机发送模式设置成功
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
      
//Send the EEPROM's internal address to read from
//发送地址码,即要读的地址,16 位分为两个8位分别发送
   I2C_SendData(I2C1, (u8)(ReadAddr>>8));       
  
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  I2C_SendData(I2C1, (u8)ReadAddr);
  
//等待主机发送过程完成
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


  I2C_GenerateSTOP(I2C1, ENABLE);


  I2C_GenerateSTART(I2C1, ENABLE);


  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

//设置从机地址,并设置主机为接收模式

  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);

  
//确认该过程完成
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

      for (i = NumByteToRead; i > 0; i--,pBuffer++)
    {
        if (i == 1)
                {
                //关闭I2C的应答功能
                I2C_AcknowledgeConfig(I2C1, DISABLE);
                 //如果接收到信息了
                 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));  
                *pBuffer = I2C_ReceiveData(I2C1);
                 //开启主机I2C的应答功能
        
                I2C_AcknowledgeConfig(I2C1, ENABLE);

                }
        else
            {
            //开启主机I2C的应答功能
                I2C_AcknowledgeConfig(I2C1, ENABLE);
                //如果接收到信息了
                 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));  
                 
                *pBuffer = I2C_ReceiveData(I2C1);  
                i=i;
                }
    }

//过程结束
  I2C_GenerateSTOP(I2C1, ENABLE);
delaytime(25000)  ;  
}


顺便再问一下,假如我用的8M晶振,rcc设置如下,那么进行一次自加,用的时间应该按什么来算?
RCC_HCLKConfig(RCC_SYSCLK_Div1);
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
bbandpp (2009-7-17 16:58:28)
理论上必须加几ms的延时才能把数据写到e2里,所以这延时你是必须加的。
下面那问题就不确定了,你可以用示波器看看。
jcx0324 (2009-7-20 10:22:33)
对EEPROM操作的话是要加延时的,不然会出错
beeqer (2009-8-10 11:08:36)
为什么非要加延时呢?????
binglin (2009-8-10 11:51:47)
加延时是等待EEPROM操作完成。
win2000_li (2009-8-10 14:34:38)
还是要按照人家的手册来做。。。

所以说延时是必须的。。。。。。。。。。。。。。。。。。