Пишите быстрее на AT24C32
Я использую чип AT24C32 EEPROM от ATmel. Я нашел код, который будет записывать и читать байты с чипа. Код пишет и читает байты правильно и без проблем.
Но мне приходится часто записывать несколько 8-байтовых значений (каждые 10-15 секунд). Я «обрезал» эти переменные до 48 бит (т.е. 6-байтовая переменная), и благодаря этому я ускорил сохранение, но оно все равно медленное.
Есть ли возможность ускорить процесс сохранения? Код ниже
void EEPROMClass::write48(int16_t address, uint64_t value)
{
uint8_t byteValue = (value & 0xFF);
write8(address, byteValue);
byteValue = ((value >> 8) & 0xFF);
write8(address + 1, byteValue);
byteValue = ((value >> 16) & 0xFF);
write8(address + 2, byteValue);
byteValue = ((value >> 24) & 0xFF);
write8(address + 3, byteValue);
byteValue = ((value >> 32) & 0xFF);
write8(address + 4, byteValue);
byteValue = ((value >> 40) & 0xFF);
write8(address + 5, byteValue);
}
void EEPROMClass::write8(int16_t const address, uint8_t const value)
{
Wire.beginTransmission(AT24C32);
Wire.write(highAddressByte(address));
Wire.write(lowAddressByte(address));
Wire.write(value);
delay(2);
Wire.endTransmission();
}
Требуется задержка
2 мс, иначе EEPROM запишет другое значение. Код имеет 4 «6-байтовых» переменных (всего 24 байта). Каждый байт составляет минимум 2 мс, поэтому общее время сохранения только «6-байтовых» переменных составляет 48 мс (округлить до 50 мс). Это слишком медленно для меня. Как ускорить функцию write
?
@Pararera, 👍2
Обсуждение3 ответа
Лучший ответ:
после записи значения в EEPROM и разрыва соединения I2C с помощью STOP, EEPROM переходит в режим самозаписи, чтобы записать то, что вы ему отправили, во внутреннюю память. (на самом деле вы не записываете значения в раздел памяти, вы записываете их в буфер, а затем внутренний контроллер записывает их в свой раздел памяти).
этот "режим самозаписи" занимает около 5 мс, и вы ничего не можете с этим поделать. но вы можете использовать «запись страницы» вместо записи байтов. эта 32-килобайтная модель имеет буфер страницы размером 32 байта. вы должны отправить все байты (если они меньше 32 байтов) сразу в одной транзакции I2C. на этот раз микросхема заполняет свой страничный буфер, а затем после STOP записывает все сразу в свою память. в вашем коде вы просто записываете один байт в свой буфер каждый раз в одной транзакции. например, отправить автобус только с одним пассажиром за раз.
помните, что в этом режиме вы устанавливаете только адрес первого байта. следующие байты автоматически размещаются в следующих адресах.
Существует ли способ «readpage» для более быстрого чтения?, @Pararera
И требуется ли задержка для чтения?, @Pararera
чтение не имеет ограничения «страницы». вы можете прочитать весь чип за одну транзакцию (он может даже перевернуть банк памяти и отправить его повторно). и ему также не нужна задержка (она такая же короткая, как микросекунды, поэтому ею можно пренебречь). @СильвиоКро, @Tirdad Sadri Nejad
Могу ли я записать 18 байт данных, начиная, например, с. адрес 24? Он пройдет 32 байта. Не испортит ли это данные? И сколько байтов я могу использовать? Все 32 байта для данных или 30 байт для данных и 2 байта для адреса?, @Pararera
32 байта - это все данные. адрес устанавливается так, как вы его задали ранее, но только для первого элемента. и помните, в режиме записи страницы вы пишете всю страницу. поскольку ваш чип имеет 32-байтовые страницы (128 * 32 байта = 4096 байтов = 32 Кбит), вы можете записать целых 32 байта на одной из страниц (1 ~ 128). для правильной записи первые 32 байта размещаются по адресам от 0 до 31, следующая партия — от 32 до 63… ., @Tirdad Sadri Nejad
и в случае, если вы запишете 18 байт на адрес 24 (вам не нужно отправлять ровно 32 байта, как я уже сказал, максимум 32 байта), ваши данные будут перезаписаны. байт0 -> 24 /байт1 -> 25 /байт2 -> 26 /байт3 -> 27 /байт4 -> 28 /байт5 -> 29 /байт6 -> 30 /байт7 -> 31 /byte8 -> 0 (все еще на первой странице. На следующую страницу не переходит) /byte9 -> 1 (все еще на первой странице. На следующую страницу не переходит), @Tirdad Sadri Nejad
Большое спасибо за помощь, @Pararera
В большинстве случаев наилучшая скорость достигается при использовании размера страницы, равного 32 байтам. Это займет больше 4 байт, но меньше 4х8 байт.
Вы можете проверить, работает ли запись одной страницы (32 байта) быстрее, чем 6-кратная запись одного байта.
Однако это зависит от того, сможете ли вы изменить свой дизайн, чтобы он записывал 32 байта за раз. Например, записав 60 секунд 4 раза по 8 байт (32 байта) на одну страницу, вместо записи каждые 15 секунд 8 байт. Это будет намного быстрее.
Я никогда не позволяю процессору ждать завершения процесса. Я вызываю процедуру сделать все, что можно сделать, поставить отметку, где я получил, и вернуться, чтобы сделать другие вещи. Следующее сканирование я беру с того места, где оставил, и продолжаю, если позволяют условия, если нет, я оставляю его для следующего сканирования. Я бы никогда не стал зацикливаться на времени ожидания. В вашем случае я бы открыл связь, отправил столько байтов, сколько смог, поставил отметку, как далеко я продвинулся, закрыл связь и вернулся. Следующие сканирования (когда данные передаются из буфера в EEPROM) я бы повторил тот же процесс для остальных данных. На любое сканирование я трачу несколько сотен микросекунд.
Это настолько старо, что я даже больше не использую Arduino. Но спасибо!, @Pararera
- Является ли использование malloc() и free() действительно плохой идеей для Arduino?
- Как читать и записывать EEPROM в ESP8266
- Какой реальный срок службы EEPROM?
- Как запомнить значения переменных после перезагрузки платы Arduino Uno R3
- Получить доступ к EEPROM ATtiny с помощью кода Arduino?
- Очистка EEPROM
- Как сохранить переменную с плавающей запятой в EEPROM
- Spiffs против Eeprom на esp8266
Какой тип скорости требуется вашему приложению? См. тесты; https://github.com/mikaelpatel/Arduino-Storage, @Mikael Patel