cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F30x I2C BR24L04 EEPROM Read All Zeros

Posted on March 09, 2017 at 12:10

Hi all. I'm trying to read the eeprom I'm using the std_periph_library. I can send the address information to eeprom and get the ack bits correctly. I've connected pullups on the SCL and SDA pins. I'm using the I2C1 (I2Cx)

const uint8_t DEVICE[] = {0xA0, 0xA4};

const uint16_t WP[] = {GPIO_Pin_10, GPIO_Pin_11};

&sharpdefine WP_PORT        GPIOB

&sharpdefine WP_DISABLE(p) GPIO_WriteBit(WP_PORT, p, Bit_RESET)

&sharpdefine WP_ENABLE(p) GPIO_WriteBit(WP_PORT, p, Bit_SET)

&sharpdefine I2Cx_PIN_ENABLE() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE)

&sharpdefine I2Cx_SCL_PIN   GPIO_Pin_8

&sharpdefine I2Cx_SDA_PIN   GPIO_Pin_9

&sharpdefine I2Cx_PIN_PORT  GPIOB

&sharpdefine I2Cx_CLK_ENABLE() RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE)

void RMSNO_Init(void)

{

 I2C_InitTypeDef i2c;

 GPIO_InitTypeDef gpio;

 NVIC_InitTypeDef nvic;

 gpio.GPIO_Pin = I2Cx_SCL_PIN | I2Cx_SDA_PIN;

 gpio.GPIO_Mode = GPIO_Mode_AF;

 gpio.GPIO_OType = GPIO_OType_PP;

 gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;

 gpio.GPIO_Speed = GPIO_Speed_50MHz;

 I2Cx_PIN_ENABLE();

 GPIO_Init(I2Cx_PIN_PORT, &gpio);

 GPIO_PinAFConfig(I2Cx_PIN_PORT, GPIO_PinSource8, GPIO_AF_4);

 GPIO_PinAFConfig(I2Cx_PIN_PORT, GPIO_PinSource9, GPIO_AF_4);

 i2c.I2C_Timing = I2Cx_TIMING;

 i2c.I2C_Ack = I2C_Ack_Enable;

 i2c.I2C_Mode = I2C_Mode_I2C;

 i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

 i2c.I2C_AnalogFilter = I2C_AnalogFilter_Enable;

 i2c.I2C_DigitalFilter = 0x00;

 i2c.I2C_OwnAddress1 = 0x00;

 I2Cx_CLK_ENABLE();

 RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);

 

 I2C_Init(I2Cx, &i2c);

 I2C_Cmd(I2Cx, ENABLE);

 /* Enable transfer address matched, transfer completed */

 //I2C_ITConfig(I2Cx, I2C_IT_ADDR, ENABLE);

 //I2C_ITConfig(I2Cx, I2C_IT_TCI, ENABLE);

 /* Set transfer direction */

 I2C_MasterRequestConfig(I2Cx,

                         I2C_Direction_Transmitter | I2C_Direction_Receiver);

  /* Ehable auto end mode */

 I2C_AutoEndCmd(I2Cx, ENABLE);

 /* Set interrupt */

 nvic.NVIC_IRQChannel = I2C1_EV_IRQn;

 nvic.NVIC_IRQChannelCmd = ENABLE;

 nvic.NVIC_IRQChannelPreemptionPriority = 0x05;

 nvic.NVIC_IRQChannelSubPriority = 0x05;

 NVIC_Init(&nvic);

 gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

 gpio.GPIO_Mode = GPIO_Mode_OUT;

 gpio.GPIO_OType = GPIO_OType_PP;

 gpio.GPIO_PuPd = GPIO_PuPd_UP;

 GPIO_Init(WP_PORT, &gpio);

 WP_ENABLE(WP[0]);

 WP_ENABLE(WP[1]);

}

static int EEPROMRead(uint8_t dev, uint16_t addr, uint8_t *buf, uint16_t n)

{

  uint8_t addrH;

 uint8_t addrL;

 int i;

 if (buf == NULL)

  return -1;

 /* Check busy flag */

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2;

 }

 /*

    Configure the slave address, nbytes, reload,

    end mode and start stop generation

  */

 I2C_TransferHandling(I2Cx, dev, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2;

 }

 addrH = (uint8_t)(addr >> 8);

 addrL = (uint8_t)addr;

 /* Send register address high byte */

 I2C_SendData(I2Cx, addrH);

 I2C_SendData(I2Cx, addrL);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2;

 }

 /* Set the page read bit */

 if (n > 1)

  dev |= (PAGE_MASK);

 

 I2C_TransferHandling(I2Cx, dev, n, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

 for (i = 0; i < n; i++)

 {

  /* Wait until RXNE flag is set */

  EEPROMTimeout = I2Cx_TIMEOUT;

  while(I2C_GetFlagStatus(I2Cx, I2C_ISR_RXNE) == RESET)

  {

    if ((EEPROMTimeout--) == 0)

    return -2;

  }

  /* Read data from RXDR */

   buf[i] = I2C_ReceiveData(I2Cx);

 }

 return 0;

}

These are the codes.

0690X00000606WHQAY.png

The waveforms attached. Device is not empty but I'm getting all zeros. WP pins are write protection pins and when they high level write is prohibited. When I want to call read;

WP_DISABLE(WP[device]);

 retval = EEPROMRead(DEVICE[device], addr, d, n);

 WP_ENABLE(WP[device]);

here is device is 0 or 1.

Edit: I've  checked the write function and I realized that the write did not complete. Timeout variable is going zero before TC is set. But STOPF is setting by hw. Here is my write function.

static int EEPROMWrite(uint8_t dev, uint16_t addr, uint8_t *buf, uint16_t n)

{

 uint8_t addH;

 uint8_t addL;

 int i;

 /* Check the buffer */

 if (buf == NULL)

  return -1;

 

 /* Check busy flag */

  EEPROMTimeout = I2Cx_TIMEOUT;

 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET)

  {

  if ((EEPROMTimeout--) == 0)

   return -2;

  }

 /* Set the page bit */

 if (n > 1)

  dev |= PAGE_MASK;

 /* Configure the communication parameters */

 I2C_TransferHandling(I2Cx, dev, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

 /* Wait until TXIS flag is set */

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2;

 }

 addH = (uint8_t)(addr >> 8);

 addL = (uint8_t)addr;

 /* Send 16-bit register address */

 I2C_SendData(I2Cx, addH);

 I2C_SendData(I2Cx, addL);

 

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2;

 }

 /* Configure the communication parameters */

 I2C_TransferHandling(I2Cx, dev, n, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

 for (i = 0; i < n; i++)

  I2C_SendData(I2Cx, buf[i]);

 

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -2; // Here is timeout occuring.

 }

 return 0;

}

Should I check the TC flag for each data or is that true. EEPROM addresses are 16-bit.

#stm32f30x #i2c #eeprom
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on March 31, 2017 at 15:31

Hi All,

I've solved the problem. There is some missing information in the BR24L04's datasheet. Address is not 16-bit so P0 is the page bit. I've though it is 'page reading or writing bit' but it is not, it is used to select first/second page of 8-bit addressable area. The device is automatically increasing the address while reading operation, there is no limit. In writing, just 16-byte could be written sequentially. In both situations, if the device sees the stop, it stops suddenly. I've changed the read function and now read has no problem. Thanks to everyone. Here is the read function, maybe help someone;

static int EEPROMRead(uint8_t dev, uint16_t addr, uint8_t *buf, uint16_t n)

{

 uint8_t addrL;

 int i;

 if (buf == NULL)

  return -1; // Buffer null

  I2C_ClearFlag(I2Cx, I2C_ISR_STOPF);

 I2C_ClearFlag(I2Cx, I2C_ISR_NACKF);

 

 /* Set the page bit */

 if (addr > (uint16_t)0x00FF)

  dev |= (PAGE_MASK);

 

 /* Check busy flag */

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -5; // Bus busy timeout

 }

 /*

    Configure the slave address, nbytes, reload,

    end mode and start stop generation

  */

 I2C_TransferHandling(I2Cx, dev, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while((I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) &&\

      (I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET))

 {

   if ((EEPROMTimeout--) == 0)

   return -4; // Start write timeout handling problem

 }

 addrL = (uint8_t)addr;

 

 /* Send register address high byte */

 I2C_SendData(I2Cx, addrL);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -3; // Transmit timeout problem

 }

 if (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXE) == RESET)

  I2Cx->ISR |= I2C_ISR_TXE;

 I2C_TransferHandling(I2Cx, dev, n, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

 for (i = 0; i < n; i++)

 {

  /* Wait until RXNE flag is set */

  EEPROMTimeout = I2Cx_TIMEOUT;

  while(I2C_GetFlagStatus(I2Cx, I2C_ISR_RXNE) == RESET)

  {

    if ((EEPROMTimeout--) == 0)

    return -2; // Receive timeout problem

  }

  /* Read data from RXDR */

   buf[i] = I2C_ReceiveData(I2Cx);

 }

 return 0;

}

View solution in original post

8 REPLIES 8
Posted on March 11, 2017 at 11:47

So you have two EEPROMs on a single bus? Do they have set different addresses? Those ROHM parts appear to have model-dependent addressing options; particularly, BR24L04-W appears ignore the A0 pin. Try to disconnect one of them. Try to write and then read back.

JW

Posted on March 16, 2017 at 11:59

Thanks for reply

Waclawek.Jan

‌ yes there is two same EEPROM on a single bus and the A0 bit is a page bit in BR24L04-W model. I'm not using it and I tried your advice but didn't edit the question. The result is same I'm getting the all ACK bits but when I reading the EEPROM is putting out all zeros. I've tried that on 4 different EEPROMs the result is same in every try. I'm confused. Thanks again.

Posted on March 16, 2017 at 14:41

No more ideas here.

Have you also tried a non-ROHM EEPROM?

JW

Posted on March 16, 2017 at 15:02

No I didn't because I've no other EEPROM. But I'll try with ADXL345 which is have I2C interface.

S.Ma
Principal
Posted on March 17, 2017 at 10:03

0690X00000606adQAA.png

So we assume that both eeprom have different pin A1/A2 settings. 0xA0-A1/A2-A3 (Write-Read address depending on the 2x256 bytes page) and 0xA4-A5/A6-A7 (2x256 byte page)

Consider before giving upto try adapting

https://community.st.com/0D50X00009XkW1qSAF

which links to I2C by GPIOs. Do the plumbing for your low level GPIO handling (this code works with various cores) and see if it works.

Posted on March 17, 2017 at 09:50

‌ can you look the edit please. Thanks.
Posted on March 17, 2017 at 10:29

Thanks

Centauris.Alpha

‌. Yes I've different slave addresses which are defined with `const uint8_t DEVICE[] = {0xA0, 0xA4};`

0690X00000606aYQAQ.png

0690X00000606XQQAY.png

Here are the device addresses and I'm first trying to with one EEPROM so the other one is not connected to the board. I want to send and am trying get datas without GPIO method. But if this is mandatory I'll check it. Thanks again.

Posted on March 31, 2017 at 15:31

Hi All,

I've solved the problem. There is some missing information in the BR24L04's datasheet. Address is not 16-bit so P0 is the page bit. I've though it is 'page reading or writing bit' but it is not, it is used to select first/second page of 8-bit addressable area. The device is automatically increasing the address while reading operation, there is no limit. In writing, just 16-byte could be written sequentially. In both situations, if the device sees the stop, it stops suddenly. I've changed the read function and now read has no problem. Thanks to everyone. Here is the read function, maybe help someone;

static int EEPROMRead(uint8_t dev, uint16_t addr, uint8_t *buf, uint16_t n)

{

 uint8_t addrL;

 int i;

 if (buf == NULL)

  return -1; // Buffer null

  I2C_ClearFlag(I2Cx, I2C_ISR_STOPF);

 I2C_ClearFlag(I2Cx, I2C_ISR_NACKF);

 

 /* Set the page bit */

 if (addr > (uint16_t)0x00FF)

  dev |= (PAGE_MASK);

 

 /* Check busy flag */

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -5; // Bus busy timeout

 }

 /*

    Configure the slave address, nbytes, reload,

    end mode and start stop generation

  */

 I2C_TransferHandling(I2Cx, dev, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while((I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) &&\

      (I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET))

 {

   if ((EEPROMTimeout--) == 0)

   return -4; // Start write timeout handling problem

 }

 addrL = (uint8_t)addr;

 

 /* Send register address high byte */

 I2C_SendData(I2Cx, addrL);

 EEPROMTimeout = I2Cx_TIMEOUT;

 while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET)

 {

   if ((EEPROMTimeout--) == 0)

   return -3; // Transmit timeout problem

 }

 if (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXE) == RESET)

  I2Cx->ISR |= I2C_ISR_TXE;

 I2C_TransferHandling(I2Cx, dev, n, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

 for (i = 0; i < n; i++)

 {

  /* Wait until RXNE flag is set */

  EEPROMTimeout = I2Cx_TIMEOUT;

  while(I2C_GetFlagStatus(I2Cx, I2C_ISR_RXNE) == RESET)

  {

    if ((EEPROMTimeout--) == 0)

    return -2; // Receive timeout problem

  }

  /* Read data from RXDR */

   buf[i] = I2C_ReceiveData(I2Cx);

 }

 return 0;

}