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);
我能成功的对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);

下面那问题就不确定了,你可以用示波器看看。
所以说延时是必须的。。。。。。。。。。。。。。。。。。