cancel
Showing results for 
Search instead for 
Did you mean: 

I2C EEPROM Memory accessing

rohittheozzy
Associate II
Posted on March 19, 2015 at 13:09

Hello, I am using STM32F0 HAL Drivers to access external EEPROM 24C64 with STM32F The functions I am using areHAL_I2C_Mem_Write/Read but the communication is not always successful. Also it worked while using smd eeprom but while using dip IC it does not work. I have given the code below for reference.

Please let me know if I am missing something here.

/**
******************************************************************************
* File Name : I2C.c
* Date : 13/10/2014 19:30:51
* Description : This file provides code for the configuration
* of the I2C instances.
******************************************************************************
*
* COPYRIGHT(c) 2014 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include ''i2c.h''
#include ''gpio.h''
/* USER CODE BEGIN 0 */
//uint8_t Data2Bwritten[8] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0xF000F0FF;//0x30108AFF;//0x00101D7C 0x2000090E;
hi2c1.Init.OwnAddress1 = 0;//(0xA0>>1);
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
hi2c1.Init.OwnAddress2 = 0xFF;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
HAL_I2C_Init(&hi2c1);
//I2C_TransferConfig();
/**Configure Analogue filter 
*/
HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)
{
/* Peripheral clock enable */
__I2C1_CLK_ENABLE();
/**I2C1 GPIO Configuration 
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA 
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
if(hi2c->Instance==I2C1)
{
/* Peripheral clock disable */
__I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration 
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA 
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);
}
} 
void EEMEM_Write(uint16_t memAdd, uint8_t * Data2Bwritten, uint16_t len)
{
uint32_t Try_Count = EEPROM_ACESS_TRY_CNT;
while(HAL_I2C_IsDeviceReady(&hi2c1, EEPROM_1_ADDRESS,EEPROM_ACESS_TRY_CNT,EEPROM_ACESS_TIMEOUT) != HAL_OK)
{
}
while(HAL_I2C_Mem_Write(&hi2c1, EEPROM_1_ADDRESS, memAdd, 2, (uint8_t *)Data2Bwritten, len, EEPROM_ACESS_TIMEOUT) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
return;
}
else
{
if(Try_Count-- == 0)
return; 
} 
}
}
void EEMEM_Read(uint16_t memAdd, uint8_t * Data2Bwritten, uint16_t len)
{
uint32_t Try_Count = EEPROM_ACESS_TRY_CNT;
while(HAL_I2C_IsDeviceReady(&hi2c1, EEPROM_1_ADDRESS,EEPROM_ACESS_TRY_CNT,EEPROM_ACESS_TIMEOUT) != HAL_OK)
{
}
while(HAL_I2C_Mem_Read(&hi2c1, EEPROM_1_ADDRESS, memAdd, 2, (uint8_t *)Data2Bwritten, len, EEPROM_ACESS_TIMEOUT) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
return;
}
else
{
if(Try_Count-- == 0)
return; 
} 
}
return;
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

#i2c-writing-page-boundaries #i2c #hal-diver #stm32f0-i2c
4 REPLIES 4
Mikk Leini
Senior
Posted on March 20, 2015 at 11:05

You define SDA and SCL as push-pull with GPIO_MODE_AF_PP. You should use GPIO_MODE_AF_OD. I've not used F0 so not 100% certain if it exists, but check it out.

Also some questions:

Did you enable GPIOB clock?

Do you have external pull-ups on SDA and SCL or you only rely on internal ones? I think internal ones are have too large resistance and therefore the rise time might cause problems.

Try lowering the bitrate. Also try without analog filter.

If possible, check the SDA and SCL slew rates with oscilloscope. And with oscilloscope or logic analyzer check that the communication is correct (ACK's are sent and so on).

gio
Associate
Posted on April 02, 2015 at 16:45

I wrote these few lines in order to write i2c memories considering page boundaries.

HAL_StatusTypeDef GIO_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint16_t WritePageSize)

{

uint32_t sizetmp = 0;

uint16_t WritePageSizeMask;  

HAL_StatusTypeDef error_code;

  if(WritePageSize > 128) WritePageSize = 128;

  WritePageSizeMask = WritePageSize - 1;

  if(((WritePageSizeMask | WritePageSize) + 1) != (WritePageSize << 1))

  {  

    return  HAL_ERROR;  // WritePageSize must be power of 2

  }

  while(Size)

  {  

    sizetmp = WritePageSize - (MemAddress & WritePageSizeMask);

    if(sizetmp > Size) sizetmp = Size;

    if(error_code = HAL_I2C_Mem_Write(hi2c, DevAddress,  MemAddress, MemAddSize, pData, sizetmp, Timeout)) return error_code;

    MemAddress += sizetmp;

    pData += sizetmp;    

    Size -= sizetmp;

  }

  return error_code;  

}

kevinliao
Associate II
Posted on April 04, 2015 at 16:21

Hi, bernabe_.giorgio

You can just use the DMA mode. and enable the     

hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;

There is example  STM32Cube_FW_L1_V1.0.0\Projects\STM32L152D_EVAL\Examples\I2C\I2C_EEPROM\

Kevin

kaihofmann
Associate II
Posted on September 02, 2015 at 13:59

Hi there,

I'm new to this forum and just wanted to paste some code I just wrote and tested to make the STM32F405 work together with a 24AA64 EEPROM. Thank you for this post, it helped me a lot.

I used the STM32CubeX-software in its current version to create the HAL with FreeRTOS-support for my board.

This code enables memory block reading and writing with the maximum page-wise amount of data allowed for this eeprom. I found out that the eeprom (used at 400kHz) needs some time to write out data to its own structure, so there are some wait-states between the page-writes to avoid NAKs from the EEPROM on the I²C. Propably the wait-states when reading are not necessary.

I hope the code-snippet is useful to somebody else.

//---------------------------------------------------------

#define EEPROM_ADDRESS              0xAE

#define EEPROM_MAXPKT             32              //(page size)

#define EEPROM_MEMBASEADDRESS   (uint16_t)0x100 //must be multiple of (EEPROM_MAXPKT)

#define EEPROM_WRITE              5               //time to wait in ms

#define EEPROM_TIMEOUT             2*EEPROM_WRITE  //timeout while writing

I2C_HandleTypeDef hi2c2;

/* I2C2 init function */

void SysHW_I2C_Init(void)

{

  hi2c2.Instance = I2C2;

  hi2c2.Init.ClockSpeed = 400000;

  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;

  hi2c2.Init.OwnAddress1 = 0;

  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;

  hi2c2.Init.OwnAddress2 = 0;

  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;

  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

  HAL_I2C_Init(&hi2c2);

}

HAL_StatusTypeDef SysHW_readEEPROM(uint8_t* MemTarget, uint16_t Size)

{

    uint16_t Counter = 0;

    HAL_StatusTypeDef Result = HAL_OK;

    while (Counter < Size && Result == HAL_OK)

    {

        uint16_t Diff = Size - Counter;

        if (Diff >= EEPROM_MAXPKT)

        {

            //Multi-Byte

            Result = HAL_I2C_Mem_Read(&hi2c2, EEPROM_ADDRESS, EEPROM_MEMBASEADDRESS + Counter, I2C_MEMADD_SIZE_16BIT, &MemTarget[Counter], EEPROM_MAXPKT, EEPROM_TIMEOUT);

            Counter += EEPROM_MAXPKT;

        }

        else

        {

            //and the remaining ones...low packet size

            Result = HAL_I2C_Mem_Read(&hi2c2, EEPROM_ADDRESS, EEPROM_MEMBASEADDRESS + Counter, I2C_MEMADD_SIZE_16BIT, &MemTarget[Counter], Diff, EEPROM_TIMEOUT);

            Counter += Diff;

        }

        HAL_Delay(EEPROM_WRITE);

    }

    return Result;

}

HAL_StatusTypeDef SysHW_writeEEPROM(uint8_t* MemSource, uint16_t Size)

{

    uint16_t Counter = 0;

    HAL_StatusTypeDef Result = HAL_OK;

    while (Counter < Size && Result == HAL_OK)

    {

        uint16_t Diff = Size - Counter;

        if (Diff >= EEPROM_MAXPKT)

        {

            //Multi-Byte

            Result = HAL_I2C_Mem_Write(&hi2c2, EEPROM_ADDRESS, EEPROM_MEMBASEADDRESS + Counter, I2C_MEMADD_SIZE_16BIT, &MemSource[Counter], EEPROM_MAXPKT, EEPROM_TIMEOUT);

            Counter += EEPROM_MAXPKT;

        }

        else

        {

            //and the remaining ones...low packet size

            Result = HAL_I2C_Mem_Write(&hi2c2, EEPROM_ADDRESS, EEPROM_MEMBASEADDRESS + Counter, I2C_MEMADD_SIZE_16BIT, &MemSource[Counter], Diff, EEPROM_TIMEOUT);

            Counter += Diff;

        }

        HAL_Delay(EEPROM_WRITE);

    }

    return Result;

}