I'm really new about microcontroller and I want to ask if I want to read the values of three different sensors and store those values in succession in an I2C EEPROM, each value occupies 6 bytes in the address, how can I do that using the I2C bus? Especially I'm not sure about specifying high bytes and low bytes for each value. I found a sample code writing a value into EEPROM:
void eeprom_write(uint16_t data){ //Writes to the EEPROM
LL_I2C_GenerateStartCondition(I2C1); //START
while(!LL_I2C_IsActiveFlag_SB(I2C1));
LL_I2C_TransmitData8(I2C1, EEPROMADR); //CONTROL BYTE (ADDRESS + WRITE)
while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_TransmitData8(I2C1, 0x00); //ADDRESS HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, 0x00); //ADDRESS LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_GenerateStopCondition(I2C1); //STOP
}
but I don't know how to write the remaining two in series with that. Can someone help me, please? Also, I programmed on Keil software and used the C language. Thank you!
The EEPROM device has a range of internal addresses where data can be stored. Your eeprom_write
function uses the hardcoded address of 0x0000 such that every call to it will overwrite the previous data at address 0x0000. You should change the function prototype to pass in the address so you can write data throughout the EEPROM.
void eeprom_write_word_at_addr(uint16_t data, uint16_t addr){ //Writes to the EEPROM
LL_I2C_GenerateStartCondition(I2C1); //START
while(!LL_I2C_IsActiveFlag_SB(I2C1));
LL_I2C_TransmitData8(I2C1, EEPROMADR); //CONTROL BYTE (ADDRESS + WRITE)
while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_TransmitData8(I2C1, (char)(addr >> 8)); //ADDRESS HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(addr & 0x00FF)); //ADDRESS LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_GenerateStopCondition(I2C1); //STOP
}
Also your function writes a 2-byte data value but I think you want to write three 2-byte values. So you could call the above function three times and update the address each call. Or you could write another function that accepts all three values and writes them all in one I2C transfer. The EEPROM's internal address auto-increments for each write so you only need to specify the beginning address. (Read the EEPROM's datasheet to confirm about auto-increment and see if there is any paging restrictions.)
void eeprom_write_3words_at_addr(uint16_t data1, uint16_t data2, uint16_t data3, uint16_t addr){ //Writes to the EEPROM
LL_I2C_GenerateStartCondition(I2C1); //START
while(!LL_I2C_IsActiveFlag_SB(I2C1));
LL_I2C_TransmitData8(I2C1, EEPROMADR); //CONTROL BYTE (ADDRESS + WRITE)
while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_TransmitData8(I2C1, (char)(addr >> 8)); //ADDRESS HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(addr & 0x00FF)); //ADDRESS LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data1 >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data1 & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data2 >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data2 & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data3 >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data3 & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_GenerateStopCondition(I2C1); //STOP
}
Or if I'm wrong about three 2-byte data values then you could pass an array containing all the data to the function like this.
void eeprom_write_words_at_addr(uint16_t *data, int num_words, uint16_t addr){ //Writes to the EEPROM
LL_I2C_GenerateStartCondition(I2C1); //START
while(!LL_I2C_IsActiveFlag_SB(I2C1));
LL_I2C_TransmitData8(I2C1, EEPROMADR); //CONTROL BYTE (ADDRESS + WRITE)
while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_TransmitData8(I2C1, (char)(addr >> 8)); //ADDRESS HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(addr & 0x00FF)); //ADDRESS LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
for (int index = 0; index < num_words; ++index) {
LL_I2C_TransmitData8(I2C1, (char)(data[index] >> 8)); //DATA HIGH BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_TransmitData8(I2C1, (char)(data[index] & 0x00FF)); //DATA LOW BYTE
while(!LL_I2C_IsActiveFlag_TXE(I2C1));
}
LL_I2C_GenerateStopCondition(I2C1); //STOP
}
The high-byte/low-byte order (i.e., endianness) of the data is probably not important as long as the eeprom_read
function uses the same order. However, the byte order of the address is important because the I2C EEPROM device expects the high-byte of the address first. See the EEPROM device's datasheet for confirmation.