Работа со встроенной eeprom в микроконтроллерах на arduino

Введение

Доброго времени суток. Прошлая моя статья про параметры в EEPROM была, мягко говоря, немного недопонята. Видимо, я как-то криво описал цель и задачу которая решалась. Постараюсь в этот раз исправиться, описать более подробно суть решаемой проблемы и в этот раз расширим границы задачи.

А именно поговорим о том, как хранить параметры, которые необходимо писать в EEPROM постоянно.

Многим может показаться, что это очень специфическая проблема, но на самом деле множество устройств именно этим и занимаются — постоянно пишут в EEPROM. Счетчик воды, тепловычислитель, одометр, всяческие журналы действий пользователя и журналы, хранящие историю измерений, да просто любое устройство, которое хранит время своей работы.

Особенность таких параметров заключается в том, что их нельзя писать просто так в одно и то же место EEPROM, вы просто израсходуете все циклы записи EEPROM. Например, если, необходимо писать время работы один раз в 1 минуту, то нетрудно посчитать, что с EEPROM в 1 000 000 циклов записей, вы загубите его меньше чем за 2 года. А что такое 2 года, если обычное измерительное устройство имеет время поверки 3 и даже 5 лет.

Кроме того, не все EEPROM имеют 1 000 000 циклов записей, многие дешевые EEPROM все еще производятся по старым технологиям с количеством записей 100 000. А если учесть, что 1 000 000 циклов указывается только при идеальных условиях, а скажем при высоких температурах это число может снизиться вдвое, то ваша EEPROM способно оказаться самым ненадежным элементом уже в первый год работы устройства.

Поэтому давайте попробуем решить эту проблему, и сделать так, чтобы обращение к параметрам было столь же простым как в прошлой статье, но при этом EEPROM хватало бы на 30 лет, ну или на 100 (чисто теоретически).

Итак, в прошлой статье, я с трудом показал, как сделать, так, чтобы с параметрами в EEPROM можно было работать интуитивно понятно, не задумываясь, где они лежат и как осуществляется доступ к ним

Напомню:

Для начала проясню, для чего вообще нужно обращаться по отдельности к каждому параметру, этот момент был упущен в прошлой статье. Спасибо товарищам @Andy_Big и @HiSER за замечания.

Все очень просто, существует огромный пласт измерительных устройств, которые используют полевые протоколы такие как HART, FF или PF, где пользовательские команды очень атомарные. Например, в HART протоколе есть отдельные команды — запись единиц изменения, запись верхнего диапазона, запись времени демпфирования, калибровка нуля, запись адрес опроса и т.д. Каждая такая команда должна записать один параметр, при этом успеть подготовить ответ и ответить. Таких параметров может быть до 500 — 600, а в небольших устройствах их около 200.

Если использовать способ, который пользователь @HiSER- это будет означать, что для перезаписи одного параметра размером в 1 byte, я должен буду переписать всю EEPROM. А если алгоритм контроля целостности подразумевает хранение копии параметров, то для 200 параметров со средней длиной в 4 байта, мне нужно будет переписать 1600 байт EEPROM, а если параметров 500, то и все 4000.

Малопотребляющие устройства или устройства, питающиеся от от токовой петли 4-20мА должны потреблять, ну скажем 3 мА, и при этом они должны иметь еще достаточно энергии для питания модема полевого интерфейса, графического индикатора, да еще и BLE в придачу. Запись в EEPROM очень энергозатратная операция. В таких устройствах писать нужно мало и быстро, чтобы средний ток потребления был не высоким.

Очевидно, что необходимо, сделать так, чтобы микроконтроллер ел как можно меньше. Самый простой способ, это уменьшить частоту тактирования, скажем до 500 КГц, или 1 Мгц (Сразу оговорюсь, в надежных применениях использование режима низкого потребления запрещено, поэтому микроконтроллер все время должен работать на одной частоте). На такой частоте, простая передача 4000 байт по SPI займет около 70 мс, прибавим к этому задержку на сохранение данных в страницу (в среднем 7мс на страницу), обратное вычитывание, и вообще обработку запроса микроконтроллером и получим около 3 секунд, на то, чтобы записать один параметр.

Поэтому в таких устройствах лучше чтобы доступ к каждому параметру был отдельным, и обращение к ним должно быть индивидуальным. Их можно группировать в структуру по смыслу, или командам пользователя, но лучше, чтобы все они не занимали больше одной страницы, а их адреса были выравнены по границам страницы.

Но вернемся к нашей основной проблеме — мы хотим постоянно писать параметры.

Важные страницы

  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макро, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту (alex@alexgyver.ru)

Будущее за последовательной памятью?

Использование микросхем памяти с последовательным интерфейсом позволяет снизить количество сигнальных линий для организации обмена данными с устройством, обращающимся к памяти, использовать более компактные корпуса, занимающие меньшее место на печатной плате. Применение микросхем с последовательным интерфейсом позволяет создавать более компактные, экономичные и дешевые устройства. А широкий выбор устройств энергонезависимой памяти с последовательным интерфейсом компании Atmel с различным напряжением питания и временем выборки, а также наличие микросхем в различных типах корпусов позволяет разработчикам выбрать наиболее удобный вариант для использования в конечном приложении.

Серия DataFlash AT45

AT45 идеально подходят для хранения памяти программ, данных и для замены последовательных EEPROM (рис. 3). DataFlash AT45 поделена на страницы, блоки и сектора, что позволяет оптимизировать процесс стирания и защиты данных. Запись и чтение данных производится через два буфера SRAM, за счет которых ускоряется процесс обмена данными и обеспечивается возможность выполнения механизма «чтение–модификация–запись». Благодаря этому механизму данные во Flash, с точки зрения внешнего устройства, можно изменять побайтно (функция эмуляции EEPROM).

Рис. 3. Блок-схема AT45

С 1997 года было выпущено несколько ревизий микросхем с измененными характеристиками, буквенное обозначение ревизии (А, В, С, D) указывается в конце наименования микросхемы. В последней ревизии «D» предусмотрен 128-байтный регистр для хранения служебной информации. Этот регистр включает уникальное 64-байтное число для каждой микросхемы (Device ID) и 64 байта однократно программируемой памяти (ОТР) для записи информации пользователя. Улучшенная защита секторов памяти микросхемы позволяет защищать каждый сектор отдельно.

Благодаря функции lockdown, запрещающей модификацию любого набора секторов (ячейки памяти становятся в дальнейшем доступны только для чтения), разработчик может заблокировать изменение определенной области памяти, например, кода загрузчика, и больше не беспокоиться о случайных нарушениях кода.

К концу 2007 года планируется все микросхемы серии АТ45 выпускать серийно в ревизии «D», а предыдущие версии будут постепенно сниматься с производства. Микросхемы серии АТ45 обеспечивают не менее 100 000 циклов перезаписи на страницу (начиная с ревизии «С»).

Микросхемы DataFlash выпускаются с диапазоном питающих напряжений 2,7–3,6 В (5-вольтовые микросхемы сняты с производства в 2000 году). На данный момент микросхемы выпускаются в различных корпусных исполнениях (рис. 4). При разработке новых проектов следует учитывать, что производитель планирует в ближайшем будущем снять с производства корпуса с большим количеством выводов (SOIC28, TSOP, CBGA) и свести весь ассортимент корпусов микросхем к двум видам — широкий (209 ml) или узкий (150 ml) 8-выводный SOIC (выводы наружу), и 8-выводный MLF (6×8 мм) или CASON (6×5 мм) (выводы под корпусом). В «широком» SOIC будут выпускаться микросхемы емкостью от 1 до 128 Мбит, а в «узком» SOIC — микросхемы емкостью от 1 до 32 Мбит, что позволит в случае необходимости легко заменить в текущем проекте имеющуюся микросхему на микросхему с другим объемом памяти, не меняя разводку на плате. Причем «узкий» SOIC и MLF, а также «широкий» SOIC и CASON совместимы по геометрическому расположению выводов, то есть одну микросхему можно поменять на другую без изменения разводки на плате.

Рис. 4. Корпуса микросхем DataFlash

Параметры микросхем DataFlash сведены в таблице 1. Сегодня серийно выпускаются микросхемы емкостью от 1 до 64 Мбит. Микросхема емкостью 128 Мбит была в планах Atmel, но сроки ее выпуска отодвинуты на неопределенный срок.

Таблица 1. Параметры серии AT45 DataFlash

Микросхемы DataFlash также выпускаются в виде карточек формата MultiMediaCards (MMC) емкостью 2–8 Мбит, что позволяет использовать combo-SD/MMC-разъемы (рис. 5). Карточки в таком формате удобно использовать для переноса информации.

Рис. 5. Микросхемы AT45 DataFlash в формате карточек MMC

В помощь разработчикам для программирования микросхем DataFlash поставляется программный комплект DataFlash Software Suite (DFSS, разработка компании HCC Embedded). Комплект распространяется свободно для покупателей микросхем памяти Atmel. Для получения DFSS необходимо подписать лицензионное соглашение, бланк которого можно получить у дистрибьюторов Atmel. После одобрения соглашения Atmel высылает по электронной почте DFSS конечному клиенту.

В комплект DFSS входят:

  • базовые драйверы для всех функций DataFlash;
  • функции организации файловой системы FAT12/FAT16;
  • функции детектирования и коррекции ошибок;
  • функции обеспечения равномерного «износа» ячеек памяти и автоматической перезаписи страниц;
  • сжатие и распаковка данных.

Помимо этого бесплатного ПО также предлагаются программные продукты фирмы HCC-Embedded, информацию о которых можно посмотреть на web-сайте www.hcc-embedded.com.

Уменьшить частоту

Самый безболезненный способ решить проблему-это просто записывать данные реже. В некоторых случаях требования к системе это позволяют. Или можно записывать только при каких-либо больших изменениях. Однако, с записью, привязанной к событиям, помните о возможном сценарии, при котором значение будет постоянно колебаться, и вызовет поток событий, которые приведут к износу EEPROM. (Будет неплохо, если вы сможете определить, сколько раз производилась запись в EEPROM. Но это потребует счётчика, который будет храниться в EEPROM… при этом проблема превращается проблему износа счётчика.)

EECR – Регистр управления EEPROM (EEPROM Control Register)

  • Бит 7 – Res: зарезервированный бит.
    Этот бит зарезервирован для будущего использования и всегда будет
    считываться как 0 в ATtiny13A. Для совместимости с будущими устройствами AVR всегда записывайте этот бит в ноль. После прочтения замаскируйте этот бит.
  • Бит 6 – Res: зарезервированный бит.
    Этот бит зарезервирован для будущего использования и всегда будет
    считываться как 0 в ATtiny13A.
  • Биты 5 и 4 – EEPM: биты режима программирования EEPROM. Установка битов режима программирования EEPROM определяет, какое действие программирования будет выполняться при записи единицы в бит EEPE. Можно запрограммировать данные в одной атомарной операции (стереть старое значение и запрограммировать новое значение) или выполнить операции стирания и записи в двух разных операциях. Время программирования для различных режимов показано в таблице 5-1 (ниже). Если бит EEPE (см. ниже) установлен, то любая запись в EEPMn будет отклонена. Во время сброса биты EEPMn будут сброшены в значение 0b00, если EEPROM не занят программированием.
  • Бит 3 – EERIE: включить прерывание EEPROM (EEPROM Ready Interrupt Enable).
    Запись единицы в бит EERIE позволяет включить прерывания EEPROM,
    если установлен I-бит в регистре . Запись нуля в бит EERIE отключает прерывание. Флаг готовности прерывания EEPROM вызывает прерывание, когда энергонезависимая память готова для программирования.
  • Бит 2 – EEMPE: мастер включения программирования EEPROM (EEPROM Master Program Enable). Бит EEMPE определяет, будет ли запись единицы в бит EEPE иметь эффект или нет. Когда бит EEMPE установлен, установка бита EEPE в течение четырех тактов запрограммирует EEPROM по выбранному адресу. Если EEMPE равен нулю, установка EEPE не будет иметь никакого эффекта. Если EEMPE был установлен с помощью программного обеспечения, аппаратное обеспечение очищает бит (сбрасывает в ноль) после четырех тактов.
  • Бит 1 – EEPE: включение программирования (записи) EEPROM. Бит EEPE — это сигнал для EEPROM. Если бит EEPE установлен, то EEPROM будет запрограммирована согласно состоянию битов EEPMn. Бит EEMPE должен быть установлен, прежде чем логическая единица будет записана в EEPE, иначе запись EEPROM не произойдёт. Когда время доступа к записи истекло, бит EEPE очищается аппаратным обеспечением. После установки EEPE процессор останавливается на два такта, прежде чем будет выполнена следующая инструкция.
  • Бит 0 – EERE: включение чтения EEPROM. Бит EERE — разрешение чтения из EEPROM. Если в регистр EEARL записан правильный адрес, то бит EERE должен быть записан в единицу, чтобы вызвать чтение EEPROM. Доступ чтения из EEPROM принимает одну инструкцию, а запрошенные данные доступны немедленно. Когда EEPROM считывается, процессор останавливается на четыре такта до выполнения следующей инструкции. Пользователь должен опросить бит EEPE перед началом операции чтения. Если операция записи выполняется, невозможно ни прочитать EEPROM, ни изменить регистр EEARL.

На рисунках:

  • Сверху указаны номера битов регистра.
  • Слева надписи:
    • Адрес регистра.
    • Read/Write — это чтение/запись. Буква под битом говорит о том, какой доступ возможен к этому биту: R — только чтение, W — только запись, R/W — чтение и запись.
    • Начальное значение (Initial Value) — значение, которое изначально (по умолчанию) хранится в бите. Если Х — то значение может быть любым (не определено).

Таблица 5.1. Биты режимов EEPROM.

EECR Время программирования Операция
EEPM1 EEPM0
3,4 мс Стирание и запись за одну операцию (Атомарная операция)
1 1,8 мс Только стирание
1 1,8 мс Только запись
1 1 Зарезервировано для будущего использования

2Софт для работы с программатором CH341A

Программатор CH341A поставляется с программой, которая, к сожалению, давно прекратила своё развитие. Последняя версия программы 1.30 датируется 2009 годом. Программа имеет предельно простой и интуитивно понятный интерфейс, который мы подробней рассмотрим чуть далее.

Программное обеспечение программатора CH341A

Также существует альтернативное программное обеспечение (например, Программатор SPI, I2C, Microwire FLASH/EEPROM v1.4.0), которое, к сожалению, также не отличается дружелюбным интерфейсом и на сегодняшний день более не поддерживается.

Однако, со своей основной задачей программатор вполне успешно справляется даже со штатным программным обеспечением. В чём мы сейчас и убедимся.

Оперативная память и динамическая память

Главный недостаток статической памяти – большое количество элементов в каждой ячейке, прямо транслирующееся в высокую стоимость, а также в большие габариты. Для того, чтобы преодолеть этот недостаток (а на самом деле еще и огромные габариты повсеместно использовавшейся в шестидесятых и начале семидесятых памяти на магнитных сердечниках) была придумана динамическая память.

Схемы ячейки динамической и статической памяти

Намного более простая ячейка позволяет существенно увеличить количество памяти на кристалле. Уже самый первый серийный кристалл DRAM (Intel 1103) в 1970 году содержал 1024 бита, а современные чипы умещают уже 16 Гигабит! Это стало возможным благодаря постоянному прогрессу технологии производства, а именно разнообразным улучшениям конструкции интегрального конденсатора. Если в самых первых чипах использовалась просто МОП-емкость, крайне похожая по конструкции на транзистор, в современных чипах DRAM конденсатор для экономии площади располагается не горизонтально, а вертикально, под или над транзистором.

Условная схема прогресса технологии производства DRAM.

То, что технологический прогресс в области DRAM сосредоточен на конденсаторе, и обусловило обособление отрасли и появление компаний, специализирующихся на разработке памяти и больше ни на чем.

Серия M25Pxx последовательной Flash-памяти с секторным стиранием

Если рассмотреть различные виды микросхем последовательной долговременной памяти с высокой плотностью, то M25Pxx с тактовой частотой 25 MГц оказываются существенно быстрее, чем многие другие типы схем Flash-памяти с последовательной выборкой. Благодаря их высокой скорости, возможности последовательного считывания, экономичности, малого размера корпусов и небольшой стоимости, семейство последовательной Flash-памяти ST находит широкое применение в различного рода приложениях.

Высокоскоростное низковольтное семейство M25Pxx последовательно считывает и записывает данные по четырехпроводной SPI-совместимой шине с тактовой частотой до 25 MГц. Использование M25Pxx придает дополнительные возможности всем приложениям, требующих быстрой загрузки кода, типа дополнительных плат персонального компьютера, включая графические карты, SCSI и сетевые карты, привод жесткого диска и автомобильные радиоприемники.

Семейство последовательной Flash-памяти ST позволяет загружать в оперативную память 1 Мб за 43 мс при минимальном числе команд, что делает их удобными при использовании. Технические и программные средства защиты предохраняют хранимую информацию от перезаписи.

Для снижения потребляемой мощности эти микросхемы работают от одного источника питания от 2,7 В до 3,6 В и имеют режим пониженного энергопотребления с потребляемым током менее 1 мкА. Кроме того, четырехпроводной интерфейс значительно уменьшает число выводов устройства используемых для управления передачей данных по шине, что обеспечивает высокую интеграцию и меньшую стоимость по сравнению с другими подобными схемами. Микросхемы памяти серии M25Pxx выпускаются в широком и узком S08, LGA и MLP корпусах. Обобщенные данные о параметрах микросхем данной серии представлены в таблице 6.

Таблица 6. Последовательная Flash, шина SPI, высокоскоростная, секторное или полное стирание, 2,7…3,6 В (-V)

Размер Обозначение Описание Корпус
512 кб M25P05-AV 512 кб (x8), 25 МГц шина SPI, 2 сектора по 256 кб, 256 байт страница, последовательное чтение за 21 мс, 4 режима защиты записи SO8, MLP8
1 Мб M25P10-АV 1 Mб (x8), 25 МГц шина PSI, 4 сектора по 256 кб, 256 байт страница, последовательное чтение за 42 мс, 4 режима защиты записи SO8, MLP8
2 Мб M25P20-V 2 Mб (x8), 25 МГц, 4 сектора по 512 кб, 256 байт страница, последовательное чтение за 84 мс, 4 режима защиты записи SO8, MLP8
4 Мб M25PE40-V 4 Mб (x8), 25 МГц, 8 секторов по 512 кб, 256 байт страница, последовательное чтение за 168 мс, 4 режима защиты записи SO8, MLP8
8 Мб M25P80-V 8 Mб (x8), 20 МГц, 16 секторов по 512 кб, 256 байт страница, последовательное чтение за 335 мс, 4 режима защиты записи SO8W, MLP8
16 Mб M25P16-V * 16Mб (X8), 25 MГц, 32 сектора по 512 кб, 256 байт страница, последовательное чтение за 670 мс, 4 режима защиты записи LGA, MLP

* в разработке

Для оценки и программирования M25PXX имеется удобный программатор/считыватель (Рис. 5). Этот программатор подключается непосредственно к компьютеру и обеспечивает пользователю прямой доступ и управление последовательной Flash-памятью M25xxx в любой конфигурации.

Рис. 5. Программатор для М25Рхх

Arduino EEPROM запись, чтение данных

Для этого занятия нам потребуется:

плата Arduino Uno / Arduino Nano / Arduino Mega.

Скетч. Чтение Arduino EEPROM (read)

#include <EEPROM.h>  // импортируем библиотеку
int address;                     // переменная для хранения адреса
byte value;                      // переменная для хранения значения

void setup() {
   Serial.begin(9600);  // запускаем монитор порта
   Serial.println(EEPROM.length());  // выводим общее количество ячеек в памяти
   delay(3000);

   // перебираем в цикле все адреса в EEPROM памяти, пока все не переберем
   while (address < EEPROM.length()) {
      value = EEPROM.read(address);  // считываем значение байта
      Serial.print("Address: ");               // выводим полученные данные на монитор порта
      Serial.print(String(address));
      Serial.print(", value: ");
      Serial.println(String(value));
      address++;                                       // наращиваем адрес и повторяем операции
      delay(100);
   }
}
void loop() {
}

Пояснения к коду:

  1. функция позволяет узнать общее число ячеек в памяти. Если вы работаете с Nano ATmega168, то цикл закончится на 512 ячейке;
  2. если память не использовалась, то все значения в ячейках будут равны 255.

Скетч. Запись Arduino EEPROM (write)

#include <EEPROM.h>  // импортируем библиотеку
int address;                     // переменная для хранения адреса
byte value;                      // переменная для хранения значения

void setup() {
   Serial.begin(9600);  // запускаем монитор порта
   Serial.println(EEPROM.length());  // выводим общее количество ячеек в памяти
   EEPROM.write(0,100);                    // записываем значение 100 в ячейку с адресом 0
   delay(3000);

   // перебираем в цикле все адреса в EEPROM памяти, пока все не переберем
   while (address < EEPROM.length()) {
      value = EEPROM.read(address);  // считываем значение байта
      Serial.print("Address: ");               // выводим полученные данные на монитор порта
      Serial.print(String(address));
      Serial.print(", value: ");
      Serial.println(String(value));
      address++;                                       // наращиваем адрес и повторяем операции
      delay(100);
   }
}
void loop() {
}

Пояснения к коду:

  1. функция каждый раз перезаписывает данные в ячейке с адресом 0, что снижает жизненный цикл памяти, лучше использовать ;
  2. в следующих примерах не будем перебирать все ячейки в памяти, а запишем и прочитаем только несколько байт в энергонезависимой памяти Ардуино.


Пример работы предыдущей программы

Скетч. Перезапись в Arduino EEPROM (update)

#include <EEPROM.h>  // импортируем библиотеку

void setup() {
   Serial.begin(9600);  // запускаем монитор порта

   EEPROM.update(0,100);               // записываем значение 100 в ячейку с адресом 0
   delay(2000);

   Serial.println(EEPROM.read(0));  // выведет на монитор порта 100
   Serial.println(EEPROM);          // выведет на монитор порта 100
   }
}
void loop() {
}

Пояснения к коду:

  1. вывод данных из ячейки с адресом 0 выполняется с помощью разных функций;
  2. функции write/read/update позволяют работать только с типами данных byte и использовать эти функции для данных типа float или int уже нельзя. Для этого следует использовать put/get, которые мы рассмотрим далее.

Последовательная FLASH-память

Семейство высокоскоростной низковольтной последовательной Flash-памяти ST обладает четырехпроводным SPI-совместимым интерфейсом, что позволяет использовать Flash вместо последовательной EEPROM. Изготавливаемые по высоко износостойкой КМОП Flash-технологии, данные микросхемы обеспечивают, по крайней мере, 10000 циклов перепрограммирования на сектор с сохранностью данных свыше 20 лет.

В настоящее время доступны два дополняющих друг друга подсемейств последовательной Flash-памяти с возможностью стирания сектора или страницы:

  • Последовательная Flash-память с секторным стиранием и страничным программированием: серия M25Pxx (полностью в производстве)
  • Последовательная Flash-память с страничным стиранием и программированием: серия M45PExx (это новая серия, доступны образцы, развертывается полное производство).

Принцип действия

Принцип работы EEPROM основан на изменении и регистрации электрического заряда в изолированной области (кармане) полупроводниковой структуры.

Ячейка памяти EEPROM представляет собой транзистор, в котором затвор выполняется из поликристаллического кремния. Затем этот затвор окисляется и в результате он будет окружен оксидом кремния — диэлектриком с прекрасными изолирующими свойствами. Изменение заряда («запись» и «стирание») производится приложением между затвором и истоком большого потенциала, чтобы напряженность электрического поля в тонком диэлектрике между каналом транзистора и карманом оказалась достаточна для возникновения туннельного эффекта. Для усиления эффекта туннелирования электронов в карман при записи применяется небольшое ускорение электронов путём пропускания тока через канал полевого транзистора (явление инжекции горячих носителей). После снятия программирующего напряжения индуцированный заряд остаётся на плавающем затворе, и, следовательно, транзистор остаётся в проводящем состоянии. Заряд на его плавающем затворе может храниться десятки лет.Чтение выполняется полевым транзистором, для которого карман выполняет функцию затвора. Потенциал плавающего затвора изменяет пороговые характеристики транзистора, что и регистрируется цепями чтения.

Ранее подобная конструкция ячеек применялась в ПЗУ с ультрафиолетовым стиранием (EPROM).Сейчас особенностью классической ячейки EEPROM можно назвать наличие второго транзистора, который помогает управлять режимами записи и стирания. Стирание информации производится подачей на программирующий затвор напряжения, противоположного напряжению записи. В отличие от ПЗУ с ультрафиолетовым стиранием, время стирания информации в EEPROM памяти составляет около 10 мс. Структурная схема энергонезависимой памяти с электрическим стиранием не отличается от структурной схемы масочного ПЗУ. Единственное отличие — вместо плавкой перемычки используется описанная выше ячейка.

Некоторые реализации EEPROM выполнялись в виде одного трёхзатворного полевого транзистора (один затвор плавающий и два обычных). Эта конструкция снабжается элементами, которые позволяют ей работать в большом массиве таких же ячеек. Соединение выполняется в виде двумерной матрицы, в которой на пересечении столбцов и строк находится одна ячейка. Поскольку ячейка EEPROM имеет третий затвор, то, помимо подложки, к каждой ячейке подходят 3 проводника (один проводник столбцов и 2 проводника строк).

Упрощенная структурная схема EEPROM.

Команды библиотеки EEPROM.h Arduino

EEPROM.read(address)
Считывает один байт из EEPROM Arduino по адресу address
EEPROM.write(address, value)
Записывает один байт со значением value в EEPROM по адресу address
EEPROM.update(address, value)
Аналог функции write(), но новые данные в ячейку записываются только тогда, когда они отличаются от уже записанного. Использование данной функции позволяет продлить жизнь памяти EEPROM.
EEPROM.get(address, data)
Считывает из EEPROM Arduino любой тип данных по адресу address. При этом данные (data) могут быть любого типа, например, int или float.
EEPROM.put(address, data)
Записывает в EEPROM Arduino любой тип данных по адресу address. Функция записывает в ячейку только отличающиеся данные.
EEPROM[address]
Позволяет обращаться с байтами EEPROM Arduino как с массивом. Байты можно считывать и записывать.