Работа с внешней EEPROM (24Cxx)

Тема в разделе "Глядите, что я сделал", создана пользователем CryNET, 28 янв 2016.

  1. vitmailru

    vitmailru Нуб

    Совершенно верно, пример работает неверно с AT24C04, цикл от 0-255 записывает в ячейки 0-255, дальше цикл от 256-512 перезыписывает те же ячейки 0-255. AT24C04 содержит две страницы, которые переключаются битом A0 (адреса 0x50 и 0x51)
    "The 4K EEPROM only uses the A2 and A1 device address bits with the third bit being a memory page address bit. The two device address bits must compare to their corresponding hard-wired input pins. The A0 pin is no connect. The 8K EEPROM only uses the A2 device address bit with the next 2 bits being for memory page addressing. The A2 bit must compare to its corresponding hard-wired input pin. The A1 and A0 pins are no connect. The 16K does not use any device address bits but instead the 3 bits are used for memory page addressing. These page addressing bits on the 4K, 8K and 16K devices should be considered the most significant bits of the data word address which follows. The A0, A1 and A2 pins are no connect."
     
  2. vitmailru

    vitmailru Нуб

    AT24C01A/02/04/08/16 адресуются 8-битным адресом и переключением страниц с помощью device address
    AT24C32-AT24C512 16-битным адресом:
    запись байта:
    Код (C++):
      Wire.beginTransmission(eeprom_device_address);
      Wire.write((int)(eeprom_address >> 8));   // MSB
      Wire.write((int)(eeprom_address & 0xFF)); // LSB
      Wire.write(value);
      Wire.endTransmission();
      delay(10);
    чтение байта:
    Код (C++):
      Wire.beginTransmission(eeprom_device_address);
      Wire.write((int)(eeprom_address >> 8));   // MSB
      Wire.write((int)(eeprom_address & 0xFF)); // LSB
      Wire.endTransmission();
      Wire.requestFrom(eeprom_device_address, (byte)1);
      return Wire.available() ? Wire.read() : 0xFF;
     
  3. vitmailru

    vitmailru Нуб

    Автор, исправьте пример, неправильно читать 512 байт адресуя их 8-битным адресом, у которого диапазон 0-255. Вот как правильно читать и записывать AT24C04
    запись
    Код (C++):
    #define DEVICE1_PAGE1 0x50
    #define DEVICE1_PAGE2 0x51
    for (int i = 0; i < 255; i++) {
      EEPROM_WriteByte(DEVICE1_PAGE1, i, 0xAB);
    }
    for (int i = 0; i < 255; i++) {
      EEPROM_WriteByte(DEVICE1_PAGE2, i, 0xAC);
    }
    чтение
    Код (C++):
    #define DEVICE1_PAGE1 0x50
    #define DEVICE1_PAGE2 0x51
    for (int i = 0; i < 255; i++) {
      Serial.print(EEPROM_ReadByte(DEVICE1_PAGE1, i), HEX);
      Serial.print(" ");
      val++;
      if(val >= 8){ val=0; Serial.println(); }
    }
    for (int i = 0; i < 255; i++) {
      Serial.print(EEPROM_ReadByte(DEVICE1_PAGE2, i), HEX);
      Serial.print(" ");
      val++;
      if(val >= 8){ val=0; Serial.println(); }
    }
     
  4. sany70

    sany70 Нуб

    попробовал переделать код для записи long, что то не получилось

    Код (C++):
    #define EEPuint32_1 50   // 1-й байт
    #define EEPuint32_2 51   // 2-й байт
    #define EEPuint32_3 52   // 3-й байт
    #define EEPuint32_4 53   // 4-й байт
     
  5. sany70

    sany70 Нуб

    запись
    Код (C++):
    void eep_write_uint32 (uint32_t x) {
      Wire1.beginTransmission(80);    // что это я не знаю
      Wire1.write((int)EEPuint32_1);  // адрес еепром для 1-го адреса
      Wire1.write((int)EEPuint32_2);  // адрес еепром для 2-го адреса
      Wire1.write((int)EEPuint32_3);  // адрес еепром для 3-го адреса
      Wire1.write((int)EEPuint32_4);  // адрес еепром для 4-го адреса
      Wire1.write(x & 0xFF);          // сохраняем 1-й байт
      Wire1.write((x >> 8)&0xFF);     // сохраняем 2-й байт
      Wire1.write((x >> 16)&0xFF);    // сохраняем 3-й байт
      Wire1.write(x >> 24);           // сохраняем 4-й байт
      Wire1.endTransmission();
    }
     
  6. sany70

    sany70 Нуб

    чтение
    Код (C++):
    uint32_t eep_read_uint32 (void) {
      byte x1, x2, x3, x4;
      Wire1.beginTransmission(80);    // что это я не знаю
      Wire1.write((int)EEPuint32_4);  // адрес еепром для 4-го адреса
      Wire1.write((int)EEPuint32_3);  // адрес еепром для 3-го адреса
      Wire1.write((int)EEPuint32_2);  // адрес еепром для 2-го адреса
      Wire1.write((int)EEPuint32_1);  // адрес еепром для 1-го адреса
      Wire1.endTransmission();
      Wire1.requestFrom(80, 4);
      if (Wire1.available()) x4 = Wire1.read();
      if (Wire1.available()) x3 = Wire1.read();
      if (Wire1.available()) x2 = Wire1.read();
      if (Wire1.available()) x1 = Wire1.read();

      return ((x4 << 24) + (x3 << 16) + (x2 << 8) + (x1));
    }
     
  7. sany70

    sany70 Нуб

    поправте пожалуйста, люди добрые
     
  8. vitmailru

    vitmailru Нуб

    Вы мои примеры внимательно смотрели? Где там передача 4-х байт адреса и запись-чтение 4-х байт данных? Где логика непонятно..
    В AT24C01A/02/04/08/16 - передача байта адреса, чтение/запись байта данных
    AT24C32-AT24C512 - передача 2-х байт адреса, чтение байта данных
    Для чтения 4-х байт вызываем 4 раза функцию чтения байта, увеличивая адрес на 1
    Вот если бы разобрались что это, то все бы получилось) Открывается транзакция чтения-записи, туда передается адрес I2C устройства
     
  9. sany70

    sany70 Нуб

    вот я и пытаюсь разобраться, всего то 3-4 месяца учусь программировать. до этого ардуино только на картинке и видел. вот и приходиться за помощью обращаться
     
  10. NAMi

    NAMi Нуб

    Код (C++):

    #define EEPROM_I2C_ADDRESS 0x50                                                  // Адрес внешнего EEPROM на шине I2C банк 0

    // ----------------------------------Функции по работе с внешним EEPROM -------------------------
    void EEPROM_WriteByte(byte Address, uint32_t data, byte range = 1) {  // Запись в EEPROM по адресу Address одного числа data с типом range
      byte x[4];
      if (range > 4) range = 4;
      x[0] = data & 0xFF;                      // Выделяем из числа data 1-й байт
      x[1] = (data >> 8)&0xFF;                 // Выделяем из числа data 2-й байт
      x[2] = (data >> 16)&0xFF;                // Выделяем из числа data 3-й байт
      x[3] = data >> 24;                       // Выделяем из числа data 4-й байт

      for (byte i = 0; i < range; i++) {
        Wire.beginTransmission(EEPROM_I2C_ADDRESS + i);
        Wire.write(Address);
        Wire.write(x[i]);
        Wire.endTransmission();
        delay(5);                                                               // В Datasheet описана задержка записи в 5мс
      }
    }
    //
    uint32_t EEPROM_ReadByte(byte Address, byte range = 1) {   // Чтение из EEPROM по адресу Address одного числа data с типом range
      uint32_t rdata = 0;
      for (byte i = 0; i < range; i++) {
        Wire.beginTransmission(EEPROM_I2C_ADDRESS + i);
        Wire.write(Address);
        Wire.endTransmission();
        Wire.requestFrom(EEPROM_I2C_ADDRESS + i, 1);
        if (Wire.available()) rdata += Wire.read() << (8 * i);
      }
      return rdata;
    }
    setup {
      uint32_t a = 123456;                             // 1E240 HEX
      Serial.print(a, HEX);
      EEPROM_WriteByte(0, a, 3);               //  Для этого числа достаточно 3-х байт
      Serial.print(" - ");
      Serial.println(EEPROM_ReadByte(0, 3), HEX);
      Serial.println();
    }
    //                 Результат:
    //               1E240 - 1E240
     
    Видимо это имелось ввиду. Мне тут для одного проекта понадобилось. Пришлось доработать Вашу мысль.
    Данные записываются "вертикально". Для 24с08 4 слоя, что позволяет хранить 256 чисел c разрядами от 8 до 32 бит особо не парясь по поводу высчитывания их начального адреса. Не экономно конечно.
     
    Последнее редактирование: 9 апр 2023