Память данных eeprom

Память данных EEPROM

Что нужно для того, чтобы стать профессиональным разработчиком программ для микроконтроллеров и выйти на такой уровень мастерства, который позволит с лёгкостью найти и устроиться на работу с высокой зарплатой (средняя зарплата программиста микроконтроллеров по России на начало 2017 года составляет 80 000 рублей). Подробнее.

ATtiny13A содержит 64 байта памяти данных EEPROM. Эта память организована как отдельное пространство данных, в котором отдельные байты могут быть прочитаны и записаны. EEPROM имеет выносливость по крайней мере 100 000 циклов записи/стирания. Обмен данными между EEPROM и процессором описан далее, и основан на использовании Регистров Адреса EEPROM (EEPROM Address Registers), Регистра Данных EEPROM (EEPROM Data Register) и Регистра Управления EEPROM (EEPROM Control Register). Подробное описания последовательной загрузки данных в EEPROM описано в документации (в оригинале это страница 106, на моём сайте будет опубликовано позже).

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

  • EEAR — Регистр Адреса EEPROM (EEPROM Address Register)
  • EEDR — Регистр Данных EEPROM (EEPROM Data Register)
  • EECR — Регистр Управления EEPROM (EEPROM Control Register)

Если объём EEPROM превышает 256 байт (вообще в AVR эта память может иметь объём до 8 КБ в зависимости от модели МК), то вместо одного регистра адреса EEAR микроконтроллер имеет два регистра: EEARH и EEARL. Регистры доступа к EEPROM имеют следующие номера:

  • EEAR — 0x1E
  • EEARL — 0x1E
  • EEARH — 0x1F
  • EEDR — 0x1D
  • EECR — 0x1C

Как видите, регистры EEAR и EEARL имеют одинаковые номера. То есть в микроконтроллере, где объём EEPROM меньше 256 байт (в таком, как ATtiny13A), можно использовать только EEAR (он же EEARL).

Регистры EEAR (или EEARH и EEARL) работают только на запись. То есть в эти регистры вы можете только записать значение — адрес EEPROM, тем самым указав микроконтроллеру, с какой ячейкой памяти дальше надо будет работать.

Регистр EEDR работает как на запись, так и на чтение. При записи через этот регистр в EEPROM поступает записываемый байт. При чтениии через этот регистр микроконтроллер получает байт из EEPROM.

Регистр управления EECR устанавливает режим работы. Через него подаются команды чтения и записи EEPROM. Установка 0-го бита начинает чтение из EEPROM. Установка 1-го бита начинает запись в EEPROM. Для управляющих битов имеются соответствующие константы (биты регистра EECR будут описаны позже в других статьях, в оригинальной документации см. стр. 21).

Чтение и запись EEPROM

Регистры Адреса EEPROM (EEPROM Access Registers) доступны через область ввода-вывода.

Время доступа для записи в EEPROM приведено в таблице 5.1. Функция самоуправления временем, однако, позволяет программному обеспечению пользователя определить, когда можно записать следующий байт. Если код пользователя содержит инструкции по записи EEPROM, необходимо принять некоторые меры предосторожности. В источниках питания с мощными фильтрами, питание VCC при включении/выключении медленно повышается (понижается). По этой причине микроконтроллер в течение некоторого времени запускается на более низком напряжении, чем допустимо для используемой тактовой частоты. Дополнительные сведения о том, как избежать сложностей в таких случаях, см. ниже в разделе “Предотвращение повреждения EEPROM”.

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

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

Чтобы предотвратить непреднамеренную запись EEPROM, необходимо выполнить определенные правила записи. Подробности см. ниже в разделах “Атомарное программирование байта” и “Раздельное программирование байта”.

Когда выполняется чтение EEPROM, работа процессора приостанавливается на четыре такта, прежде чем следующая инструкция может быть выполнена. При записи EEPROM процессор останавливается на два такта перед выполнением следующей инструкции. То есть на время чтения/записи EEPROM процессор перестаёт выполнять команды и никакие другие инструкции не могут быть выполнены.

Атомарное программирование байта (Atomic Byte Programming)

Операция в общей области памяти называется атомарной, если она завершается в один шаг (не путать с тактом!) относительно других потоков (процессов), имеющих доступ к этой памяти. Во время выполнения такой операции над переменной, ни один поток не может наблюдать изменение наполовину завершенным. То есть пока атомарное обращение к памяти не будет завершено, доступ к этой памяти из другой операции невозможен. Атомарная загрузка гарантирует, что переменная будет загружена целиком в один момент времени.

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

Использование Атомарного Программирования байта (Atomic Byte Programming) — это самый простой режим. Записывая байт в EEPROM, пользователь должен записать адрес в регистр EEARL, а данные в регистр EEDR. Если биты EEPMn равны нулю, запись EEPE (в течение четырех тактов после записи EEMPE) вызовет операцию стирания/записи.

И стирание, и запись выполняются за одну операцию (полное время программирования показано в таблица 5-1 выше). Бит EEPE остается установленным до завершения операций стирания и записи. Пока микроконтроллер занят программированием, невозможно выполнять какие-либо другие операции с EEPROM.

Раздельное программирование байта (Split Byte Programming)

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

Стирание EEPROM

Для того, чтобы стереть байт, его адрес необходимо записать в регистр EEARL. Если биты EEPMn равны 0b01, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию стирания (время программирования указано выше в таблице 5-1). Бит EEPE остается установленным до завершения операции стирания. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

Запись EEPROM

Для записи ячейки памяти пользователь должен записать адрес в EEARL, а данные — в EEDR. Если биты EEPMn равны 0b10, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию записи (время программирования приведено выше в таблице 5-1). В EEPE бит остается установленным до тех пор, пока операция записи не завершится. Если записываемая ячейка не была очищена (стерта) перед записью, сохраненные данные должны считаться потерянными. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

Калибровка генератора тактовой частоты с помощью регистра калибровки (Oscillator Calibration Register) используется для настройки времени доступа к EEPROM. Убедитесь, что частота генератора соответствует требованиям, описанным в разделе “OSCCAL – Oscillator Calibration Register » (в оригинальной документации стр. 27, на моём сайте будет описана позже).

В следующих примерах кода показана одна функция на Ассемблере и C для стирания, записи или атомарной записи EEPROM. В примерах предполагается, что прерывания управляются (например, отключением прерываний глобально) таким образом, что во время выполнения этих функций прерывания не будут происходить.

См. также пример здесь.

В следующих примерах кода показаны функции на Ассемблере и C для чтения EEPROM. В примерах предполагается, что прерывания управляются таким образом, чтобы во время выполнения этих функций не возникало прерываний.

См. также пример здесь.

Предотвращение повреждения EEPROM

Если напряжение питания VCC слишком низкое (например, во время включения питания), данные в EEPROM можно повредить, потому что нарастание напряжения может оказаться слишком медленным для процессора и EEPROM, что не позволит им работать правильно. Эти вопросы такие же, как для систем, использующих память EEPROM, и должны быть применены такие же проектные решения.

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

Повреждения данных EEPROM можно легко избежать, следуя этому совету по проектированию:

Поддерживайте активный (низкий) сброс AVR во время недостаточного напряжения питания. Это можно сделать, включив внутренний детектор (Brown-out Detector (BOD)). Если уровень напряжения BOD не соответствует необходимому уровню напряжения, то можно использовать внешнюю цепь сброса, поддерживающую низкий уровень на выводе сброса и предохраняющую EEPROM от порчи. Если сброс происходит во время выполнения операции записи, операция записи будет завершена при условии, что напряжение питания достаточно.

ПРИМЕЧАНИЕ
Обычно все типовые схемы предусматривают такую защиту без дополнительного программирования (без использования BOD). Самое простое решение — подключить вход сброса микроконтроллера к плюсу источника питания через резистор, а к минусу — через конденсатор. При подаче питания на входе сброса будет низкий уровень, пока не зарядится конденсатор. То есть микроконтроллер не запустится, пока не зарядится конденсатор. Остаётся только рассчитать номиналы резистора и конденсатора, но это уже другая тема.

Arduino EEPROM энергонезависимая память

Ардуино предоставляет своим пользователям три типа встроенной памяти устройств и одна из них EEPROM – энергонезависимая память.

Описание памяти EEPROM

Arduino – это целое семейство различных устройств для создания электронных проектов. Микроконтроллеры очень удобны для использования, доступны к освоению даже новичку. Каждый микроконтроллер состоит из платы, программ для обеспечения работы, памяти. В этой статье будет рассмотрена энергонезависимая память, используемая в Arduino.

Ардуино предоставляет своим пользователям три типа встроенной памяти устройств: стационарное ОЗУ (оперативно-запоминающее устройство или SRAM — static random access memory) – необходимо для записи и хранения данных в процессе использования; флеш-карты – для сохранения уже записанных схем; EEPROM – для хранения и последующего использования данных.

На ОЗУ все данные стираются, как только происходит перезагрузка устройства либо отключается питание. Вторые две сохраняют всю информацию до перезаписи и позволяют извлекать ее при необходимости. Флеш-накопители достаточно распространены в настоящее время. Подробнее стоит рассмотреть память EEPROM.

Аббревиатура расшифровывается, как Electrically Erasable Programmable Read-Only Memory и в переводе на русский дословно означает – электрически стираемая программируемая память только для чтения. Производитель гарантирует сохранность информации на несколько десятилетий вперед после последнего отключения питания (обычно приводят срок в 20 лет, зависит от скорости снижения заряда устройства).

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

Объем памяти, в сравнении с современными носителями, очень небольшой и разный для различных микроконтроллеров. Например, для:

  • ATmega328 – 1кБ
  • ATmega168 и ATmega8 – 512 байт,
  • ATmega2560 и ATmega1280 – 4 кБ.

Так устроено потому, что каждый микроконтроллер предназначен для определенного объема задач, имеет разное количество выводов для подключения, соответственно, необходим разный объем памяти. При этом такого количества достаточно для обычно создаваемых проектов.

Для записи на EEPROM требуется значительное количество времени – около 3 мс. Если в момент записи отключается питание, данные не сохраняются вовсе либо могут быть записаны ошибочно. Требуется всегда дополнительно проверять внесенную информацию, чтобы избежать сбоев во время работы. Считывание данных происходит гораздо быстрее, ресурс памяти от этого не снижается.

Библиотека

Работа с памятью EEPROM осуществляется с помощью библиотеки, которая была специально создана для Ардуино. Главными являются способность к записи и чтению данных. Библиотека активируется командой #include EEPROM.h.

Далее используются простые команды:

  • для записи – EEPROM.write(address, data);
  • для чтения – EEPROM.read(address).

В данных скетчах: address – аргумент с данными ячейки, куда вносятся данные второго аргумента data; при считывании используется один аргумент address, который показывает, откуда следует читать информацию.

Функция Назначение
read(address) считывает 1 байт из EEPROM ; address – адрес, откуда считываются данные (ячейка, начиная с 0);
write(address, value) записывает в память значение value (1 байт, число от 0 до 255) по адресу address;
update(address, value) заменяет значение value по адресу address, если её старое содержимое отличается от нового;
get(address, data) считывает данные data указанного типа из памяти по адресу address;
put(address, data) записывает данные data указанного типа в память по адресу address;
EEPROM[address] позволяет использовать идентификатор «EEPROM» как массив, чтобы записывать данные в память и считывать их из памяти.
Читайте также  Компания iar представила демонстрационную плату серии kickstart для mcu lpc4088

Запись целых чисел

Запись целых чисел в энергонезависимую память EEPROM осуществить достаточно просто. Внесение чисел происходит с запуском функции EEPROM.write(). В скобках указываются необходимые данные. При этом числа от 0 до 255 и числа свыше 255 записываются по-разному. Первые вносятся просто – их объем занимает 1 байт, то есть одну ячейку. Для записи вторых необходимо использовать операторов highByte() высший байт и lowByte() низший байт.

Число делится на байты и записывается отдельно по ячейкам. Например, число 789 запишется в две ячейки: в первую пойдет множитель 3, а во вторую – недостающее значение. В итоге получается необходимое значение:

Для «воссоединения» большого целого числа применяется функция word(): int val = word(hi, low). Нужно читывать, что максимальное целое число для записи – 65536 (то есть 2 в степени 16). В ячейках, в которых еще не было иных записей, на мониторе будут стоять цифры 255 в каждой.

Запись чисел с плавающей запятой и строк

Числа с плавающей запятой и строк – это форма записи действительных чисел, где они представляются из мантиссы и показателя степени. Запись таких чисел в энергонезависимую память EEPROM производится с активацией функции EEPROM.put(), считывание, соответственно, – EEPROM.get().

При программировании числовые значения с плавающей запятой обозначаются, как float, стоит отметить, что это не команда, а именно число. Тип Char (символьный тип) – используется для обозначения строк. Процесс записи чисел на мониторе запускается при помощи setup(), считывание – с помощью loop().

В процессе на экране монитора могут появиться значения ovf, что значит «переполнено», и nan, что значит «отсутствует числовое значение». Это говорит о том, что записанная в ячейку информация не может быть воспроизведена, как число с плавающей точкой. Такой ситуации не возникнет, если достоверно знать, в какой ячейке какой тип информации записан.

Примеры проектов и скетчей

Пример №1

Скетч запишет до 16 символов с последовательного порта и в цикле выведет 16 символов из EEPROM. Благодаря Arduino IDE данные записываются в EEPROM и контролируется содержимое энергонезависимой памяти.

Пример №2

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

Пример №3

Запись в память два целых числа, чтение их из EEPROM и вывод в последовательный порт. Числа от 0 до 255 занимают 1 байт памяти, с помощью функции EEPROM.write() записываются в нужную ячейку. Для чисел больше 255 их нужно делить на байты с помощью highByte() и lowByte() и записывать каждый байт в свою ячейку. Максимальное число при этом – 65536 (или 2 16 ).

Пример №4

Запись чисел с плавающей запятой и строк — метод EEPROM.put(). Чтение – EEPROM.get().

Пример №5

Использование EEPROM как массива.

Работа с EEPROM

Как упоминалось ранее, ресурс памяти EEPROM ограничен. Для продления срока службы энергонезависимой памяти, вместо функции write() запись, лучше применять функцию update обновление. При этом перезапись ведется только для тех ячеек, где значение отличается от вновь записываемого.

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

Такая память на Ардуино стандартно хранит самое важное для работы контроллера и устройства. К примеру, если на такой базе создается регулятор температуры и исходные данные окажутся ошибочными, устройство будет работать «неадекватно» существующим условиям – сильно занижать или завышать температуру.

Существует несколько ситуаций, когда память EEPROM содержит неправильные данные:

  1. При первоначальной активации – еще не было ни одной записи.
  2. В момент неконтролируемого отключения питания – часть или все данные не запишутся или запишутся некорректно.
  3. После завершения возможных циклов перезаписи данных.

Чтобы избежать возникновения неприятных последствий, устройство можно запрограммировать на несколько вариантов действий: применить данные аварийного кода, отключить систему полностью, подать сигнал о неисправности, использовать заранее созданную копию или другие.

Для контроля целостности информации используют контрольный код системы. Он создается по образцу записи первоначальных данных и, при проверке, он вновь просчитывает данные. Если результат отличается – это ошибка. Самым распространенным вариантом такой проверки является контрольная сумма – выполняется обычная математическая операция по сложению всех значений ячеек.

Опытные программисты добавляют к этому коду дополнительное «исключающее ИЛИ», например, E5h. В случае если все значения равны нулю, а система по ошибке обнулила исходные данные – такая хитрость выявит ошибку.

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

Электроника для всех

Блог о электронике

AVR. Учебный Курс. Использование EEPROM

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

Чтобы что-то записать в EEPROM нужно в регистры адреса EEARH и EEARL (EEPROM Address Register) положить адрес ячейки в которую мы хотим записать байт. После чего нужно дождаться готовности памяти к записи – EEPROM довольно медленная штука. О готовности к записи нам доложит флаг EEWE (EEPROM Write Enable) регистра управления состоянием EECR, когда он будет равен 0, то память готова к следующей записи. Сам байт, который нужно записать, помещается в регистр EEDR (EEPROM Data Register). После чего взводится предохранительный бит EEMWE (EEPROM Master Write Enable), а затем, в течении четырех тактов, нужно установить бит EEWE и байт будет записан. Если в течении четырех тактов не успеешь выставить бит EEWE то предохранительный бит EEMWE сбросится и его придется выставлять снова. Это сделано для защиты от случайной записи в EEPROM память.

Чтение происходит примерно аналогичным образом, вначале ждем готовности памяти, потом заносим в регистры нужный адрес, а затем выставляем бит чтения EERE (EEPROM Read Enable) и следующей командой забираем из регистра данных EEDR наше число, сохраняя его в любом регистре общего назначения. Чтобы было понятно, я тебе набросал две процедурки – на чтение и на запись. Чтобы записать байт , нужно в регистры R16 и R17 занести младший и старший байт адреса нужной ячейки, а в регистр R21 байт который мы хотим записать. После чего вызвать процедуру записи. Аналогично и с чтением – в регистра R16 и R17 адрес, а в регистре R21 будет считанное значение.

Вот так выглядит запись в память:

… LDI R16,0 ; Загружаем адрес нулевой ячейки LDI R17,0 ; EEPROM LDI R21,45 ; и хотим записать в нее число 45 RCALL EEWrite ; вызываем процедуру записи.

LDI R16,0 ; Загружаем адрес нулевой ячейки LDI R17,0 ; EEPROM из которой хотим прочитать байт RCALL EERead ; вызываем процедуру чтения. После которой ; в R21 будет считанный байт.

Ну и, разумеется, сами процедуры чтения и записи

EEWrite: SBIC EECR,EEWE ; Ждем готовности памяти к записи. Крутимся в цикле RJMP EEWrite ; до тех пор пока не очистится флаг EEWE CLI ; Затем запрещаем прерывания. OUT EEARL,R16 ; Загружаем адрес нужной ячейки OUT EEARH,R17 ; старший и младший байт адреса OUT EEDR,R21 ; и сами данные, которые нам нужно загрузить SBI EECR,EEMWE ; взводим предохранитель SBI EECR,EEWE ; записываем байт SEI ; разрешаем прерывания RET ; возврат из процедуры EERead: SBIC EECR,EEWE ; Ждем пока будет завершена прошлая запись. RJMP EERead ; также крутимся в цикле. OUT EEARL, R16 ; загружаем адрес нужной ячейки OUT EEARH, R17 ; его старшие и младшие байты SBI EECR,EERE ; Выставляем бит чтения IN R21, EEDR ; Забираем из регистра данных результат RET

Да, при работе с EEPROM нужно в цикле ожидания готовности не забывать командой WDR сбрасывать Watch Dog Timer — специальный сторожевой таймер, отслеживающий зависание процессора. Если его не сбрасывать с нужной периодичностью, то он сбрасывает контроллер. Это, конечно, если Watch Dog используется. По дефолту он вырублен. Но помнить надо, иначе огребете трудно отслеживаемый глюк.

Впрочем, у EEPROM тоже есть свои прерывания. Это:

.ORG $01E RETI ; (EE_RDY) EEPROM Ready

И никто не помешает выбросить цикл ожидания и сделать массовую запись в ЕЕПРОМ на прерываниях! Аналогично как это сделано для USART. А если надо что то сохранить очень быстро, то можно и буферизированную с пробросом через RAM таким же образом запись заюзать. Т.е. сначала быстро сожрали в оперативку, а потом, неспеша, по прерываниям, загнать в EEPROM.

Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!

А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.

127 thoughts on “AVR. Учебный Курс. Использование EEPROM”

Спасибо! Отличная статья! Как раз сейчас нужно будет использовать EEPROM. Конечно можно прочитать даташит, что я обычно и делаю, но там все довольно разбросано, а здесь раз прочитал и в голове сложилась четкая структура.

P.S. Еще интересно, может у тебя уже был опыт по использованию карт памяти SD/MMC? Там же вроде элементарно по SPI с ними общаться.

До SPI пока руки не доходили. А так да, в планах. С этими карточками проблема составляет не SPI доступ, а FAT 🙂

Впринципе туда можно любую файловую систему зарулить. Хоть Fat, хоть Ext2fs, хоть вобще BSD’шную файловую систему.
А описаний и документации, как работать с этими системами хоть отбавляй!
Хочу использовать SD катрочку в автомобильном логгере (запись показаний датчиков системы впрыска)

Забыл написать, что у атмеловских контроллеров есть так называемая «мертвая зона» EEPROM-a. У 64й атмеги, например, это все адреса от 0x00 — 0x100. Так же была замечена тенденция (по крайней мере на атмегах), чем круче модель (ATMeag32->64->128), тем больше у нее мертвая зона EEPROM. Причем в документации, про нее нифига не написано и подбирать придется в ручную. Ах да, чем же она такая мертвая эта зона. А тем, что запись и чтение в ней происходят через раз, а то и не происходят вообще. Дрочится конечно можно, но лучше оставить эти 100 адресов на советси разработчиков и работать со стабильным ПЗУ.

Может это контроллеры бракованные были? Или может запись производилась без проверки готовности EEPROM’а?

Нет, контроллеры н бракованные и запись проводилась так как нужно, будь уверен.

День добрый!
Ребята, вы все занимаетесь электроникой, помогите решить задачу, пожалуйста.
Для вас это не составит труда, а человеку поможете.

Задание:
Разработать систему измерения частоты и скважности сигнала с ТТЛ – совместимыми уровнями и вывод результата на индикатор МТ-16S2х (частота – верхняя строка, скважность — нижняя). Диапазон измеряемых частот — 1÷1000 Гц. Абсолютный шаг измерения скважности – не менее 0,1 мс. Период накопления данных при измерении частоты – 1 секунда.
ядро м/п системы:
ATMEGA-8, ATTINY2313 (AVR)
Нужны:
расчетные параметры устройств (адреса, режимы работы и.т.д.),
принципиальную электрическую схему системы,
блок-схему программы, программу на языке ассемблера.

Помогите пожалуйста, я не понимаю в этом ничего. А вам может будет интересно.
Зарание спасибо.

Не, нам это не интересно уже. Если будут _конкретные_ вопросы, на которые можно будет дать четкий ответ, то задавай.

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

Читайте также  Датчик вибрации для охранного устройства

Я догадался.
Ну что я могу сказать. Вы, похоже, сильно ошиблись специальностью, мне вас искренне жаль. В таком случае ничем помочь не могу. Если кто из комментов откликнется, то может быть вам повезет.

Блин, парюсь уже часа 3 с этим EEPROM
В .ESEG объявил константы, так Студия не цапает их сама при эмуляции — пришлось вручную через меню указывать файл .epp. Ладно, вроде заработало.
Но!! В Протеусе никак не могу загрузить данные EEPROM. Уж и конвертер hex2bin скачал, .epp файл конвертнул в .bin, указал в настройках ATMega8 — Initial Contens of EEPROM этот файл. А нифига — смотрю в паузе на содержимое EEPROM — везде 0xFF
Помогите, плиз!

Хм… Помог сброс данных модели и последующий выбор .bin файла….
И все-таки протеус очень веселый….

З.Ы. Студия тоже не фонтан… Сменил в простеньком проекте мегу8 на мегу 32 — так студия перестала показывать состояние всех РВВ… Создал пустой проект, скопипастил код туда — все заработало 🙂 Чудеса просто…

А вот такой насущный вопрос:
Собираю схему электронного одометра. Надо будет хранить пробег включая сотни метров. Ясно, что возможность записи в EEPROM закончится очень быстро. Вопрос: 100,000 записей это для всей памяти либо для одной ячейки? Т.е. могу ли я записать в оду ячейку 100000 раз потом перейти к следующей и т.д. таким образом использовать EEPROM долгое время? Если нет, то какой выход в данной ситуации можно посоветовать?
Спасибо!

1 применить память типа FRAM от Ramtron у ней число циклов перезаписи такое, что скорей у твоей машины все молекулы сотрутся.

2 держать данные в памяти, а на епром сбрасывать раз в 10-15 минут.

И 100 000 это для каждой ячейки.

Почему фигня в еепром при включении питания пишется? бодлевел вроде поставил.

EEPROM и flash память

EEPROM — это энергонезавимая память с электрическим стиранием информации. Количество циклов записи-стирания в этих микросхемах достигает 1000000 раз. Заминающие ячейки в них, также как и в постоянных запоминающих устройствах с электрическим стиранием EPROM, реализуются на основе транзисторов с плавающим затвором. Внутреннее устройство этой запоминающей ячейки приведено на рисунке 1:


Рисунок 1. Запоминающая ячейка ПЗУ с электрическим стиранием (EEPROM)

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

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

Структурная схема энергонезависимой памяти с электрическим стиранием не отличается от структурной схемы масочного ПЗУ. Единственное отличие — вместо плавкой перемычки используется описанная выше ячейка. Ее упрощенная структурная схема приведена на рисунке 2.


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

В качестве примера микросхем EEPROM памяти можно назвать отечественные микросхемы 573РР3, 558РР3 и зарубежные микросхемы серий AT28с010, AT28с040 фирмы Atmel, HN58V1001 фирмы Hitachi Semiconductor, X28C010 фирмы Intersil Corporation. В EEPROM памяти чаще всего хранятся пользовательские данные в сотовых аппаратах, которые не должны стираться при выключении питания (например адресные книги), конфигурационная информация роутеров или сотовых аппаратов, реже эти микросхемы применяются в качестве конфигурационной памяти FPGA или хранения данных DSP. EEPROM изображаются на принципиальных схемах как показано на рисунке 3.


Рисунок 3. Условно-графическое обозначение электрически стираемого постоянного запоминающего устройства

Чтение информации из параллельной EEPROM памяти производится аналогично чтению из масочного ПЗУ. Сначала на шине адреса выставляется адрес считываемой ячейки памяти в двоичном коде A0. A9, затем подается сигнал чтения RD. Сигнал выбора кристалла CS обычно используется в качестве дополнительного адресного провода для обращения к микросхеме. Временные диаграммы сигналов на входах и выходах этого вида ПЗУ приведены на рисунке 4.


Рисунок 4. Временные диаграммы сигналов чтения информации из EEPROM памяти

На рисунке 5 приведен чертеж типового корпуса микросхемы параллельной EEPROM памяти.


Рисунок 5. Чертеж корпуса микросхемы параллельной EEPROM

Обычно данные, которые хранятся в EEPROM требуются достаточно редко. Время считывания при этом не критично. Поэтому в ряде случаев адрес и данные передаются в микросхему и обратно через последовательный порт. Это позволяет уменьшить габариты микросхем за счет уменьшения количества внешних выводов. При этом используются два вида последовательных портов — SPI порт и I2C порт (микросхемы 25сXX и 24cXX серий соответственно). Зарубежной серии 24cXX соответствует отечественная серия микросхем 558РРX.

Внутренняя схема микросхем серии 24сXX (например AT24C01) приведена на рисунке 6.


Рисунок 6. Внутренняя схема микросхемы AT24C01

Подобные микросхемы широко используются для сохранения настроек телевизоров, в качестве памяти plug and play в компьютерах и ноутбуках, конфигурационной памяти ПЛИС и сигнальных процессоров (DSP). Применение последовательной EEPROM памяти позволило значительно уменьшить стоимость данных устройств и увеличить удобство работы с ними. Пример расположения данной микросхемы на печатной плате карты памяти компьютера приведен на рисунке 7.


Рисунок 7. EEPROM на печатной плате карты памяти компьютера

На рисунке 8 приведена схема электронной карты с применением внешней EEPROM микросхемы.


Рисунок 8. Схема электронной карты с применением внешней EEPROM

На данной схеме микроконтроллер PIC16F84 осуществляет обмен данными с EEPROM памятью 24LC16B. В таких устройствах, как SIM-карта, уже не применяется внешняя микросхема памяти. В SIM-картах сотовых аппаратов используется внутренняя EEPROM память однокристального микроконтроллера. Это позволяет максимально снизить цену данного устройства.

Схема управления для электрически стираемых программируемых ПЗУ получилась сложная, поэтому наметилось два направления развития этих микросхем:

  1. ЕСППЗУ (EEPROM) — электрически стираемое программируемое постоянное запоминающее устройство
  2. FLASH-ПЗУ

FLASH — ПЗУ отличаются от ЭСППЗУ тем, что стирание производится не каждой ячейки отдельно, а всей микросхемы в целом или блока запоминающей матрицы этой микросхемы, как это делалось в РПЗУ.


Рисунок 9. Условно-графическое обозначение FLASH памяти

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


Рисунок 10. Временные диаграммы сигналов чтения информации из ПЗУ

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

В настоящее время широко распространилось название флешка. Это связано с внешними накопителями, предназначенными для переноски данных с одного компьютера на другой. В составе подобного устройства основной элемент, это FLASH-ПЗУ. Именно в него записывает данные, полученные по USB-интерфейсу контроллер FLASH памяти. Ну, и считывает, конечно. Фотография печатной платы USB флешки без корпуса приведена на рисунке 11.


Рисунок 11. Внутреннее устройство флешки

Именно микроконтроллер формирует сигналы, временные диаграммы которых показаны на рисунке 10, которые необходимы для работы микросхемы FLASH-ПЗУ.

Дата последнего обновления файла 04.08.2020

Понравился материал? Поделись с друзьями!

  1. Микушин А.В. Занимательно о микроконтроллерах. — СПб, БХВ-Петербург, 2006.
  2. Микушин А.В., Сажнев А.М., Сединин В.И. Цифровые устройства и микропроцессоры. — СПб, БХВ-Петербург, 2010.
  3. С.А. Майоров, В.В. Кириллов, А.А. Приблуда Введение в микро ЭВМ — Л., Машиностроение 1988
  4. Постоянные запоминающие устройства (http://naf-st.ru/)
  5. EEPROM Параллельные (http://www.chipfind.ru/)

Вместе со статьей «Постоянные запоминающие устройства (ПЗУ)» читают:

Как хранить данные в Arduino

У плат семейства плат Arduino есть несколько видов памяти. Во-первых, это статическое ОЗУ (оперативное запоминающее устройство), которая используется для хранения переменных в процессе выполнения программы. Во-вторых, это флеш-память, в которой хранятся написанные вами скетчи. И в-третьих, это EEPROM, которую можно использовать для постоянного хранения информации. Первый тип памяти – энергозависимый, он теряет всю информацию после перезагрузки Arduino. Вторые два типа памяти хранят информацию пока она не будет перезаписана новой, даже после отключения питания. Последний тип памяти – EEPROM – позволяет записывать данные, хранить их и считывать при необходимости. Эту память мы и рассмотрим сейчас.

Инструкция по использованию EEPROM в Arduino

1 Описание памяти EEPROM

EEPROM означает Electrically Erasable Programmable Read-Only Memory, т.е. электрически стираемое перепрограммируемое постоянное запоминающее устройство. Данные в этой памяти могут храниться десятки лет после отключения питания. Количество циклов перезаписи – порядка нескольких миллионов раз.

2 Библиотека EEPROM

Функция Назначение
read(address) считывает 1 байт из EEPROM ; address – адрес, откуда считываются данные (ячейка, начиная с 0);
write(address, value) записывает в память значение value (1 байт, число от 0 до 255) по адресу address;
update(address, value) заменяет значение value по адресу address, если её старое содержимое отличается от нового;
get(address, data) считывает данные data указанного типа из памяти по адресу address;
put(address, data) записывает данные data указанного типа в память по адресу address;
EEPROM[address] позволяет использовать идентификатор «EEPROM» как массив, чтобы записывать данные в память и считывать их из памяти.

Чтобы задействовать библиотеку в скетче, подключаем её директивой #include EEPROM.h.

3 Запись целых чисел в EEPROM

Если число больше, чем 255, то с помощью операторов highByte() и lowByte() его нужно делить на байты и записывать каждый байт в свою ячейку. Максимальное число при этом – 65536 (или 2 16 ).

Смотрите, монитор последовательного порта в ячейку 0 просто выводит число, меньшее, чем 255. В ячейках 1 и 2 хранится большое число 789. При этом ячейка 1 хранит множитель переполнения 3, а ячейка 2 – недостающее число 21 (т.е. 789 = 3×256 + 21).

Запись целых чисел в EEPROM Arduino

Чтобы заново «собрать» большое число, разобранное на байты, есть функция word(): int val = word(hi, low), где «hi» и «low» – это значения старшего и младшего байтов числа «val».

Во всех остальных ячейках, которые не были нами ни разу записаны, хранятся числа 255.

4 Запись чисел с плавающей запятой и строк в EEPROM

Для записи чисел с плавающей запятой и строк нужно использовать метод EEPROM.put(), а для чтения – EEPROM.get().

В процедуре setup() сначала запишем число с плавающей запятой «f». Затем сдвинемся на количество ячеек памяти, которое занимает тип «float», и запишем строку символов «char» ёмкостью 20 ячеек.

В процедуре loop() будем считывать все ячейки памяти и пытаться расшифровать их сначала как тип «float», а затем как тип «char», и выводить результат в последовательный порт.

Запись чисел с плавающей запятой в EEPROM Arduino

Видно, что значение в ячейках с 0 по 3 правильно определилось как число с плавающей точкой, а начиная с 4-ой – как строка.

Появляющиеся значения ovf (переполнение) и nan (не число) говорят о том, что значение в ячейке памяти по этому адресу не может быть корректно преобразовано в число с плавающей точкой. Если вы точно знаете, какого типа данные какие ячейки памяти занимают, то у вас не будет возникать проблем.

5 Работа с EEPROM как с массивом

Очень удобная возможность – обращение к ячейкам памяти как к элементам массива EEPROM. В данном скетче в процедуре setup() мы сначала запишем данные в 4 первых байта, а в процедуре loop() ежеминутно будем считывать данные из всех ячеек и выводить их в последовательный порт.

Работа с ячейками памяти EEPROM Arduino как с элементами массива

Работа с параметрами в EEPROM, как не износить память

Введение

Доброго времени суток. Прошлая моя статья про параметры в 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 секунд, на то, чтобы записать один параметр.

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

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

Как работать с EEPROM, чтобы не износить её

Те кто в курсе, можете пропустить этот раздел. Для остальных краткое, чисто мое дилетантское пояснение.

Как я уже сказал, число записей в EEPROM ограничено. Это число варьируется, и может быть 100 000, а может и 1 000 000. Так как же быть, если я хочу записать параметр 10 000 000 раз? И здесь мы должны понять, как внутри EEPROM устроен доступ к ячейкам памяти.

Итак, в общем случае вся EEPROM разделена на страницы. Страницы изолированы друг от друга. Страницы могут быть разного размера, для небольших EEPROM это, скажем, 16, 32 или 64 байта. Каждый раз когда вы записываете данные по какому-то адресу, EEPROM копирует все содержимое страницы, в которой находятся эти данные, во внутренний буфер. Затем меняет данные, которые вы передали в этом буфере и записывает весь буфер обратно. Т.е. по факту, если вы поменяли 1 байт в странице, вы переписываете всю страницу. Но из-за того, что страницы изолированы друг от друга остальные страницы не трогаются.

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

Да придется пожертвовать память, но как сделать по другому, я пока не знаю. Если есть какие мысли — пишите в комментариях.

Анализ требований и дизайн

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

Все требования можно сформулировать следующим образом:

Пользователь должен задать параметры EEPROM и время обновления параметра

На этапе компиляции нужно посчитать количество необходимых страниц (записей), чтобы уложиться в необходимое время работы EEPROM. Для этого нужно знать:

Количество циклов перезаписи

Время обновления параметра

Время жизни устройства

Хотя конечно, можно было дать возможность пользователю самому задавать количество записей, но что-то я хочу, чтобы все считалось само на этапе компиляции.

Каждая наша переменная(параметр) должна иметь уникальный начальный адрес в EEPROM

Мы не хотим сами руками задавать адрес, он должен высчитываться на этапе компиляции

При каждой следующей записи, адрес параметра должен изменяться, так, чтобы данные не писались по одному и тому же адресу

Это также должно делаться автоматически, но уже в runtime, никаких дополнительных действий в пользовательском коде мы делать не хотим.

Мы не хотим постоянно лазить в EEPROM, когда пользователь хочет прочитать параметр

Обычно EEPROM подключается через I2C и SPI, передача данных по этим интерфейсам тоже отнимает время, поэтому лучше кэшировать параметры в ОЗУ, и возвращать сразу копию из кеша.

При инициализации мы должны найти самую последнюю запись, её считать и закешировать.

За целостность должен отвечать драйвер.

За алгоритм проверки целостности отвечает драйвер, если при чтении он обнаружил несоответствие он должен вернуть ошибку. В нашем случае, пусть в качестве алгоритма целостности будет простое хранение копии параметра. Сам драйвер описывать не буду, но приведу пример кода.

Ну кажется это все наши хотелки. Как и в прошлой статье давайте прикинем дизайн класса, который будет описывать такой параметр и удовлетворять нашим требованиям:

Класс AntiWearNvData будет похож на, CachedNvData из прошлой статьи, но с небольшими изменениям. При каждой записи в EEPROM, нам нужно постоянно сдвигать адрес записи, поэтому необходимо хранить индекс, который будет указывать на номер текущей записи. Этот индекс должен записываться в EEPROM вместе с параметром, чтобы после инициализации можно было найти запись с самым большим индексом — эта запись и будет самой актуальной. Индекс можно сделать uint32_t точно хватит на 30 лет — даже при 100 000 циклах записи.

И вот наш класс:

Посмотрим на то, как реализуются наши требования таким дизайном.

Пользователь должен задать параметры EEPROM и время обновления параметр

В отличии от CachedNvData Из предыдущей статьи здесь появился параметр updateTime . На основе этого параметра можно посчитать сколько записей необходимо для того, чтобы уложиться в ожидаемое время жизни EEPROM. Сами параметры EEPROM можно задать в отдельном заголовочнике. Например, так:

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

При каждой следующей записи, адрес параметра должен изменяться, так, чтобы данные не писались по одному и тому же адресу

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

По нему мы будет рассчитывать следующий адрес записи

Для того, чтобы после выключения/включения датчика найти последнюю запись, считать её и проинициализировать значением по адресу этой записи кеширумое значение в ОЗУ.

Для этого заведена специальная структура tAntiWear . Её то мы и будем сохранять при вызове метода Set(. ) , который, кроме непосредственно записи, еще сдвигает индекс текущей записи на 1.

Давайте посмотрим как реализован метод расчета текущего адреса записи:

Мы не хотим постоянно лазить в EEPROM, когда пользователь хочет прочитать параметр

Метод Get() — крайне простой, он просто возвращает копию из ОЗУ

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

В общем-то и все класс готов, полный код класса:

Полный код класса

По аналогии с CachedNvData из прошлой статьи, все параметры должны быть зарегистрированы в едином списке, причем, в этом списке мы можем регистрировать как и CachedNvData , так и наши AntiWearNvData параметры.

Я немного переделал список, так как IAR компилятор все еще не понимает много фишек из С++17, и собственно теперь список принимает только типы, а не ссылки на параметры. Кроме того, теперь у него появились методы SetToDefault и Init . Первый нужен, например, чтобы сбросить все параметры в их начальное значение. А второй, чтобы проинициализировать кешируемые в ОЗУ копии.

Также в CachedNvData я добавил параметр recordSize и recordCounts = 1 . Чтобы расчет адреса параметра был унифицирован для разного типа параметров.

Результат

Собственно все, теперь мы можем регистрировать в списке любые параметры:

Замечу, что пользователю параметров нужно только объявить параметр и список, а вся портянка с кодом, до этого, пишется один раз. Используются параметры точно также как и CachedNvData .

Что произойдет в этом примере, когда мы будем писать 10,11,12. 15 в наш параметр. Каждый раз при записи, адрес параметра будет смещаться на размер параметра + размер индекса + размер копии параметра и индекса. Как только количество записей превысит максимальное количество, параметр начнет писаться с начального адреса.

На картинке снизу как раз видно, что число 15 с индексом 5 записалось с начального адреса, а 10 теперь нет вообще.

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

Вот и все, надеюсь в этой статье цель получилось пояснить более детально, спасибо за то, что прочитали до конца.