EEPROM AT24C16读写注意事项

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();
            }
        }
    }  
}

 

你可能感兴趣的:(EEPROM,STM32)