yllqabz 发表于 2020-4-26 08:56:31

24LC024读写问题

针对这种EEPROM器件,根据芯片手册配置,不超过16字节读写正常,超过就不对,会覆盖之前的内容,就是说永远只写前16个地址,后面的地址没有写上,看了半天也不知道是怎么回事?有没有哪位用过,给个提示。主控制器用的STM32F103。读写控制代码如下:#define         ADDR_24LC02_Write         0xA0
#define         ADDR_24LC02_Read         0xA1
#define         BufferSize                         34       


HAL_I2C_Mem_Write(&hi2c2, ADDR_24LC02_Write, 0, I2C_MEMADD_SIZE_8BIT, WriteBuffer, BufferSize, 0x10);
HAL_I2C_Mem_Read(&hi2c2, ADDR_24LC02_Read, 0, I2C_MEMADD_SIZE_8BIT, ReadBuffer, BufferSize, 0x10);


WriteBuffer写入数据依次为1-34;ReadBuffer读取仅有33,34,19,20,21,22,23,24,25,26,27,28,29,30,31,32。只能读到16个地址数,我认为是写的时候只写了16个地址,数据一直在前16个地址上覆盖。

toofree 发表于 2020-4-26 09:11:19

EEPROM不能直接跨页写,要跨页的话,得重新指定一次新的页地址,同时得有一次停止位。
理解一下这段代码,其中NumOfPage、NumOfSingle两个变量,以及I2C_FLASH_PAGESIZE。
/**
* @briefWrites buffer of data to the I2C EEPROM.
* @parampBuffer : pointer to the buffercontaining the data to be
*   written to the EEPROM.
* @paramWriteAddr : EEPROM's internal address to write to.
* @paramNumByteToWrite : number of bytes to write to the EEPROM.
* @retval None
*/
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, count = 0;
uint16_t Addr = 0;

Addr = WriteAddr % I2C_FLASH_PAGESIZE;
count = I2C_FLASH_PAGESIZE - Addr;
NumOfPage =NumByteToWrite / I2C_FLASH_PAGESIZE;
NumOfSingle = NumByteToWrite % I2C_FLASH_PAGESIZE;

/* If WriteAddr is I2C_FLASH_PAGESIZE aligned*/
if(Addr == 0)
{
    /* If NumByteToWrite < I2C_FLASH_PAGESIZE */
    if(NumOfPage == 0)
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_FLASH_PAGESIZE */
    else
    {
      while(NumOfPage--)
      {
      I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_FLASH_PAGESIZE);
      I2C_EE_WaitEepromStandbyState();
      WriteAddr +=I2C_FLASH_PAGESIZE;
      pBuffer += I2C_FLASH_PAGESIZE;
      }

      if(NumOfSingle!=0)
      {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
      }
    }
}
/* If WriteAddr is not I2C_FLASH_PAGESIZE aligned*/
else
{
    /* If NumByteToWrite < I2C_FLASH_PAGESIZE */
    if(NumOfPage== 0)
    {
      /* If the number of data to be written is more than the remaining space
      in the current page: */
      if (NumByteToWrite > count)
      {
      /* Write the data conained in same page */
      I2C_EE_PageWrite(pBuffer, WriteAddr, count);
      I2C_EE_WaitEepromStandbyState();      
      
      /* Write the remaining data in the following page */
      I2C_EE_PageWrite((uint8_t*)(pBuffer + count), (WriteAddr + count), (NumByteToWrite - count));
      I2C_EE_WaitEepromStandbyState();      
      }      
      else      
      {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();      
      }   
    }
    /* If NumByteToWrite > I2C_FLASH_PAGESIZE */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =NumByteToWrite / I2C_FLASH_PAGESIZE;
      NumOfSingle = NumByteToWrite % I2C_FLASH_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_FLASH_PAGESIZE);
      I2C_EE_WaitEepromStandbyState();
      WriteAddr +=I2C_FLASH_PAGESIZE;
      pBuffer += I2C_FLASH_PAGESIZE;
      }
      if(NumOfSingle != 0)
      {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
      }
    }
}
}

/**
* @briefWrites more than one byte to the EEPROM with a single WRITE cycle.
* @note   The number of byte can't exceed the EEPROM page size.
* @parampBuffer : pointer to the buffer containing the data to be
*   written to the EEPROM.
* @paramWriteAddr : EEPROM's internal address to write to.
* @paramNumByteToWrite : number of bytes to write to the EEPROM.
* @retval None
*/
void I2C_EE_PageWrite(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t NumByteToWrite)
{
/* While the bus is busy */
while(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));

/* Send START condition */
I2C_GenerateSTART(I2C_EE, ENABLE);

/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));

/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C_EE, EEPROM_ADDRESS, I2C_Direction_Transmitter);

/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

#ifdef EE_M24C08

/* Send the EEPROM's internal address to write to : only one byte Address */
I2C_SendData(I2C_EE, WriteAddr);

#elif defined(EE_M24C64_32)

/* Send the EEPROM's internal address to write to : MSB of the address first */
I2C_SendData(I2C_EE, (uint8_t)((WriteAddr & 0xFF00) >> 8));

/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

/* Send the EEPROM's internal address to write to : LSB of the address */
I2C_SendData(I2C_EE, (uint8_t)(WriteAddr & 0x00FF));

#endif /* EE_M24C08 */

/* Test on EV8 and clear it */
while(! I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

/* While there is data to be written */
while(NumByteToWrite--)
{
    /* Send the current byte */
    I2C_SendData(I2C_EE, *pBuffer);

    /* Point to the next byte to be written */
    pBuffer++;

    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

/* Send STOP condition */
I2C_GenerateSTOP(I2C_EE, ENABLE);
}

/**
* @briefWait for EEPROM Standby state
* @paramNone
* @retval None
*/
void I2C_EE_WaitEepromStandbyState(void)      
{
__IO uint16_t SR1_Tmp = 0;

do
{
    /* Send START condition */
    I2C_GenerateSTART(I2C_EE, ENABLE);

    /* Read I2C_EE SR1 register to clear pending flags */
    SR1_Tmp = I2C_ReadRegister(I2C_EE, I2C_Register_SR1);

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C_EE, EEPROM_ADDRESS, I2C_Direction_Transmitter);

}while(!(I2C_ReadRegister(I2C_EE, I2C_Register_SR1) & 0x0002));

/* Clear AF flag */
I2C_ClearFlag(I2C_EE, I2C_FLAG_AF);

/* STOP condition */   
I2C_GenerateSTOP(I2C_EE, ENABLE);
}


mylovemcu 发表于 2020-4-26 09:15:11

仔细看一下那两个读写函数最后那个0x10应该是数据长度改一下就好了

yllqabz 发表于 2020-4-26 09:29:52

mylovemcu 发表于 2020-4-26 09:15
仔细看一下那两个读写函数最后那个0x10应该是数据长度改一下就好了

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
最后那个是超时吧... ...

likang1202 发表于 2020-4-26 09:39:56

toofree 发表于 2020-4-26 09:11
EEPROM不能直接跨页写,要跨页的话,得重新指定一次新的页地址,同时得有一次停止位。
理解一下这段代码, ...

围观大佬

yllqabz 发表于 2020-4-26 10:04:44

if(HAL_I2C_Mem_Write(&hi2c2, ADDR_24LC02_Write, 0, I2C_MEMADD_SIZE_8BIT, WriteBuffer, 16, 0x10) == HAL_OK)
                {
                        HAL_Delay(10);               
               
                        if(HAL_I2C_Mem_Write(&hi2c2, ADDR_24LC02_Write, 16, I2C_MEMADD_SIZE_8BIT, WriteBuffer+16, 16, 0x10) == HAL_OK)
                        {
                                HAL_Delay(10);
                               
                                if(HAL_I2C_Mem_Write(&hi2c2, ADDR_24LC02_Write, 32, I2C_MEMADD_SIZE_8BIT, WriteBuffer+32, 16, 0x10) == HAL_OK)
                                {
                                        HAL_Delay(10);
                                }
                        }
                }
我想了一个最简单的办法,适合不需要太多存储的情况,既然不能跨页连写,那么我就采用随机写,连续读的方式,就不用修改那么多。

发表于 2020-4-26 10:10:44

楼主,注意看手册中E2的每页大小,页数。写入的时候需要换页,读取可以不用。

Dandjinh 发表于 2020-4-26 10:35:56

EEPROM参数里有个页写时间,一般是5ms,意思是每次写换页要等5ms才能切换下一页,所以写要注意时序。读没要求。

Dandjinh 发表于 2020-4-26 10:36:52

EEPROM参数里有个页写时间,一般是5ms,意思是每次写换页要等5ms才能切换下一页,所以写要注意时序。读没要求。

yllqabz 发表于 2020-4-26 12:33:58

Dandjinh 发表于 2020-4-26 10:36
EEPROM参数里有个页写时间,一般是5ms,意思是每次写换页要等5ms才能切换下一页,所以写要注意时序。读没要 ...

意思是写完一次后加长HAL_Delay时间?
页: [1] 2
查看完整版本: 24LC024读写问题