如何将串行数据写入 I2C EEPROM?

How to write serial data ino I2C EEPROM?

我对微控制器真的很陌生,我想问一下我是否要读取三个不同传感器的值并将这些值连续存储在I2C EEPROM中,每个值在地址中占用6个字节,如何才能我是用 I2C 总线做的吗?特别是我不确定为每个值指定高字节和低字节。 我找到了一个将值写入 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
  }

但我不知道如何将剩下的两个与它串联起来。有谁可以帮助我吗?另外,我在Keil软件上编程,用的是C语言。 谢谢!

EEPROM 设备具有可存储数据的内部地址范围。您的 eeprom_write 函数使用 0x0000 的硬编码地址,这样每次调用它都会覆盖地址 0x0000 处的先前数据。您应该更改函数原型以传入地址,以便您可以在整个 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
}

你的函数也写了一个 2 字节的数据值,但我认为你想写 three 2 字节的值。所以你可以调用上面的函数三次并在每次调用时更新地址。或者您可以编写另一个函数来接受所有三个值并将它们全部写入一个 I2C 传输中。 EEPROM 的内部地址会在每次写入时自动递增,因此您只需指定起始地址。 (阅读 EEPROM 的数据表以确认自动递增并查看是否有任何分页限制。)

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
}

或者,如果我对三个 2 字节数据值有误,那么您可以像这样将包含所有数据的数组传递给函数。

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
}

数据的high-byte/low-byte顺序(即endianness)可能并不重要,只要eeprom_read函数使用同样的顺序。但是,地址的字节顺序很重要,因为 I2C EEPROM 设备首先需要地址的高字节。请参阅 EEPROM 设备的数据表进行确认。