1

I'm using STM32 with EEPROM 512KB, i inilized the project using STM32CubeMX

PB7 as I2C_SDA PB6 as I2C_SCL

Generated Functions

I2C_HandleTypeDef hi2c1;

/* I2C1 init function */
void MX_I2C1_Init(void)
{
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    /**I2C1 GPIO Configuration    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA 
    */
    GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();

    /* I2C1 interrupt Init */
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }
}

void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{

  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspDeInit 0 */

  /* USER CODE END I2C1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_I2C1_CLK_DISABLE();

    /**I2C1 GPIO Configuration    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA 
    */
    HAL_GPIO_DeInit(GPIOB, I2C_SCL_Pin|I2C_SDA_Pin);

    /* I2C1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
    HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspDeInit 1 */

  /* USER CODE END I2C1_MspDeInit 1 */
  }
} 

In main i call MX_I2C1_Init() then HAL_I2C_MspInit(&hi2c1) , but when i call

while(HAL_I2C_Mem_Write(hi2c,(uint16_t)DevAddress,(uint16_t)MemAddress,I2C_MEMADD_SIZE_8BIT,pData,(uint16_t)16-MemAddress,1000)!= HAL_OK && 1);

This while loop never returns HAL_OK, so i can not processed to read the written data to verify. My EEPROM is

CAT24C512WI-GT3OSCT-ND and the A0->A2, WP are connected to ground

mustafabarakat
  • 409
  • 1
  • 6
  • 22

5 Answers5

0

Try this. First call the device readiness check and make sure that the device is ready.

while(HAL_I2C_IsDeviceReady(&hi2c1, I2C_EEPROM_ADDRESS, 64, HAL_MAX_DELAY)!= HAL_OK); and then

while(HAL_I2C_Mem_Write(&hi2c1, I2C_EEPROM_ADDRESS, eeStart, I2C_MEMADD_SIZE_8BIT, pRamStart, num, HAL_MAX_DELAY)!= HAL_OK); 64 in "HAL_I2C_IsDeviceReady" - the number of attempts. Sometimes one or more times is not enough. Check. Need &hi2c1, not hi2c1

0

All right! The first time will be "true", but after writing to the eeprom, you need to make sure that the recording is completed and the eeprom is ready for the next step. You have not been & before hi2c1 in the last line. And, maybe for EEPROM 512kb you need to specify "I2C_MEMADD_SIZE_16BIT" and not "I2C_MEMADD_SIZE_8BIT"?

0

Immediately after the call to HAL_I2C_MspInit(&hi2c1) you need to check the state of the i2c whit

    while(HAL_I2C_Mem_Write(
                       &hi2c1,
                       I2C_EEPROM_ADDRESS,
                       eeStart,
                       I2C_MEMADD_SIZE_8BIT,
                       pRamStart,
                       num,
                       HAL_MAX_DELAY) == HAL_BUSY);

if the program is stuck in the while loop always returning HAL_BUSY its very likely that you are using a micro controller whit a hardware bug you can check the errata of the stm32f10xx8 in page 26, this happened to me whit the stm32f103c8t6 which is of the STM32F10xx8 family (if your device is not of this family you can still try the second solution listed below).

the solution is listed in the errata and is this:

Workaround The SCL and SDA analog filter output is updated after a transition occurs on the SCL and SDA line respectively. The SCL and SDA transition can be forced by software configuring the I2C I/Os in output mode. Then, once the analog filters are unlocked and output the SCL and SDA lines level, the BUSY flag can be reset with a software reset, and the I2C can enter master mode. Therefore, the following sequence must be applied:

  1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
  2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR)
  3. Check SCL and SDA High level in GPIOx_IDR.
  4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
  5. Check SDA Low level in GPIOx_IDR.
  6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
  7. Check SCL Low level in GPIOx_IDR.
  8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
  9. Check SCL High level in GPIOx_IDR.
  10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
  11. Check SDA High level in GPIOx_IDR.
  12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
  13. Set SWRST bit in I2Cx_CR1 register.
  14. Clear SWRST bit in I2Cx_CR1 register.
  15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register.

another solution is adding

__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(2);
__HAL_RCC_I2C1_RELEASE_RESET();

to HAL_I2C_MspInit(...) after __HAL_RCC_I2C1_CLK_ENABLE(); so that the final solution is

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    /**I2C1 GPIO Configuration    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA 
    */
    GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
    //--------------added code :D -----------------------------------
    __HAL_RCC_I2C1_FORCE_RESET();
    HAL_Delay(2);
    __HAL_RCC_I2C1_RELEASE_RESET();
    //-------------end of added code---------------------------------

    /* I2C1 interrupt Init */
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }
}

the second solution may or may not work whit you because its not the solution recommended by ST but in my case and many others works although i wouldn't trust this solution in a product, that depends on the model of your micro you can play whit the delay if 2 doesn't work it really depends on which micro controller you are using.

0

I developed an EEPROM library, you can check it and use it for the project.

Features:

  • Support All AT24C Memories with auto data control
  • Support Write Protect
  • Support Multi-Line Address
  • Optional Pin Configurations
  • High-Speed Memory Library
  • Support AVR & ARM Cortex M

Library Link

-1

How do you determine that the recording, which requires considerable time, by the standards of the processor, is completed? To do this, there is this procedure HAL_I2C_IsDevitseReady.