2017-03-09 03:10 AM
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.
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 #eepromSolved! Go to Solution.
2017-03-31 06:31 AM
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 nullI2C_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;
}2017-03-11 02:47 AM
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
2017-03-16 04:59 AM
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.2017-03-16 07:41 AM
No more ideas here.
Have you also tried a non-ROHM EEPROM?
JW
2017-03-16 08:02 AM
No I didn't because I've no other EEPROM. But I'll try with ADXL345 which is have I2C interface.
2017-03-17 02:03 AM
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
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.2017-03-17 02:50 AM
2017-03-17 03:29 AM
Thanks
Centauris.Alpha
. Yes I've different slave addresses which are defined with `const uint8_t DEVICE[] = {0xA0, 0xA4};`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.
2017-03-31 06:31 AM
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 nullI2C_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;
}