AT24C16每页有16个字节,128页,共2048字节。128页分成8块,每块256字节。
I2C开始信号后,第一个字节为器件地址,由1010+3位块地址+1位读写标志组成, 3位块地址刚好可以表示8个块, 8块的器件地址分别为:0xa0、0xa2、0xa4、0xa6、0xa8、0xaa、0xac、0xae;
写数据时,可连续写完256字节,换到下一块时,需要要重新更改器件地址。
此处需特别说明,写第一块时,地址从0xa000~0xa0ff;写满后,需更新器件地址,从0xa200开始。如果写到0xa0ff后继续增加字节,地址变为0xa100,此时数据不会写到第二块,而是从第一块首地址开始覆盖。 0xa100其实是读数据地址。
读数据时,不受页、块限制,可以从给定地址一直读下去。
补充说明一点:
写数据时,还受页限制,用循环写入数据时,一次最多只能写入16个字节,超出1页地址的数据不能被写入,也不会从页开始覆盖原有数据(这个跟块有区别)
详细一点说
/* 循环发送 NumByteToWrite 个数据 */
while(NumByteToWrite--)
{
I2C_SendData(EEPROM_I2C, *pBuffer);
pBuffer++;
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(8);
}
}
这样一个循环是不可以跨页写数据的。
保存自己写的两个函数,以备以后用到,这两个函数经实际应用无误。
/**
* @brief 在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数
* 不能超过EEPROM页的大小,AT24C16每页有16个字节
* @param
* @arg pBuffer:缓冲区指针
* @arg WriteAddr:写地址
* @arg NumByteToWrite:写的字节数
* @retval 无
*/
uint32_t I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
u8 EquipAddr = 0, PageAddr = 0;
EquipAddr = (WriteAddr >> 8) & 0xfe;
PageAddr = WriteAddr & 0xff;
I2CTimeout = I2CT_LONG_TIMEOUT;
while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY)) //等空闲
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(4);
}
I2C_GenerateSTART(EEPROM_I2C, ENABLE); /* 产生起始信号 */
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)) /* 检测 EV5 事件并清除标志*/
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(5);
}
I2C_Send7bitAddress(EEPROM_I2C, EquipAddr,I2C_Direction_Transmitter); /* 发送 EEPROM 设备地址 */
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) /* 检测 EV6 事件并清除标志*/
{
if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(6);
}
I2C_SendData(EEPROM_I2C, PageAddr);
//I2C_Send7bitAddress(EEPROM_I2C, PageAddr , I2C_Direction_Transmitter); /* 发送要写入的 EEPROM 内部地址(即 EEPROM 内部存储器的地址) */
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) /* 检测 EV8 事件并清除标志*/
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(7);
}
/* 循环发送 NumByteToWrite 个数据 */
while(NumByteToWrite--)
{
I2C_SendData(EEPROM_I2C, *pBuffer);
pBuffer++;
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(8);
}
}
/* 发送停止信号 */
I2C_GenerateSTOP(EEPROM_I2C, ENABLE);
return 1;
}
/**
* @brief 将缓冲区中的数据写到I2C EEPROM中
* @param
* @arg pBuffer:缓冲区指针
* @arg WriteAddr:写地址
* @arg NumByteToWrite:写的字节数,不能超过要写入块的容量
* @retval 无
*/
void I2C_EE_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0,temp = 0;
Addr = WriteAddr % I2C_PageSize;
count = I2C_PageSize - Addr;
//开始写入的地址是EEPROM的第WriteAddr /I2C_PageSize + 1页,该页还剩余count个字节
NumOfPage = NumByteToWrite / I2C_PageSize; //计算出要写多少整数页
NumOfSingle = NumByteToWrite % I2C_PageSize;
//Addr=0,开始写入的地址是某页的开始
if(Addr == 0)
{
if(NumOfPage == 0) //要写入的字节数不足一页
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
else
{
while(NumOfPage--)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
I2C_EE_WaitEepromStandbyState();
WriteAddr += I2C_PageSize;
pBuffer += I2C_PageSize;
}
if(NumOfSingle!=0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
} //end if(NumOfPage == 0)
}
else //开始写入的地址是某页的中间某位置
{
if(NumOfPage== 0)
{
if (NumOfSingle > count) //当前面写不完,要写到下一页
{
temp = NumOfSingle - count; // temp 的数据要写到下一页
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
I2C_EE_WaitEepromStandbyState();
WriteAddr += count;
pBuffer += count;
I2C_EE_PageWrite(pBuffer, WriteAddr, temp);
I2C_EE_WaitEepromStandbyState();
}
else
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
I2C_EE_WaitEepromStandbyState();
}
}
else
{
//先把当前页剩余的count个字节写完,再将剩余的NumByteToWrite - count个字节写到后续页中
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / I2C_PageSize;
NumOfSingle = NumByteToWrite % I2C_PageSize;
if(count != 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
I2C_EE_WaitEepromStandbyState();
WriteAddr += count;
pBuffer += count;
}
while(NumOfPage--)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
I2C_EE_WaitEepromStandbyState();
WriteAddr += I2C_PageSize;
pBuffer += I2C_PageSize;
}
if(NumOfSingle != 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
}
}
}